diff --git a/DEPS b/DEPS
index 41282367..9335b273 100644
--- a/DEPS
+++ b/DEPS
@@ -234,30 +234,30 @@
   # 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': 'bfafc430e850f5d0fab75a6eb5000606399ec268',
+  'skia_revision': 'c3db55663e5a38834a7eb65e39262db4d53d3e8c',
   # 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': 'a299e86f9feb9075105d7a7da4c40bd6f47c8faa',
+  'v8_revision': 'f7bd3615625263b36d3809b12dc6c3fb22fc53d6',
   # 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': 'ff89ba1b2503b39a49f53a12f46b97d50bca67db',
+  'angle_revision': 'd781ef09f664c20dd60ddcbe08ff24f4082f5f2c',
   # 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': '6e23c082b73a952d36c0cdb2f33f597166674f6d',
+  'swiftshader_revision': '9e727fadeb6656279ad51514b7f9067b8246d3e0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '31883270b7eea64726d4e233c83333bc88c72c27',
+  'pdfium_revision': '64a3691918bca26c4d233c8c897d926a39e4a8b7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
   #
   # Note this revision should be updated with
   # third_party/boringssl/roll_boringssl.py, not roll-dep.
-  'boringssl_revision': '69030a0ceabfe69c58cb2b83d9d4852333e3d0c2',
+  'boringssl_revision': '3a667d10e94186fd503966f5638e134fe9fb4080',
   # 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.
@@ -277,11 +277,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': '5ea7f18df797eb055c2b0efcb0637a82ca0eba84',
+  'nacl_revision': 'a90ea5be6142bb492ca9bb42ba099fbb56832384',
   # 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': '81912a1385e8fc7694eda820221e15745cdcada4',
+  'freetype_revision': '3cabd142ce42627a7e4410ce62616e5c4b91dc6e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -301,7 +301,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': '8a112e2bdf2b5839f07c820e255d78c835b0fd62',
+  'catapult_revision': '7ae3bc476654dd8161245fd5c42ae7aae3d010dc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -309,7 +309,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': '7b0a00ed9ee000df7c439435f0b9c392fab19e95',
+  'devtools_frontend_revision': '940c740d4eff9e79792059b87a0d93606c2124db',
   # 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.
@@ -349,11 +349,11 @@
   # 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': '28b0f94466789753ccc7c947ff38ef83a1b1de2c',
+  'dawn_revision': '0e9be588dac74f2dbec4b28904edd9d4404c8762',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': 'f551a2617507d6b98fbc2d60040658bcc6103457',
+  'quiche_revision': '2179330e447ac1cc3c51ce425d1e182760e2bb62',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -603,7 +603,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'ba753073ba67f0f83eaabe77ca30a901108aedd4',
+    'url': Var('chromium_git') + '/website.git' + '@' + '2d3d2506eb24119e5d6e4630658f5de665991972',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -791,7 +791,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '5_6hGqfW9hh3pWzd73P3qsKKKFcswNcKOHp0z_Xen94C',
+          'version': 'jXiiROMn0WffhrxtV5WAwhgkPccRtz7S0sTKt5pboZsC',
       },
     ],
     'condition': 'checkout_android',
@@ -1025,12 +1025,12 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '96bec379fd500dc064ceeb7c76e47208052947ab',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'eddfad34242e54fe5441469b80f643a5ba766dc0',
       'condition': 'checkout_linux',
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b6c1ed40d5d89f22a1ecee39acb33de3cf8158a8',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a29f589a15b7f80edd3d0bbe4f3a2dbb1120316c',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1413,7 +1413,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '715528ea109f8b98cecd82b9ebbad27d8b19a79d',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd5cb19a57dc7ffbdef44cae5fd34f1875376e051',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1491,7 +1491,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'BsMGVIB-SMSFb0qDOwUoX0kok6z1XZdfmi4kKMOPrWYC'
+              'version': 'RGchQ75eBrFQJRPQJMv5DT7uzlwr_ttfbGI2Kqlzw0wC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1595,7 +1595,7 @@
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '62d7d0c928c9a040dce96aa2f16c00e7e67d59cb',
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@8e41c1d91f9d2f0a26fc5f31e8e9684898be2769',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@40b07bc7873c9c4c3f23389ad9da5270179c3f61',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '5e49f57a6e71a026a54eb42e366de09a4142d24e',
@@ -1634,7 +1634,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '5e8ac4959f931fcffb7d0d97b82b22ba0db6258e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f002e2fc905947ff050277fe4642c8502b4011de',
+    Var('webrtc_git') + '/src.git' + '@' + 'f05f2823b3a5ee96fc194d9a44f7a0f518a70cef',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1692,7 +1692,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ab50507898a4085ebc173006b1fcb28af16b72ce',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@38dc45caacb9ae20cd64e3bd759f8d42ff08480f',
     'condition': 'checkout_src_internal',
   },
 
@@ -3382,7 +3382,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib',
-              'version': 'version:2@1.5.31.cr0',
+              'version': 'version:2@1.6.0.cr0',
           },
       ],
       'condition': 'checkout_android',
@@ -3393,7 +3393,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common',
-              'version': 'version:2@1.5.31.cr0',
+              'version': 'version:2@1.6.0.cr0',
           },
       ],
       'condition': 'checkout_android',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index bc7788d1..3a1cc75 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -1221,6 +1221,11 @@
   return input_api.os_path.splitext(file_path)[1] == ".proto"
 
 
+def _IsXmlOrGrdFile(input_api, file_path):
+  ext = input_api.os_path.splitext(file_path)[1]
+  return ext in ('.grd', '.xml')
+
+
 def CheckNoUpstreamDepsOnClank(input_api, output_api):
   """Prevent additions of dependencies from the upstream repo on //clank."""
   # clank can depend on clank
@@ -1801,6 +1806,15 @@
   change. Breaking - rules is an error, breaking ! rules is a
   warning.
   """
+  # Return early if no relevant file types were modified.
+  for f in input_api.AffectedFiles():
+    path = f.LocalPath()
+    if (_IsCPlusPlusFile(input_api, path) or _IsProtoFile(input_api, path) or
+        _IsJavaFile(input_api, path)):
+      break
+  else:
+    return []
+
   import sys
   # We need to wait until we have an input_api object and use this
   # roundabout construct to import checkdeps because this file is
@@ -2633,6 +2647,12 @@
 
 def CheckJavaStyle(input_api, output_api):
   """Runs checkstyle on changed java files and returns errors if any exist."""
+
+  # Return early if no java files were modified.
+  if not any(_IsJavaFile(input_api, f.LocalPath()) for f in
+             input_api.AffectedFiles()):
+    return []
+
   import sys
   original_sys_path = sys.path
   try:
@@ -2989,6 +3009,11 @@
      //build/OWNERS.setnoparent (see also
      //docs/code_reviews.md#owners-files-details)
   """
+  # Return early if no OWNERS files were modified.
+  if not any(f.LocalPath().endswith('OWNERS') for f in
+             input_api.AffectedFiles(include_deletes=False)):
+    return []
+
   errors = []
 
   allowed_owners_files_file = 'build/OWNERS.setnoparent'
@@ -3419,6 +3444,12 @@
 
 def _CheckAndroidXmlStyle(input_api, output_api, is_check_on_upload):
   """Checks Android XML styles """
+
+  # Return early if no relevant files were modified.
+  if not any(_IsXmlOrGrdFile(input_api, f.LocalPath()) for f in
+             input_api.AffectedFiles(include_deletes=False)):
+    return []
+
   import sys
   original_sys_path = sys.path
   try:
@@ -3535,9 +3566,14 @@
   """Checks if a .pydeps file needs to be regenerated."""
   # This check is for Python dependency lists (.pydeps files), and involves
   # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It
-  # doesn't work on Windows and Mac, so skip it on other platforms.
+  # doesn't work on Windows and Mac, so skip it on other platforms and skip if
+  # no pydeps files are affected.
   if not input_api.platform.startswith('linux'):
     return []
+  if not any(f.LocalPath().endswith('.pydeps') for f in input_api.AffectedFiles(
+             include_deletes=True)):
+    return []
+
   is_android = _ParseGclientArgs().get('checkout_android', 'false') == 'true'
   pydeps_to_check = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
   results = []
@@ -5166,6 +5202,10 @@
   changed_mojoms = input_api.AffectedFiles(
       include_deletes=True,
       file_filter=lambda f: f.LocalPath().endswith(('.mojom')))
+
+  if not changed_mojoms:
+    return []
+
   delta = []
   for mojom in changed_mojoms:
     old_contents = ''.join(mojom.OldContents()) or None
diff --git a/WATCHLISTS b/WATCHLISTS
index cf544d9..3731d71d 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2823,7 +2823,9 @@
     'tracing': ['tracing+reviews@chromium.org',
                 'wfh+watch@chromium.org',
                 'spang+watch@chromium.org'],
-    'traffic_annotation': ['nicolaso+watch@chromium.org'],
+    'traffic_annotation': ['nicolaso+watch@chromium.org',
+                           'ramyagopalan+watch@google.com',
+			   'jorgelo+watch@chromium.org'],
     'translate': ['translate-reviews@chromium.org'],
     'turtledove': ['taymon@google.com'],
     'ui_compositor': ['cc-bugs@chromium.org'],
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index f0365a6e..b1691b3 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -521,6 +521,12 @@
   // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html,
   // defer to the Android system.
   context_params->initial_ssl_config->symantec_enforcement_disabled = true;
+  // Do not enforce Legacy TLS removal if support is still enabled.
+  if (base::FeatureList::IsEnabled(
+          android_webview::features::kWebViewLegacyTlsSupport)) {
+    context_params->initial_ssl_config->version_min =
+        network::mojom::SSLVersion::kTLS1;
+  }
 
   // WebView does not currently support Certificate Transparency
   // (http://crbug.com/921750).
diff --git a/android_webview/browser/aw_browser_context_unittest.cc b/android_webview/browser/aw_browser_context_unittest.cc
index f3a33ba..d301b28 100644
--- a/android_webview/browser/aw_browser_context_unittest.cc
+++ b/android_webview/browser/aw_browser_context_unittest.cc
@@ -6,7 +6,9 @@
 #include "android_webview/browser/aw_browser_process.h"
 #include "android_webview/browser/aw_feature_list_creator.h"
 #include "android_webview/browser/network_service/aw_network_change_notifier_factory.h"
+#include "android_webview/common/aw_features.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_content_client_initializer.h"
@@ -80,4 +82,35 @@
       network_context_params.initial_ssl_config->sha1_local_anchors_enabled);
 }
 
+// Tests that TLS 1.0/1.1 is still allowed for WebView by default.
+TEST_F(AwBrowserContextTest, LegacyTLSVersionsAllowed) {
+  AwBrowserContext context;
+  network::mojom::NetworkContextParams network_context_params;
+  cert_verifier::mojom::CertVerifierCreationParams cert_verifier_params;
+  context.ConfigureNetworkContextParams(
+      false, base::FilePath(), &network_context_params, &cert_verifier_params);
+
+  ASSERT_TRUE(network_context_params.initial_ssl_config);
+  EXPECT_EQ(network::mojom::SSLVersion::kTLS1,
+            network_context_params.initial_ssl_config->version_min);
+}
+
+// Tests that TLS 1.0/1.1 are disallowed when the escape hatch feature is
+// disabled.
+TEST_F(AwBrowserContextTest, LegacyTLSVersionsDisallowed) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(
+      android_webview::features::kWebViewLegacyTlsSupport);
+
+  AwBrowserContext context;
+  network::mojom::NetworkContextParams network_context_params;
+  cert_verifier::mojom::CertVerifierCreationParams cert_verifier_params;
+  context.ConfigureNetworkContextParams(
+      false, base::FilePath(), &network_context_params, &cert_verifier_params);
+
+  ASSERT_TRUE(network_context_params.initial_ssl_config);
+  EXPECT_EQ(network::mojom::SSLVersion::kTLS12,
+            network_context_params.initial_ssl_config->version_min);
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client_receiver_bindings.cc b/android_webview/browser/aw_content_browser_client_receiver_bindings.cc
index ada3758..36c16a74 100644
--- a/android_webview/browser/aw_content_browser_client_receiver_bindings.cc
+++ b/android_webview/browser/aw_content_browser_client_receiver_bindings.cc
@@ -34,12 +34,8 @@
     return;
   }
 
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host);
-  DCHECK(web_contents) << "WebContents not available.";
-
   auto* aw_browser_context =
-      static_cast<AwBrowserContext*>(web_contents->GetBrowserContext());
+      static_cast<AwBrowserContext*>(render_frame_host->GetBrowserContext());
   DCHECK(aw_browser_context) << "AwBrowserContext not available.";
 
   PrefService* pref_service = aw_browser_context->GetPrefService();
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc
index bbf8d58..7b4acfe 100644
--- a/android_webview/common/aw_features.cc
+++ b/android_webview/common/aw_features.cc
@@ -51,6 +51,10 @@
 const base::Feature kWebViewJavaJsBridgeMojo{"WebViewJavaJsBridgeMojo",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
+// When enabled, connections using legacy TLS 1.0/1.1 versions are allowed.
+const base::Feature kWebViewLegacyTlsSupport{"WebViewLegacyTlsSupport",
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enables logging whether it was a first party page when logging PageTimeSpent.
 const base::Feature kWebViewLogFirstPartyPageTimeSpent{
     "WebViewLogFirstPartyPageTimeSpent", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h
index 747d5de..e0ecc5ee 100644
--- a/android_webview/common/aw_features.h
+++ b/android_webview/common/aw_features.h
@@ -22,6 +22,7 @@
 extern const base::Feature kWebViewExtraHeadersSameOriginOnly;
 extern const base::Feature kWebViewForceDarkModeMatchTheme;
 extern const base::Feature kWebViewJavaJsBridgeMojo;
+extern const base::Feature kWebViewLegacyTlsSupport;
 extern const base::Feature kWebViewLogFirstPartyPageTimeSpent;
 extern const base::Feature kWebViewMeasureScreenCoverage;
 extern const base::Feature kWebViewMixedContentAutoupgrades;
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 2147d58..e5a6a203 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
@@ -222,5 +222,7 @@
                             + "an exception."),
             Flag.baseFeature(BlinkFeatures.PREFETCH_ANDROID_FONTS,
                     "Enables prefetching Android fonts on renderer startup."),
+            Flag.baseFeature(AwFeatures.WEBVIEW_LEGACY_TLS_SUPPORT,
+                    "Whether legacy TLS versions (TLS 1.0/1.1) conections are allowed."),
     };
 }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 7b8461b..96b51ac 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1422,6 +1422,10 @@
     "system/supervised/supervised_icon_string.h",
     "system/system_notification_controller.cc",
     "system/system_notification_controller.h",
+    "system/time/calendar_event_list_item_view.cc",
+    "system/time/calendar_event_list_item_view.h",
+    "system/time/calendar_event_list_view.cc",
+    "system/time/calendar_event_list_view.h",
     "system/time/calendar_month_view.cc",
     "system/time/calendar_month_view.h",
     "system/time/calendar_utils.cc",
@@ -2527,7 +2531,10 @@
     "system/session/logout_confirmation_controller_unittest.cc",
     "system/session/session_limit_notification_controller_unittest.cc",
     "system/status_area_widget_unittest.cc",
+    "system/time/calendar_event_list_view_unittest.cc",
     "system/time/calendar_month_view_unittest.cc",
+    "system/time/calendar_unittest_utils.cc",
+    "system/time/calendar_unittest_utils.h",
     "system/time/calendar_view_controller_unittest.cc",
     "system/time/calendar_view_unittest.cc",
     "system/time/time_of_day_unittest.cc",
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc
index 3d1e382..639d311 100644
--- a/ash/app_list/app_list_presenter_unittest.cc
+++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -160,7 +160,8 @@
   suggestion_result->set_best_match(true);
   suggestion_result->set_display_type(SearchResultDisplayType::kList);
   SearchResultActions actions;
-  actions.push_back(SearchResultAction(gfx::ImageSkia(), u"Remove",
+  actions.push_back(SearchResultAction(SearchResultActionType::kRemove,
+                                       gfx::ImageSkia(), u"Remove",
                                        true /*visible_on_hover*/));
   suggestion_result->SetActions(actions);
 
diff --git a/ash/app_list/model/app_list_model.cc b/ash/app_list/model/app_list_model.cc
index 95085be..e6fc179 100644
--- a/ash/app_list/model/app_list_model.cc
+++ b/ash/app_list/model/app_list_model.cc
@@ -273,8 +273,6 @@
           static_cast<AppListFolderItem*>(item)->item_list());
     }
     top_level_item_list_->DeleteItem(id);
-    for (auto& observer : observers_)
-      observer.OnAppListItemDeleted(id);
     return;
   }
 
@@ -312,8 +310,6 @@
           static_cast<AppListFolderItem*>(item)->item_list());
     }
     top_level_item_list_->DeleteItemAt(0);
-    for (auto& observer : observers_)
-      observer.OnAppListItemDeleted(id);
   }
 }
 
@@ -428,8 +424,6 @@
       observer.OnAppListItemWillBeDeleted(item);
     std::string id = removed_item->id();
     removed_item.reset();  // Deletes item.
-    for (auto& observer : observers_)
-      observer.OnAppListItemDeleted(id);
   }
 
   // Delete the folder if the folder becomes empty after child removal.
diff --git a/ash/app_list/model/app_list_model_observer.h b/ash/app_list/model/app_list_model_observer.h
index 87804c3..5568e10 100644
--- a/ash/app_list/model/app_list_model_observer.h
+++ b/ash/app_list/model/app_list_model_observer.h
@@ -5,8 +5,6 @@
 #ifndef ASH_APP_LIST_MODEL_APP_LIST_MODEL_OBSERVER_H_
 #define ASH_APP_LIST_MODEL_APP_LIST_MODEL_OBSERVER_H_
 
-#include <string>
-
 #include "ash/app_list/model/app_list_model_export.h"
 #include "base/observer_list_types.h"
 
@@ -27,9 +25,6 @@
   // Triggered just before an item is deleted from the model.
   virtual void OnAppListItemWillBeDeleted(AppListItem* item) {}
 
-  // Triggered just after an item is deleted from the model.
-  virtual void OnAppListItemDeleted(const std::string& id) {}
-
   // Triggered after |item| has moved, changed folders, or changed properties.
   virtual void OnAppListItemUpdated(AppListItem* item) {}
 
diff --git a/ash/app_list/views/continue_section_view_unittest.cc b/ash/app_list/views/continue_section_view_unittest.cc
index 3ef59ba..ff4a5d7 100644
--- a/ash/app_list/views/continue_section_view_unittest.cc
+++ b/ash/app_list/views/continue_section_view_unittest.cc
@@ -375,20 +375,22 @@
   AddSearchResult("id2", AppListSearchResultType::kDriveChip);
   AddSearchResult("id3", AppListSearchResultType::kDriveChip);
 
+  UpdateDisplay("1200x800");
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
   VerifyResultViewsUpdated();
 
   ASSERT_TRUE(GetContinueSectionView()->GetVisible());
   ASSERT_EQ(3u, GetContinueSectionView()->GetTasksSuggestionsCount());
 
-  const int width = GetResultViewAt(0)->width();
+  const gfx::Size size = GetResultViewAt(0)->size();
   const int vertical_position = GetResultViewAt(0)->y();
 
   for (int i = 1; i < 3; i++) {
-    EXPECT_EQ(width, GetResultViewAt(i)->width());
-    EXPECT_EQ(vertical_position, GetResultViewAt(i)->y());
-    EXPECT_GT(GetResultViewAt(i)->x(),
-              GetResultViewAt(i - 1)->bounds().right());
+    const ContinueTaskView* task_view = GetResultViewAt(i);
+    EXPECT_TRUE(task_view->GetVisible());
+    EXPECT_EQ(size, task_view->size());
+    EXPECT_EQ(vertical_position, task_view->y());
+    EXPECT_GT(task_view->x(), GetResultViewAt(i - 1)->bounds().right());
   }
 }
 
@@ -398,22 +400,54 @@
   AddSearchResult("id3", AppListSearchResultType::kDriveChip);
   AddSearchResult("id4", AppListSearchResultType::kFileChip);
 
+  UpdateDisplay("1200x800");
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
   VerifyResultViewsUpdated();
 
   ASSERT_TRUE(GetContinueSectionView()->GetVisible());
   ASSERT_EQ(4u, GetContinueSectionView()->GetTasksSuggestionsCount());
 
-  const int width = GetResultViewAt(0)->width();
+  const gfx::Size size = GetResultViewAt(0)->size();
   const int vertical_position = GetResultViewAt(0)->y();
 
   for (int i = 1; i < 4; i++) {
-    EXPECT_EQ(width, GetResultViewAt(i)->width());
-    EXPECT_EQ(vertical_position, GetResultViewAt(i)->y());
-    EXPECT_GT(GetResultViewAt(i)->x(),
-              GetResultViewAt(i - 1)->bounds().right());
+    const ContinueTaskView* task_view = GetResultViewAt(i);
+    EXPECT_TRUE(task_view->GetVisible());
+    EXPECT_EQ(size, task_view->size());
+    EXPECT_EQ(vertical_position, task_view->y());
+    EXPECT_GT(task_view->x(), GetResultViewAt(i - 1)->bounds().right());
   }
 }
 
+// Tests that number of shown continue section items is reduced if they don't
+// all fit into the available space (while maintaining min width).
+TEST_F(ContinueSectionViewTest,
+       TabletModeLayoutWithFourSuggestionsWithRestrictedSpace) {
+  AddSearchResult("id1", AppListSearchResultType::kFileChip);
+  AddSearchResult("id2", AppListSearchResultType::kDriveChip);
+  AddSearchResult("id3", AppListSearchResultType::kDriveChip);
+  AddSearchResult("id4", AppListSearchResultType::kFileChip);
+
+  // Set the display width so only 2 continue section tasks fit into available
+  // space.
+  UpdateDisplay("800x600");
+
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  VerifyResultViewsUpdated();
+
+  ASSERT_EQ(4u, GetContinueSectionView()->GetTasksSuggestionsCount());
+
+  // Only first two tasks are visible.
+  for (int i = 0; i < 4; ++i)
+    EXPECT_EQ(i <= 1, GetResultViewAt(i)->GetVisible()) << i;
+
+  const ContinueTaskView* first_task = GetResultViewAt(0);
+  const ContinueTaskView* second_task = GetResultViewAt(1);
+
+  EXPECT_EQ(first_task->size(), second_task->size());
+  EXPECT_EQ(first_task->y(), second_task->y());
+  EXPECT_GT(second_task->x(), first_task->bounds().right());
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/ash/app_list/views/continue_task_container_view.cc b/ash/app_list/views/continue_task_container_view.cc
index 24555d9..a9199f55 100644
--- a/ash/app_list/views/continue_task_container_view.cc
+++ b/ash/app_list/views/continue_task_container_view.cc
@@ -185,7 +185,7 @@
                   gfx::Insets(0, kColumnSpacingTablet, 0, 0))
       .SetDefault(views::kFlexBehaviorKey,
                   views::FlexSpecification(
-                      views::MinimumFlexSizeRule::kScaleToMinimum,
+                      views::MinimumFlexSizeRule::kScaleToMinimumSnapToZero,
                       views::MaximumFlexSizeRule::kScaleToMaximum));
 }
 
diff --git a/ash/app_list/views/result_selection_controller_unittest.cc b/ash/app_list/views/result_selection_controller_unittest.cc
index ebfc621..9c9ea2f4 100644
--- a/ash/app_list/views/result_selection_controller_unittest.cc
+++ b/ash/app_list/views/result_selection_controller_unittest.cc
@@ -109,7 +109,8 @@
         result_view->GetActionsView()->SetActions(
             std::vector<SearchResult::Action>(
                 params.actions_per_result.value(),
-                SearchResult::Action(gfx::ImageSkia(), std::u16string(),
+                SearchResult::Action(SearchResultActionType::kRemove,
+                                     gfx::ImageSkia(), std::u16string(),
                                      false)));
         search_result_views_.emplace_back(std::move(result_view));
       } else {
@@ -1286,7 +1287,8 @@
   // Remove two trailing actions - the result action is de-selected.
   selected_view->AsResultViewWithActions()->GetActionsView()->SetActions(
       std::vector<SearchResult::Action>(
-          1, SearchResult::Action(gfx::ImageSkia(), std::u16string(), false)));
+          1, SearchResult::Action(ash::SearchResultActionType::kRemove,
+                                  gfx::ImageSkia(), std::u16string(), false)));
   ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation());
   EXPECT_TRUE(CurrentResultActionNotSelected());
 
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc
index ed222e7..61f20be 100644
--- a/ash/app_list/views/search_result_view.cc
+++ b/ash/app_list/views/search_result_view.cc
@@ -585,7 +585,7 @@
   DCHECK_LT(index, result()->actions().size());
 
   if (result()->is_omnibox_search()) {
-    SearchResultActionType button_action = GetSearchResultActionType(index);
+    SearchResultActionType button_action = result()->actions()[index].type;
 
     switch (button_action) {
       case SearchResultActionType::kRemove: {
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc
index b121388d..3255691b 100644
--- a/ash/capture_mode/capture_mode_controller.cc
+++ b/ash/capture_mode/capture_mode_controller.cc
@@ -995,9 +995,8 @@
   if (!delegate_->IsCaptureAllowedByPolicy()) {
     return CaptureAllowance::kDisallowedByPolicy;
   }
-  if (!delegate_->IsCaptureAllowedByDlp(
-          capture_params.window, capture_params.bounds,
-          /*for_video=*/type_ == CaptureModeType::kVideo)) {
+  if (!delegate_->IsCaptureAllowedByDlp(capture_params.window,
+                                        capture_params.bounds)) {
     return CaptureAllowance::kDisallowedByDlp;
   }
 
diff --git a/ash/capture_mode/test_capture_mode_delegate.cc b/ash/capture_mode/test_capture_mode_delegate.cc
index be19e449..cf35efa41 100644
--- a/ash/capture_mode/test_capture_mode_delegate.cc
+++ b/ash/capture_mode/test_capture_mode_delegate.cc
@@ -96,9 +96,9 @@
   std::move(callback).Run(/*proceed=*/is_allowed_by_dlp_);
 }
 
-bool TestCaptureModeDelegate::IsCaptureAllowedByDlp(const aura::Window* window,
-                                                    const gfx::Rect& bounds,
-                                                    bool for_video) const {
+bool TestCaptureModeDelegate::IsCaptureAllowedByDlp(
+    const aura::Window* window,
+    const gfx::Rect& bounds) const {
   return is_allowed_by_dlp_;
 }
 
diff --git a/ash/capture_mode/test_capture_mode_delegate.h b/ash/capture_mode/test_capture_mode_delegate.h
index 2aeb9f94..2398a8d 100644
--- a/ash/capture_mode/test_capture_mode_delegate.h
+++ b/ash/capture_mode/test_capture_mode_delegate.h
@@ -73,8 +73,7 @@
   void CheckCaptureModeInitRestrictionByDlp(
       OnCaptureModeDlpRestrictionChecked callback) override;
   bool IsCaptureAllowedByDlp(const aura::Window* window,
-                             const gfx::Rect& bounds,
-                             bool for_video) const override;
+                             const gfx::Rect& bounds) const override;
   bool IsCaptureAllowedByPolicy() const override;
   void StartObservingRestrictedContent(
       const aura::Window* window,
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn
index 309136d..968a90d 100644
--- a/ash/components/arc/BUILD.gn
+++ b/ash/components/arc/BUILD.gn
@@ -107,6 +107,7 @@
 
   deps = [
     "//ash",
+    "//ash/components/arc/enterprise",
     "//ash/components/arc/input_overlay/resources:resources_grit",
     "//ash/components/audio",
     "//ash/constants",
@@ -132,7 +133,6 @@
     "//chromeos/ui/base",
     "//chromeos/ui/frame",
     "//components/account_id",
-    "//components/arc/enterprise",
     "//components/arc/vector_icons",
     "//components/exo",
     "//components/google/core/common",
@@ -186,8 +186,8 @@
   defines = [ "ARC_IMPLEMENTATION" ]
 
   deps = [
+    "//ash/components/arc/session:arc_base_enums",
     "//build:chromeos_buildflags",
-    "//components/arc/session:arc_base_enums",
     "//components/guest_os:prefs",
     "//components/prefs",
   ]
@@ -239,10 +239,10 @@
 
   public_deps = [
     ":arc_base_utils",
+    "//ash/components/arc/session",
+    "//ash/components/arc/session:arc_base_enums",
+    "//ash/components/arc/session:connection_holder",
     "//components/arc/mojom",
-    "//components/arc/session",
-    "//components/arc/session:arc_base_enums",
-    "//components/arc/session:connection_holder",
     "//dbus",
   ]
 }
@@ -276,8 +276,8 @@
   ]
 
   public_deps = [
+    "//ash/components/arc/session:connection_holder",
     "//components/arc/mojom:notifications",
-    "//components/arc/session:connection_holder",
   ]
 }
 
@@ -359,9 +359,9 @@
   ]
 
   deps = [
+    "//ash/components/arc/enterprise",
     "//ash/constants",
     "//base",
-    "//components/arc/enterprise",
     "//components/keyed_service/content",
     "//components/prefs:test_support",
     "//components/user_prefs",
@@ -430,6 +430,9 @@
   # TODO(b/129295708): Clean up unused deps. Update users of this target.
   deps = [
     "//ash/components/arc:arc_test_support",
+    "//ash/components/arc/enterprise",
+    "//ash/components/arc/media_session",
+    "//ash/components/arc/video_accelerator:common",
     "//ash/constants",
     "//ash/keyboard/ui",
     "//ash/public/cpp",
@@ -452,9 +455,6 @@
     "//chromeos/policy",
     "//chromeos/ui/frame",
     "//components/account_id",
-    "//components/arc/enterprise",
-    "//components/arc/media_session",
-    "//components/arc/video_accelerator:common",
     "//components/exo",
     "//components/exo:test_support",
     "//components/keyed_service/content",
diff --git a/ash/components/arc/appfuse/arc_appfuse_bridge.cc b/ash/components/arc/appfuse/arc_appfuse_bridge.cc
index 8c62d87..0386fcb8 100644
--- a/ash/components/arc/appfuse/arc_appfuse_bridge.cc
+++ b/ash/components/arc/appfuse/arc_appfuse_bridge.cc
@@ -9,11 +9,11 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/arc/arc_appfuse_provider_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace arc {
diff --git a/ash/components/arc/appfuse/arc_appfuse_bridge_unittest.cc b/ash/components/arc/appfuse/arc_appfuse_bridge_unittest.cc
index 531d2e5..98cc5c93 100644
--- a/ash/components/arc/appfuse/arc_appfuse_bridge_unittest.cc
+++ b/ash/components/arc/appfuse/arc_appfuse_bridge_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "ash/components/arc/appfuse/arc_appfuse_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/arc_browser_context_keyed_service_factory_base.h b/ash/components/arc/arc_browser_context_keyed_service_factory_base.h
index 586de85..af25e09d 100644
--- a/ash/components/arc/arc_browser_context_keyed_service_factory_base.h
+++ b/ash/components/arc/arc_browser_context_keyed_service_factory_base.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/logging.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
diff --git a/ash/components/arc/arc_prefs.cc b/ash/components/arc/arc_prefs.cc
index 01b9156f..32ac663 100644
--- a/ash/components/arc/arc_prefs.cc
+++ b/ash/components/arc/arc_prefs.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/components/arc/arc_prefs.h"
-#include "components/arc/session/arc_management_transition.h"
+#include "ash/components/arc/session/arc_management_transition.h"
 
 #include <string>
 
diff --git a/ash/components/arc/audio/arc_audio_bridge.cc b/ash/components/arc/audio/arc_audio_bridge.cc
index b0f343e..2d596b88 100644
--- a/ash/components/arc/audio/arc_audio_bridge.cc
+++ b/ash/components/arc/audio/arc_audio_bridge.cc
@@ -7,11 +7,11 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/audio/audio_device.h"
 #include "ash/public/cpp/system_tray.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 namespace {
diff --git a/ash/components/arc/audio/arc_audio_bridge.h b/ash/components/arc/audio/arc_audio_bridge.h
index 8c9526d..874449c 100644
--- a/ash/components/arc/audio/arc_audio_bridge.h
+++ b/ash/components/arc/audio/arc_audio_bridge.h
@@ -5,9 +5,9 @@
 #ifndef ASH_COMPONENTS_ARC_AUDIO_ARC_AUDIO_BRIDGE_H_
 #define ASH_COMPONENTS_ARC_AUDIO_ARC_AUDIO_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/components/audio/cras_audio_handler.h"
 #include "components/arc/mojom/audio.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/ash/components/arc/audio/arc_audio_bridge_unittest.cc b/ash/components/arc/audio/arc_audio_bridge_unittest.cc
index 7cc6d5b..cdca106d 100644
--- a/ash/components/arc/audio/arc_audio_bridge_unittest.cc
+++ b/ash/components/arc/audio/arc_audio_bridge_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "ash/components/arc/audio/arc_audio_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/camera/arc_camera_bridge.cc b/ash/components/arc/camera/arc_camera_bridge.cc
index a78406c..1a9e56da 100644
--- a/ash/components/arc/camera/arc_camera_bridge.cc
+++ b/ash/components/arc/camera/arc_camera_bridge.cc
@@ -7,13 +7,13 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "chromeos/dbus/arc/arc_camera_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "crypto/random.h"
 #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/components/arc/camera/arc_camera_bridge_unittest.cc b/ash/components/arc/camera/arc_camera_bridge_unittest.cc
index a723921..3c656b0 100644
--- a/ash/components/arc/camera/arc_camera_bridge_unittest.cc
+++ b/ash/components/arc/camera/arc_camera_bridge_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "ash/components/arc/camera/arc_camera_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/clipboard/arc_clipboard_bridge.cc b/ash/components/arc/clipboard/arc_clipboard_bridge.cc
index d98b1f0..b03253b 100644
--- a/ash/components/arc/clipboard/arc_clipboard_bridge.cc
+++ b/ash/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -9,11 +9,11 @@
 #include <vector>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/auto_reset.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/clipboard_constants.h"
 #include "ui/base/clipboard/clipboard_monitor.h"
diff --git a/ash/components/arc/clipboard/arc_clipboard_bridge_unittest.cc b/ash/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
index 05483412..2e953082 100644
--- a/ash/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
+++ b/ash/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
@@ -8,12 +8,12 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_clipboard_instance.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_callback.h"
 #include "components/arc/mojom/clipboard.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/clipboard/clipboard.h"
diff --git a/ash/components/arc/crash_collector/arc_crash_collector_bridge.cc b/ash/components/arc/crash_collector/arc_crash_collector_bridge.cc
index 6ec1948..62caeb83 100644
--- a/ash/components/arc/crash_collector/arc_crash_collector_bridge.cc
+++ b/ash/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
@@ -20,7 +21,6 @@
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace {
diff --git a/ash/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc b/ash/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc
index 5127b687..216fb591 100644
--- a/ash/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc
+++ b/ash/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc
@@ -6,8 +6,8 @@
 
 #include <unistd.h>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/arc/dark_theme/arc_dark_theme_bridge.cc b/ash/components/arc/dark_theme/arc_dark_theme_bridge.cc
index 3714de4..e8f8a1da 100644
--- a/ash/components/arc/dark_theme/arc_dark_theme_bridge.cc
+++ b/ash/components/arc/dark_theme/arc_dark_theme_bridge.cc
@@ -5,14 +5,14 @@
 #include "ash/components/arc/dark_theme/arc_dark_theme_bridge.h"
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/style/color_provider.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace arc {
diff --git a/ash/components/arc/dark_theme/arc_dark_theme_bridge.h b/ash/components/arc/dark_theme/arc_dark_theme_bridge.h
index 9d592c7..7783366 100644
--- a/ash/components/arc/dark_theme/arc_dark_theme_bridge.h
+++ b/ash/components/arc/dark_theme/arc_dark_theme_bridge.h
@@ -5,10 +5,10 @@
 #ifndef ASH_COMPONENTS_ARC_DARK_THEME_ARC_DARK_THEME_BRIDGE_H_
 #define ASH_COMPONENTS_ARC_DARK_THEME_ARC_DARK_THEME_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/public/cpp/style/color_mode_observer.h"
 #include "base/threading/thread_checker.h"
 #include "components/arc/mojom/dark_theme.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
diff --git a/ash/components/arc/dark_theme/arc_dark_theme_bridge_unittest.cc b/ash/components/arc/dark_theme/arc_dark_theme_bridge_unittest.cc
index d1adcba..dca8d54 100644
--- a/ash/components/arc/dark_theme/arc_dark_theme_bridge_unittest.cc
+++ b/ash/components/arc/dark_theme/arc_dark_theme_bridge_unittest.cc
@@ -6,11 +6,11 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_dark_theme_instance.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
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 f64fee7..51694df 100644
--- a/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
+++ b/ash/components/arc/disk_quota/arc_disk_quota_bridge.cc
@@ -7,11 +7,11 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/userdataauth/arc_quota_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace arc {
diff --git a/components/arc/enterprise/BUILD.gn b/ash/components/arc/enterprise/BUILD.gn
similarity index 100%
rename from components/arc/enterprise/BUILD.gn
rename to ash/components/arc/enterprise/BUILD.gn
diff --git a/components/arc/enterprise/DEPS b/ash/components/arc/enterprise/DEPS
similarity index 100%
rename from components/arc/enterprise/DEPS
rename to ash/components/arc/enterprise/DEPS
diff --git a/components/arc/enterprise/OWNERS b/ash/components/arc/enterprise/OWNERS
similarity index 100%
rename from components/arc/enterprise/OWNERS
rename to ash/components/arc/enterprise/OWNERS
diff --git a/components/arc/enterprise/arc_apps_tracker.h b/ash/components/arc/enterprise/arc_apps_tracker.h
similarity index 83%
rename from components/arc/enterprise/arc_apps_tracker.h
rename to ash/components/arc/enterprise/arc_apps_tracker.h
index 3c22aadb..49add14 100644
--- a/components/arc/enterprise/arc_apps_tracker.h
+++ b/ash/components/arc/enterprise/arc_apps_tracker.h
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_ENTERPRISE_ARC_APPS_TRACKER_H_
-#define COMPONENTS_ARC_ENTERPRISE_ARC_APPS_TRACKER_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_ARC_APPS_TRACKER_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_ARC_APPS_TRACKER_H_
+
+#include "base/callback_forward.h"
 
 namespace arc {
 namespace data_snapshotd {
@@ -30,4 +32,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_ARC_APPS_TRACKER_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_ARC_APPS_TRACKER_H_
diff --git a/components/arc/enterprise/arc_data_remove_requested_pref_handler.cc b/ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.cc
similarity index 94%
rename from components/arc/enterprise/arc_data_remove_requested_pref_handler.cc
rename to ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.cc
index 3630d46..961bd94 100644
--- a/components/arc/enterprise/arc_data_remove_requested_pref_handler.cc
+++ b/ash/components/arc/enterprise/arc_data_remove_requested_pref_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 "components/arc/enterprise/arc_data_remove_requested_pref_handler.h"
+#include "ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.h"
 
 #include "ash/components/arc/arc_prefs.h"
 #include "base/memory/ptr_util.h"
diff --git a/components/arc/enterprise/arc_data_remove_requested_pref_handler.h b/ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.h
similarity index 87%
rename from components/arc/enterprise/arc_data_remove_requested_pref_handler.h
rename to ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.h
index f447eba2..30d20ea 100644
--- a/components/arc/enterprise/arc_data_remove_requested_pref_handler.h
+++ b/ash/components/arc/enterprise/arc_data_remove_requested_pref_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 COMPONENTS_ARC_ENTERPRISE_ARC_DATA_REMOVE_REQUESTED_PREF_HANDLER_H_
-#define COMPONENTS_ARC_ENTERPRISE_ARC_DATA_REMOVE_REQUESTED_PREF_HANDLER_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_REMOVE_REQUESTED_PREF_HANDLER_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_REMOVE_REQUESTED_PREF_HANDLER_H_
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
@@ -51,4 +51,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_ARC_DATA_REMOVE_REQUESTED_PREF_HANDLER_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_REMOVE_REQUESTED_PREF_HANDLER_H_
diff --git a/ash/components/arc/enterprise/arc_data_remove_requested_pref_handler_unittest.cc b/ash/components/arc/enterprise/arc_data_remove_requested_pref_handler_unittest.cc
index 0c40e460..50f00ad 100644
--- a/ash/components/arc/enterprise/arc_data_remove_requested_pref_handler_unittest.cc
+++ b/ash/components/arc/enterprise/arc_data_remove_requested_pref_handler_unittest.cc
@@ -5,11 +5,11 @@
 #include <memory>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.h"
+#include "ash/components/arc/session/arc_data_remover.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "components/arc/enterprise/arc_data_remove_requested_pref_handler.h"
-#include "components/arc/session/arc_data_remover.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/arc/enterprise/arc_data_snapshotd_bridge.cc b/ash/components/arc/enterprise/arc_data_snapshotd_bridge.cc
similarity index 98%
rename from components/arc/enterprise/arc_data_snapshotd_bridge.cc
rename to ash/components/arc/enterprise/arc_data_snapshotd_bridge.cc
index 62a04bc..a58db6b 100644
--- a/components/arc/enterprise/arc_data_snapshotd_bridge.cc
+++ b/ash/components/arc/enterprise/arc_data_snapshotd_bridge.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 "components/arc/enterprise/arc_data_snapshotd_bridge.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_bridge.h"
 
 #include <utility>
 
diff --git a/components/arc/enterprise/arc_data_snapshotd_bridge.h b/ash/components/arc/enterprise/arc_data_snapshotd_bridge.h
similarity index 94%
rename from components/arc/enterprise/arc_data_snapshotd_bridge.h
rename to ash/components/arc/enterprise/arc_data_snapshotd_bridge.h
index 6406f367..21fed03 100644
--- a/components/arc/enterprise/arc_data_snapshotd_bridge.h
+++ b/ash/components/arc/enterprise/arc_data_snapshotd_bridge.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 COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_BRIDGE_H_
-#define COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_BRIDGE_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_BRIDGE_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_BRIDGE_H_
 
 #include <string>
 
@@ -86,4 +86,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_BRIDGE_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_BRIDGE_H_
diff --git a/ash/components/arc/enterprise/arc_data_snapshotd_bridge_unittest.cc b/ash/components/arc/enterprise/arc_data_snapshotd_bridge_unittest.cc
index 8c98e46..caafb055 100644
--- a/ash/components/arc/enterprise/arc_data_snapshotd_bridge_unittest.cc
+++ b/ash/components/arc/enterprise/arc_data_snapshotd_bridge_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 "components/arc/enterprise/arc_data_snapshotd_bridge.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_bridge.h"
 
 #include <memory>
 
diff --git a/components/arc/enterprise/arc_data_snapshotd_manager.cc b/ash/components/arc/enterprise/arc_data_snapshotd_manager.cc
similarity index 99%
rename from components/arc/enterprise/arc_data_snapshotd_manager.cc
rename to ash/components/arc/enterprise/arc_data_snapshotd_manager.cc
index c21c34a..64ed279 100644
--- a/components/arc/enterprise/arc_data_snapshotd_manager.cc
+++ b/ash/components/arc/enterprise/arc_data_snapshotd_manager.cc
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
 
 #include <utility>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/enterprise/arc_data_remove_requested_pref_handler.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_bridge.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -22,8 +24,6 @@
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
-#include "components/arc/enterprise/arc_data_remove_requested_pref_handler.h"
-#include "components/arc/enterprise/arc_data_snapshotd_bridge.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
diff --git a/components/arc/enterprise/arc_data_snapshotd_manager.h b/ash/components/arc/enterprise/arc_data_snapshotd_manager.h
similarity index 96%
rename from components/arc/enterprise/arc_data_snapshotd_manager.h
rename to ash/components/arc/enterprise/arc_data_snapshotd_manager.h
index 867781c..1bece38 100644
--- a/components/arc/enterprise/arc_data_snapshotd_manager.h
+++ b/ash/components/arc/enterprise/arc_data_snapshotd_manager.h
@@ -2,22 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_MANAGER_H_
-#define COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_MANAGER_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_MANAGER_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_MANAGER_H_
 
 #include <memory>
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/enterprise/arc_apps_tracker.h"
+#include "ash/components/arc/enterprise/snapshot_hours_policy_service.h"
+#include "ash/components/arc/enterprise/snapshot_reboot_controller.h"
+#include "ash/components/arc/enterprise/snapshot_session_controller.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
-#include "components/arc/enterprise/arc_apps_tracker.h"
-#include "components/arc/enterprise/snapshot_hours_policy_service.h"
-#include "components/arc/enterprise/snapshot_reboot_controller.h"
-#include "components/arc/enterprise/snapshot_session_controller.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
 class PrefService;
@@ -429,4 +429,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_MANAGER_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_MANAGER_H_
diff --git a/ash/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc b/ash/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
index fc0e5d8..a0b70e7 100644
--- a/ash/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
+++ b/ash/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
 
 #include <memory>
 #include <string>
 #include <vector>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_bridge.h"
+#include "ash/components/arc/enterprise/snapshot_session_controller.h"
 #include "ash/components/arc/test/fake_apps_tracker.h"
 #include "ash/components/arc/test/fake_snapshot_reboot_notification.h"
 #include "ash/constants/ash_switches.h"
@@ -22,8 +24,6 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
 #include "chromeos/dbus/upstart/fake_upstart_client.h"
-#include "components/arc/enterprise/arc_data_snapshotd_bridge.h"
-#include "components/arc/enterprise/snapshot_session_controller.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/fake_user_manager.h"
diff --git a/components/arc/enterprise/arc_snapshot_reboot_notification.h b/ash/components/arc/enterprise/arc_snapshot_reboot_notification.h
similarity index 76%
rename from components/arc/enterprise/arc_snapshot_reboot_notification.h
rename to ash/components/arc/enterprise/arc_snapshot_reboot_notification.h
index 67241d0..6a6affa 100644
--- a/components/arc/enterprise/arc_snapshot_reboot_notification.h
+++ b/ash/components/arc/enterprise/arc_snapshot_reboot_notification.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 COMPONENTS_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_H_
-#define COMPONENTS_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_H_
 
 #include "base/callback_forward.h"
 
@@ -29,4 +29,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_H_
diff --git a/components/arc/enterprise/snapshot_hours_policy_service.cc b/ash/components/arc/enterprise/snapshot_hours_policy_service.cc
similarity index 98%
rename from components/arc/enterprise/snapshot_hours_policy_service.cc
rename to ash/components/arc/enterprise/snapshot_hours_policy_service.cc
index 579c02d..1baaef7 100644
--- a/components/arc/enterprise/snapshot_hours_policy_service.cc
+++ b/ash/components/arc/enterprise/snapshot_hours_policy_service.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 "components/arc/enterprise/snapshot_hours_policy_service.h"
+#include "ash/components/arc/enterprise/snapshot_hours_policy_service.h"
 
 #include <memory>
 #include <utility>
diff --git a/components/arc/enterprise/snapshot_hours_policy_service.h b/ash/components/arc/enterprise/snapshot_hours_policy_service.h
similarity index 95%
rename from components/arc/enterprise/snapshot_hours_policy_service.h
rename to ash/components/arc/enterprise/snapshot_hours_policy_service.h
index c906573..c7a8f8f 100644
--- a/components/arc/enterprise/snapshot_hours_policy_service.h
+++ b/ash/components/arc/enterprise/snapshot_hours_policy_service.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 COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_HOURS_POLICY_SERVICE_H_
-#define COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_HOURS_POLICY_SERVICE_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_HOURS_POLICY_SERVICE_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_HOURS_POLICY_SERVICE_H_
 
 #include <vector>
 
@@ -143,4 +143,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_HOURS_POLICY_SERVICE_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_HOURS_POLICY_SERVICE_H_
diff --git a/ash/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc b/ash/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc
index 40ecc88..015d230a 100644
--- a/ash/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc
+++ b/ash/components/arc/enterprise/snapshot_hours_policy_service_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 "components/arc/enterprise/snapshot_hours_policy_service.h"
+#include "ash/components/arc/enterprise/snapshot_hours_policy_service.h"
 
 #include <memory>
 #include <string>
diff --git a/components/arc/enterprise/snapshot_reboot_controller.cc b/ash/components/arc/enterprise/snapshot_reboot_controller.cc
similarity index 97%
rename from components/arc/enterprise/snapshot_reboot_controller.cc
rename to ash/components/arc/enterprise/snapshot_reboot_controller.cc
index 2b8eecb3..251746b 100644
--- a/components/arc/enterprise/snapshot_reboot_controller.cc
+++ b/ash/components/arc/enterprise/snapshot_reboot_controller.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 "components/arc/enterprise/snapshot_reboot_controller.h"
+#include "ash/components/arc/enterprise/snapshot_reboot_controller.h"
 
 #include "base/logging.h"
 #include "chromeos/dbus/power/power_manager_client.h"
diff --git a/components/arc/enterprise/snapshot_reboot_controller.h b/ash/components/arc/enterprise/snapshot_reboot_controller.h
similarity index 85%
rename from components/arc/enterprise/snapshot_reboot_controller.h
rename to ash/components/arc/enterprise/snapshot_reboot_controller.h
index 29682783..e299001 100644
--- a/components/arc/enterprise/snapshot_reboot_controller.h
+++ b/ash/components/arc/enterprise/snapshot_reboot_controller.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 COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_REBOOT_CONTROLLER_H_
-#define COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_REBOOT_CONTROLLER_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_REBOOT_CONTROLLER_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_REBOOT_CONTROLLER_H_
 
+#include "ash/components/arc/enterprise/arc_snapshot_reboot_notification.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
-#include "components/arc/enterprise/arc_snapshot_reboot_notification.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
 namespace arc {
@@ -56,4 +56,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_REBOOT_CONTROLLER_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_REBOOT_CONTROLLER_H_
diff --git a/ash/components/arc/enterprise/snapshot_reboot_controller_unittest.cc b/ash/components/arc/enterprise/snapshot_reboot_controller_unittest.cc
index 0dd99a4..15ac0ca 100644
--- a/ash/components/arc/enterprise/snapshot_reboot_controller_unittest.cc
+++ b/ash/components/arc/enterprise/snapshot_reboot_controller_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 "components/arc/enterprise/snapshot_reboot_controller.h"
+#include "ash/components/arc/enterprise/snapshot_reboot_controller.h"
 #include "ash/components/arc/test/fake_snapshot_reboot_notification.h"
 #include "base/test/task_environment.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/components/arc/enterprise/snapshot_session_controller.cc b/ash/components/arc/enterprise/snapshot_session_controller.cc
similarity index 98%
rename from components/arc/enterprise/snapshot_session_controller.cc
rename to ash/components/arc/enterprise/snapshot_session_controller.cc
index 11e872e..53d9276 100644
--- a/components/arc/enterprise/snapshot_session_controller.cc
+++ b/ash/components/arc/enterprise/snapshot_session_controller.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 "components/arc/enterprise/snapshot_session_controller.h"
+#include "ash/components/arc/enterprise/snapshot_session_controller.h"
 
 #include "base/ignore_result.h"
 #include "base/logging.h"
diff --git a/components/arc/enterprise/snapshot_session_controller.h b/ash/components/arc/enterprise/snapshot_session_controller.h
similarity index 86%
rename from components/arc/enterprise/snapshot_session_controller.h
rename to ash/components/arc/enterprise/snapshot_session_controller.h
index ea47d21..e0ff613 100644
--- a/components/arc/enterprise/snapshot_session_controller.h
+++ b/ash/components/arc/enterprise/snapshot_session_controller.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 COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_SESSION_CONTROLLER_H_
-#define COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_SESSION_CONTROLLER_H_
+#ifndef ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_SESSION_CONTROLLER_H_
+#define ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_SESSION_CONTROLLER_H_
 
+#include "ash/components/arc/enterprise/arc_apps_tracker.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list_types.h"
 #include "base/timer/timer.h"
-#include "components/arc/enterprise/arc_apps_tracker.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
 namespace base {
@@ -54,4 +54,4 @@
 }  // namespace data_snapshotd
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_SESSION_CONTROLLER_H_
+#endif  // ASH_COMPONENTS_ARC_ENTERPRISE_SNAPSHOT_SESSION_CONTROLLER_H_
diff --git a/ash/components/arc/enterprise/snapshot_session_controller_unittest.cc b/ash/components/arc/enterprise/snapshot_session_controller_unittest.cc
index d8a42cc..2ad6076 100644
--- a/ash/components/arc/enterprise/snapshot_session_controller_unittest.cc
+++ b/ash/components/arc/enterprise/snapshot_session_controller_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 "components/arc/enterprise/snapshot_session_controller.h"
+#include "ash/components/arc/enterprise/snapshot_session_controller.h"
 
 #include <memory>
 #include <string>
diff --git a/ash/components/arc/ime/arc_ime_bridge_impl.cc b/ash/components/arc/ime/arc_ime_bridge_impl.cc
index a024843..76d8f1f3 100644
--- a/ash/components/arc/ime/arc_ime_bridge_impl.cc
+++ b/ash/components/arc/ime/arc_ime_bridge_impl.cc
@@ -8,10 +8,10 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "ui/base/ime/composition_text.h"
 #include "ui/base/ime/text_input_flags.h"
 #include "ui/base/ime/text_input_type.h"
diff --git a/ash/components/arc/ime/arc_ime_service_unittest.cc b/ash/components/arc/ime/arc_ime_service_unittest.cc
index 0340f4c..6b2d113c 100644
--- a/ash/components/arc/ime/arc_ime_service_unittest.cc
+++ b/ash/components/arc/ime/arc_ime_service_unittest.cc
@@ -9,13 +9,13 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/keyboard/ui/keyboard_ui_controller.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "components/arc/mojom/ime.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/test/test_windows.h"
diff --git a/ash/components/arc/keyboard_shortcut/arc_keyboard_shortcut_bridge.cc b/ash/components/arc/keyboard_shortcut/arc_keyboard_shortcut_bridge.cc
index 9065765..af84f7b2 100644
--- a/ash/components/arc/keyboard_shortcut/arc_keyboard_shortcut_bridge.cc
+++ b/ash/components/arc/keyboard_shortcut/arc_keyboard_shortcut_bridge.cc
@@ -6,11 +6,11 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
diff --git a/ash/components/arc/lock_screen/arc_lock_screen_bridge.cc b/ash/components/arc/lock_screen/arc_lock_screen_bridge.cc
index b2e7575b3..6a0c17a 100644
--- a/ash/components/arc/lock_screen/arc_lock_screen_bridge.cc
+++ b/ash/components/arc/lock_screen/arc_lock_screen_bridge.cc
@@ -5,11 +5,11 @@
 #include "ash/components/arc/lock_screen/arc_lock_screen_bridge.h"
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/session_manager/core/session_manager.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/ash/components/arc/lock_screen/arc_lock_screen_bridge.h b/ash/components/arc/lock_screen/arc_lock_screen_bridge.h
index 270a26d..a688694 100644
--- a/ash/components/arc/lock_screen/arc_lock_screen_bridge.h
+++ b/ash/components/arc/lock_screen/arc_lock_screen_bridge.h
@@ -5,9 +5,9 @@
 #ifndef ASH_COMPONENTS_ARC_LOCK_SCREEN_ARC_LOCK_SCREEN_BRIDGE_H_
 #define ASH_COMPONENTS_ARC_LOCK_SCREEN_ARC_LOCK_SCREEN_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/threading/thread_checker.h"
 #include "components/arc/mojom/lock_screen.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
diff --git a/ash/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc b/ash/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc
index a783dc6..5c9cfdf 100644
--- a/ash/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc
+++ b/ash/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "ash/components/arc/lock_screen/arc_lock_screen_bridge.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_lock_screen_instance.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/arc/media_session/BUILD.gn b/ash/components/arc/media_session/BUILD.gn
similarity index 100%
rename from components/arc/media_session/BUILD.gn
rename to ash/components/arc/media_session/BUILD.gn
diff --git a/components/arc/media_session/DEPS b/ash/components/arc/media_session/DEPS
similarity index 100%
rename from components/arc/media_session/DEPS
rename to ash/components/arc/media_session/DEPS
diff --git a/components/arc/media_session/DIR_METADATA b/ash/components/arc/media_session/DIR_METADATA
similarity index 100%
rename from components/arc/media_session/DIR_METADATA
rename to ash/components/arc/media_session/DIR_METADATA
diff --git a/components/arc/media_session/OWNERS b/ash/components/arc/media_session/OWNERS
similarity index 100%
rename from components/arc/media_session/OWNERS
rename to ash/components/arc/media_session/OWNERS
diff --git a/components/arc/media_session/arc_media_session_bridge.cc b/ash/components/arc/media_session/arc_media_session_bridge.cc
similarity index 96%
rename from components/arc/media_session/arc_media_session_bridge.cc
rename to ash/components/arc/media_session/arc_media_session_bridge.cc
index c7039b8..68e718b7 100644
--- a/components/arc/media_session/arc_media_session_bridge.cc
+++ b/ash/components/arc/media_session/arc_media_session_bridge.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/media_session/arc_media_session_bridge.h"
+#include "ash/components/arc/media_session/arc_media_session_bridge.h"
 
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/media_session_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/media_session/public/cpp/features.h"
diff --git a/components/arc/media_session/arc_media_session_bridge.h b/ash/components/arc/media_session/arc_media_session_bridge.h
similarity index 85%
rename from components/arc/media_session/arc_media_session_bridge.h
rename to ash/components/arc/media_session/arc_media_session_bridge.h
index 9da27d8..af719a2 100644
--- a/components/arc/media_session/arc_media_session_bridge.h
+++ b/ash/components/arc/media_session/arc_media_session_bridge.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
-#define COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
+#ifndef ASH_COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
+#define ASH_COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "components/arc/mojom/media_session.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
@@ -52,4 +52,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
+#endif  // ASH_COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
diff --git a/ash/components/arc/media_session/arc_media_session_bridge_unittest.cc b/ash/components/arc/media_session/arc_media_session_bridge_unittest.cc
index e63a1e3..ee44219 100644
--- a/ash/components/arc/media_session/arc_media_session_bridge_unittest.cc
+++ b/ash/components/arc/media_session/arc_media_session_bridge_unittest.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 "components/arc/media_session/arc_media_session_bridge.h"
+#include "ash/components/arc/media_session/arc_media_session_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/memory/arc_memory_bridge.cc b/ash/components/arc/memory/arc_memory_bridge.cc
index 79a553a..bbc41fe7 100644
--- a/ash/components/arc/memory/arc_memory_bridge.cc
+++ b/ash/components/arc/memory/arc_memory_bridge.cc
@@ -7,10 +7,10 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_observer.h"
 #include "content/public/browser/browser_context.h"
 
 namespace arc {
diff --git a/ash/components/arc/memory/arc_memory_bridge_unittest.cc b/ash/components/arc/memory/arc_memory_bridge_unittest.cc
index 3398fa9..4638c39 100644
--- a/ash/components/arc/memory/arc_memory_bridge_unittest.cc
+++ b/ash/components/arc/memory/arc_memory_bridge_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "ash/components/arc/memory/arc_memory_bridge.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_memory_instance.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "base/test/bind.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.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/ash/components/arc/memory_pressure/arc_memory_pressure_bridge.cc b/ash/components/arc/memory_pressure/arc_memory_pressure_bridge.cc
index 916c696..a30f5ce 100644
--- a/ash/components/arc/memory_pressure/arc_memory_pressure_bridge.cc
+++ b/ash/components/arc/memory_pressure/arc_memory_pressure_bridge.cc
@@ -5,10 +5,10 @@
 #include "ash/components/arc/memory_pressure/arc_memory_pressure_bridge.h"
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "components/arc/mojom/process.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 namespace {
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 2228910..d97ab7c 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
@@ -9,11 +9,11 @@
 
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/metrics/stability_metrics_manager.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_process_instance.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "chromeos/dbus/resourced/fake_resourced_client.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/arc/metrics/arc_metrics_service.cc b/ash/components/arc/metrics/arc_metrics_service.cc
index fdd3cf4..a6cf4da 100644
--- a/ash/components/arc/metrics/arc_metrics_service.cc
+++ b/ash/components/arc/metrics/arc_metrics_service.cc
@@ -10,6 +10,7 @@
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
 #include "ash/components/arc/metrics/stability_metrics_manager.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "base/bind.h"
 #include "base/logging.h"
@@ -20,7 +21,6 @@
 #include "base/strings/string_util.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/exo/wm_helper.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_prefs/user_prefs.h"
diff --git a/ash/components/arc/metrics/arc_metrics_service.h b/ash/components/arc/metrics/arc_metrics_service.h
index 2515246..c809a33f 100644
--- a/ash/components/arc/metrics/arc_metrics_service.h
+++ b/ash/components/arc/metrics/arc_metrics_service.h
@@ -12,6 +12,8 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -22,8 +24,6 @@
 #include "components/arc/mojom/anr.mojom.h"
 #include "components/arc/mojom/metrics.mojom.h"
 #include "components/arc/mojom/process.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/guest_os/guest_os_engagement_metrics.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/ash/components/arc/metrics/arc_metrics_service_unittest.cc b/ash/components/arc/metrics/arc_metrics_service_unittest.cc
index bd0fba8..1325b31 100644
--- a/ash/components/arc/metrics/arc_metrics_service_unittest.cc
+++ b/ash/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/stability_metrics_manager.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "ash/constants/app_types.h"
 #include "base/metrics/histogram_samples.h"
@@ -20,7 +21,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/test/browser_task_environment.h"
@@ -403,10 +403,20 @@
   expectation[CreateAnrKey(kAppTypeSystemServer, mojom::AnrType::INPUT)] = 1;
   VerifyAnr(tester, expectation);
 
-  service()->ReportAnr(
-      GetAnr(mojom::AnrSource::SYSTEM_SERVER, mojom::AnrType::SERVICE));
-  expectation[CreateAnrKey(kAppOverall, mojom::AnrType::SERVICE)] = 1;
-  expectation[CreateAnrKey(kAppTypeSystemServer, mojom::AnrType::SERVICE)] = 1;
+  service()->ReportAnr(GetAnr(mojom::AnrSource::SYSTEM_SERVER,
+                              mojom::AnrType::FOREGROUND_SERVICE));
+  expectation[CreateAnrKey(kAppOverall, mojom::AnrType::FOREGROUND_SERVICE)] =
+      1;
+  expectation[CreateAnrKey(kAppTypeSystemServer,
+                           mojom::AnrType::FOREGROUND_SERVICE)] = 1;
+  VerifyAnr(tester, expectation);
+
+  service()->ReportAnr(GetAnr(mojom::AnrSource::SYSTEM_SERVER,
+                              mojom::AnrType::BACKGROUND_SERVICE));
+  expectation[CreateAnrKey(kAppOverall, mojom::AnrType::BACKGROUND_SERVICE)] =
+      1;
+  expectation[CreateAnrKey(kAppTypeSystemServer,
+                           mojom::AnrType::BACKGROUND_SERVICE)] = 1;
   VerifyAnr(tester, expectation);
 
   service()->ReportAnr(
@@ -435,11 +445,12 @@
   expectation[CreateAnrKey(kAppTypeArcOther, mojom::AnrType::INPUT)] = 1;
   VerifyAnr(tester, expectation);
 
-  service()->ReportAnr(
-      GetAnr(mojom::AnrSource::ARC_APP_LAUNCHER, mojom::AnrType::SERVICE));
-  expectation[CreateAnrKey(kAppOverall, mojom::AnrType::SERVICE)] = 2;
-  expectation[CreateAnrKey(kAppTypeArcAppLauncher, mojom::AnrType::SERVICE)] =
-      1;
+  service()->ReportAnr(GetAnr(mojom::AnrSource::ARC_APP_LAUNCHER,
+                              mojom::AnrType::FOREGROUND_SERVICE));
+  expectation[CreateAnrKey(kAppOverall, mojom::AnrType::FOREGROUND_SERVICE)] =
+      2;
+  expectation[CreateAnrKey(kAppTypeArcAppLauncher,
+                           mojom::AnrType::FOREGROUND_SERVICE)] = 1;
   VerifyAnr(tester, expectation);
 }
 
diff --git a/ash/components/arc/midis/arc_midis_bridge.cc b/ash/components/arc/midis/arc_midis_bridge.cc
index e7eceb9..ec252b59 100644
--- a/ash/components/arc/midis/arc_midis_bridge.cc
+++ b/ash/components/arc/midis/arc_midis_bridge.cc
@@ -7,11 +7,11 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/arc/arc_midis_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/system/invitation.h"
diff --git a/ash/components/arc/midis/arc_midis_bridge_unittest.cc b/ash/components/arc/midis/arc_midis_bridge_unittest.cc
index c7ac4292..c6e91755 100644
--- a/ash/components/arc/midis/arc_midis_bridge_unittest.cc
+++ b/ash/components/arc/midis/arc_midis_bridge_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "ash/components/arc/midis/arc_midis_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/net/arc_net_host_impl.cc b/ash/components/arc/net/arc_net_host_impl.cc
index cf579e7..e81a6b52 100644
--- a/ash/components/arc/net/arc_net_host_impl.cc
+++ b/ash/components/arc/net/arc_net_host_impl.cc
@@ -8,6 +8,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/containers/cxx20_erase.h"
@@ -29,7 +30,6 @@
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "chromeos/network/onc/onc_utils.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "dbus/object_path.h"
diff --git a/ash/components/arc/net/arc_net_host_impl.h b/ash/components/arc/net/arc_net_host_impl.h
index df599bc3..c084ee5 100644
--- a/ash/components/arc/net/arc_net_host_impl.h
+++ b/ash/components/arc/net/arc_net_host_impl.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/weak_ptr.h"
@@ -20,7 +21,6 @@
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "components/arc/mojom/net.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/ash/components/arc/net/arc_net_host_impl_unittest.cc b/ash/components/arc/net/arc_net_host_impl_unittest.cc
index aca31074..506787d 100644
--- a/ash/components/arc/net/arc_net_host_impl_unittest.cc
+++ b/ash/components/arc/net/arc_net_host_impl_unittest.cc
@@ -7,8 +7,8 @@
 #include <string>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.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/obb_mounter/arc_obb_mounter_bridge.cc b/ash/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
index 06d806ac..1ea5e9e66 100644
--- a/ash/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
+++ b/ash/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
@@ -7,11 +7,11 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/arc/arc_obb_mounter_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 
diff --git a/ash/components/arc/pay/arc_digital_goods_bridge.cc b/ash/components/arc/pay/arc_digital_goods_bridge.cc
index 04c18c5..b60efb62 100644
--- a/ash/components/arc/pay/arc_digital_goods_bridge.cc
+++ b/ash/components/arc/pay/arc_digital_goods_bridge.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/no_destructor.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "third_party/blink/public/mojom/digital_goods/digital_goods.mojom.h"
 
 namespace arc {
diff --git a/ash/components/arc/pay/arc_payment_app_bridge.cc b/ash/components/arc/pay/arc_payment_app_bridge.cc
index 098cd7e5..34bebcf08 100644
--- a/ash/components/arc/pay/arc_payment_app_bridge.cc
+++ b/ash/components/arc/pay/arc_payment_app_bridge.cc
@@ -7,10 +7,10 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "base/no_destructor.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 namespace {
diff --git a/ash/components/arc/pay/arc_payment_app_bridge_unittest.cc b/ash/components/arc/pay/arc_payment_app_bridge_unittest.cc
index 3145f13..6cf79174 100644
--- a/ash/components/arc/pay/arc_payment_app_bridge_unittest.cc
+++ b/ash/components/arc/pay/arc_payment_app_bridge_unittest.cc
@@ -6,10 +6,10 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_payment_app_bridge_test_support.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/components/arc/power/arc_power_bridge.cc b/ash/components/arc/power/arc_power_bridge.cc
index 0247d24..11b6c5c4 100644
--- a/ash/components/arc/power/arc_power_bridge.cc
+++ b/ash/components/arc/power/arc_power_bridge.cc
@@ -9,6 +9,8 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/location.h"
@@ -17,8 +19,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/device_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
diff --git a/ash/components/arc/power/arc_power_bridge.h b/ash/components/arc/power/arc_power_bridge.h
index a4c587e7..a869d71 100644
--- a/ash/components/arc/power/arc_power_bridge.h
+++ b/ash/components/arc/power/arc_power_bridge.h
@@ -9,13 +9,13 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/mojom/anr.mojom.h"
 #include "components/arc/mojom/power.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
diff --git a/ash/components/arc/power/arc_power_bridge_unittest.cc b/ash/components/arc/power/arc_power_bridge_unittest.cc
index 1c7315148..89f9697 100644
--- a/ash/components/arc/power/arc_power_bridge_unittest.cc
+++ b/ash/components/arc/power/arc_power_bridge_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_power_instance.h"
 #include "base/run_loop.h"
@@ -14,7 +15,6 @@
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
 #include "components/arc/mojom/power.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
diff --git a/ash/components/arc/property/arc_property_bridge.cc b/ash/components/arc/property/arc_property_bridge.cc
index 39e3905..329f57a7b 100644
--- a/ash/components/arc/property/arc_property_bridge.cc
+++ b/ash/components/arc/property/arc_property_bridge.cc
@@ -8,10 +8,10 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/field_trial.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 namespace {
diff --git a/ash/components/arc/property/arc_property_bridge.h b/ash/components/arc/property/arc_property_bridge.h
index 87b4c796..7c1b593 100644
--- a/ash/components/arc/property/arc_property_bridge.h
+++ b/ash/components/arc/property/arc_property_bridge.h
@@ -7,9 +7,9 @@
 
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/threading/thread_checker.h"
 #include "components/arc/mojom/property.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/ash/components/arc/property/arc_property_bridge_unittest.cc b/ash/components/arc/property/arc_property_bridge_unittest.cc
index 8ce752b..7560000 100644
--- a/ash/components/arc/property/arc_property_bridge_unittest.cc
+++ b/ash/components/arc/property/arc_property_bridge_unittest.cc
@@ -6,10 +6,10 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/test/scoped_field_trial_list_resetter.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
diff --git a/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.cc b/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
index b72e0d8..77772bf 100644
--- a/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
+++ b/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
@@ -5,10 +5,10 @@
 #include "ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h"
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/shell.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/memory/singleton.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
diff --git a/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h b/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h
index 1b8579b..1d6efdf2 100644
--- a/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h
+++ b/ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h
@@ -5,11 +5,11 @@
 #ifndef ASH_COMPONENTS_ARC_ROTATION_LOCK_ARC_ROTATION_LOCK_BRIDGE_H_
 #define ASH_COMPONENTS_ARC_ROTATION_LOCK_ARC_ROTATION_LOCK_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/display/screen_orientation_controller.h"
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "base/threading/thread_checker.h"
 #include "components/arc/mojom/rotation_lock.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/ash/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc b/ash/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc
index 1b6ad1b2..ea9b8f4 100644
--- a/ash/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc
+++ b/ash/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/sensor/arc_iio_sensor_bridge.cc b/ash/components/arc/sensor/arc_iio_sensor_bridge.cc
index 9db5068..ad53a9b 100644
--- a/ash/components/arc/sensor/arc_iio_sensor_bridge.cc
+++ b/ash/components/arc/sensor/arc_iio_sensor_bridge.cc
@@ -7,9 +7,9 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/memory/singleton.h"
 #include "chromeos/components/sensors/ash/sensor_hal_dispatcher.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 
diff --git a/ash/components/arc/sensor/arc_iio_sensor_bridge.h b/ash/components/arc/sensor/arc_iio_sensor_bridge.h
index 679ecd5..666c83c 100644
--- a/ash/components/arc/sensor/arc_iio_sensor_bridge.h
+++ b/ash/components/arc/sensor/arc_iio_sensor_bridge.h
@@ -5,10 +5,10 @@
 #ifndef ASH_COMPONENTS_ARC_SENSOR_ARC_IIO_SENSOR_BRIDGE_H_
 #define ASH_COMPONENTS_ARC_SENSOR_ARC_IIO_SENSOR_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/mojom/iio_sensor.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/ash/components/arc/sensor/arc_iio_sensor_bridge_unittest.cc b/ash/components/arc/sensor/arc_iio_sensor_bridge_unittest.cc
index fa09e38..07f60b4a 100644
--- a/ash/components/arc/sensor/arc_iio_sensor_bridge_unittest.cc
+++ b/ash/components/arc/sensor/arc_iio_sensor_bridge_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "ash/components/arc/sensor/arc_iio_sensor_bridge.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_iio_sensor_instance.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
diff --git a/ash/components/arc/sensor/arc_sensor_bridge.cc b/ash/components/arc/sensor/arc_sensor_bridge.cc
index 12fdcaa..17905089 100644
--- a/ash/components/arc/sensor/arc_sensor_bridge.cc
+++ b/ash/components/arc/sensor/arc_sensor_bridge.cc
@@ -7,13 +7,13 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/singleton.h"
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "chromeos/dbus/arc/arc_sensor_service_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/system/invitation.h"
 #include "mojo/public/cpp/system/platform_handle.h"
diff --git a/components/arc/session/BUILD.gn b/ash/components/arc/session/BUILD.gn
similarity index 98%
rename from components/arc/session/BUILD.gn
rename to ash/components/arc/session/BUILD.gn
index fc34fd4..34cbccc 100644
--- a/components/arc/session/BUILD.gn
+++ b/ash/components/arc/session/BUILD.gn
@@ -41,6 +41,7 @@
     "//ash/components/arc:arc_base_utils",
     "//ash/components/arc:arc_features",
     "//ash/components/arc:prefs",
+    "//ash/components/arc/enterprise",
     "//ash/constants:constants",
     "//ash/public/cpp",
     "//ash/public/cpp/external_arc:external_arc",
@@ -51,7 +52,6 @@
     "//chromeos/dbus/upstart",
     "//chromeos/memory:memory",
     "//chromeos/system:system",
-    "//components/arc/enterprise",
     "//components/arc/mojom",
     "//components/prefs:prefs",
     "//components/user_manager",
diff --git a/components/arc/session/OWNERS b/ash/components/arc/session/OWNERS
similarity index 100%
rename from components/arc/session/OWNERS
rename to ash/components/arc/session/OWNERS
diff --git a/components/arc/session/adb_sideloading_availability_delegate.h b/ash/components/arc/session/adb_sideloading_availability_delegate.h
similarity index 79%
rename from components/arc/session/adb_sideloading_availability_delegate.h
rename to ash/components/arc/session/adb_sideloading_availability_delegate.h
index 57494f20e..fcda37d 100644
--- a/components/arc/session/adb_sideloading_availability_delegate.h
+++ b/ash/components/arc/session/adb_sideloading_availability_delegate.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 COMPONENTS_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_H_
-#define COMPONENTS_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_H_
+#define ASH_COMPONENTS_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_H_
 
 #include "base/callback_forward.h"
 
@@ -24,4 +24,4 @@
 };
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_H_
diff --git a/components/arc/session/arc_bridge_host_impl.cc b/ash/components/arc/session/arc_bridge_host_impl.cc
similarity index 98%
rename from components/arc/session/arc_bridge_host_impl.cc
rename to ash/components/arc/session/arc_bridge_host_impl.cc
index 723404de..3812bb2 100644
--- a/components/arc/session/arc_bridge_host_impl.cc
+++ b/ash/components/arc/session/arc_bridge_host_impl.cc
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/arc_bridge_host_impl.h"
+#include "ash/components/arc/session/arc_bridge_host_impl.h"
 
 #include <algorithm>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/mojo_channel.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_manager.h"
 #include "ash/public/cpp/message_center/arc_notifications_host_initializer.h"
 #include "base/bind.h"
@@ -71,8 +73,6 @@
 #include "components/arc/mojom/wake_lock.mojom.h"
 #include "components/arc/mojom/wallpaper.mojom.h"
 #include "components/arc/mojom/webapk.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/mojo_channel.h"
 
 namespace arc {
 
diff --git a/components/arc/session/arc_bridge_host_impl.h b/ash/components/arc/session/arc_bridge_host_impl.h
similarity index 96%
rename from components/arc/session/arc_bridge_host_impl.h
rename to ash/components/arc/session/arc_bridge_host_impl.h
index 098bf2fb..bf46261d 100644
--- a/components/arc/session/arc_bridge_host_impl.h
+++ b/ash/components/arc/session/arc_bridge_host_impl.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_BRIDGE_HOST_IMPL_H_
-#define COMPONENTS_ARC_SESSION_ARC_BRIDGE_HOST_IMPL_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_BRIDGE_HOST_IMPL_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_BRIDGE_HOST_IMPL_H_
 
 #include <memory>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/threading/thread_checker.h"
 #include "components/arc/mojom/arc_bridge.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_holder.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -215,4 +215,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_BRIDGE_HOST_IMPL_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_BRIDGE_HOST_IMPL_H_
diff --git a/components/arc/session/arc_bridge_host_impl_unittest.cc b/ash/components/arc/session/arc_bridge_host_impl_unittest.cc
similarity index 98%
rename from components/arc/session/arc_bridge_host_impl_unittest.cc
rename to ash/components/arc/session/arc_bridge_host_impl_unittest.cc
index 18c5bb4..45bf765 100644
--- a/components/arc/session/arc_bridge_host_impl_unittest.cc
+++ b/ash/components/arc/session/arc_bridge_host_impl_unittest.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/arc_bridge_host_impl.h"
+#include "ash/components/arc/session/arc_bridge_host_impl.h"
 
 #include <memory>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "components/arc/mojom/arc_bridge.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/components/arc/session/arc_bridge_service.cc b/ash/components/arc/session/arc_bridge_service.cc
similarity index 98%
rename from components/arc/session/arc_bridge_service.cc
rename to ash/components/arc/session/arc_bridge_service.cc
index 5f1fbcb..5459220c 100644
--- a/components/arc/session/arc_bridge_service.cc
+++ b/ash/components/arc/session/arc_bridge_service.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 "components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 
 // These header is necessary for instantiation of ConnectionHolder.
 #include "components/arc/mojom/accessibility_helper.mojom.h"
diff --git a/components/arc/session/arc_bridge_service.h b/ash/components/arc/session/arc_bridge_service.h
similarity index 98%
rename from components/arc/session/arc_bridge_service.h
rename to ash/components/arc/session/arc_bridge_service.h
index c9f4e5e27..95e843f 100644
--- a/components/arc/session/arc_bridge_service.h
+++ b/ash/components/arc/session/arc_bridge_service.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_BRIDGE_SERVICE_H_
-#define COMPONENTS_ARC_SESSION_ARC_BRIDGE_SERVICE_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_BRIDGE_SERVICE_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_BRIDGE_SERVICE_H_
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/observer_list.h"
-#include "components/arc/session/connection_holder.h"
 
 namespace arc {
 
@@ -424,4 +424,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_BRIDGE_SERVICE_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_BRIDGE_SERVICE_H_
diff --git a/components/arc/session/arc_bridge_service_unittest.cc b/ash/components/arc/session/arc_bridge_service_unittest.cc
similarity index 95%
rename from components/arc/session/arc_bridge_service_unittest.cc
rename to ash/components/arc/session/arc_bridge_service_unittest.cc
index 80c2c1c3..8f69393 100644
--- a/components/arc/session/arc_bridge_service_unittest.cc
+++ b/ash/components/arc/session/arc_bridge_service_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 "components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 
 #include "base/scoped_observation.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/arc/session/arc_client_adapter.cc b/ash/components/arc/session/arc_client_adapter.cc
similarity index 79%
rename from components/arc/session/arc_client_adapter.cc
rename to ash/components/arc/session/arc_client_adapter.cc
index 0c46be6..8462c12d 100644
--- a/components/arc/session/arc_client_adapter.cc
+++ b/ash/components/arc/session/arc_client_adapter.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/arc_client_adapter.h"
 
 #include "ash/components/arc/arc_util.h"
-#include "components/arc/session/arc_container_client_adapter.h"
-#include "components/arc/session/arc_vm_client_adapter.h"
+#include "ash/components/arc/session/arc_container_client_adapter.h"
+#include "ash/components/arc/session/arc_vm_client_adapter.h"
 
 namespace arc {
 
diff --git a/components/arc/session/arc_client_adapter.h b/ash/components/arc/session/arc_client_adapter.h
similarity index 91%
rename from components/arc/session/arc_client_adapter.h
rename to ash/components/arc/session/arc_client_adapter.h
index 30e6415..ffae590 100644
--- a/components/arc/session/arc_client_adapter.h
+++ b/ash/components/arc/session/arc_client_adapter.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_CLIENT_ADAPTER_H_
-#define COMPONENTS_ARC_SESSION_ARC_CLIENT_ADAPTER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_CLIENT_ADAPTER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_CLIENT_ADAPTER_H_
 
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/arc_start_params.h"
+#include "ash/components/arc/session/arc_upgrade_params.h"
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/observer_list.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "components/arc/session/arc_start_params.h"
-#include "components/arc/session/arc_upgrade_params.h"
 
 namespace cryptohome {
 class Identification;
@@ -95,4 +95,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_CLIENT_ADAPTER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_CLIENT_ADAPTER_H_
diff --git a/components/arc/session/arc_client_adapter_unittest.cc b/ash/components/arc/session/arc_client_adapter_unittest.cc
similarity index 94%
rename from components/arc/session/arc_client_adapter_unittest.cc
rename to ash/components/arc/session/arc_client_adapter_unittest.cc
index 828be02..590fedf 100644
--- a/components/arc/session/arc_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_client_adapter_unittest.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/arc_client_adapter.h"
 
 #include <memory>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/command_line.h"
 #include "base/scoped_observation.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #include "chromeos/dbus/upstart/fake_upstart_client.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
diff --git a/components/arc/session/arc_container_client_adapter.cc b/ash/components/arc/session/arc_container_client_adapter.cc
similarity index 97%
rename from components/arc/session/arc_container_client_adapter.cc
rename to ash/components/arc/session/arc_container_client_adapter.cc
index 816baa0..e06a418 100644
--- a/components/arc/session/arc_container_client_adapter.cc
+++ b/ash/components/arc/session/arc_container_client_adapter.cc
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/arc_container_client_adapter.h"
+#include "ash/components/arc/session/arc_container_client_adapter.h"
 
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_upgrade_params.h"
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/notreached.h"
@@ -15,8 +17,6 @@
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/login_manager/arc.pb.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/arc_upgrade_params.h"
 
 namespace arc {
 namespace {
diff --git a/ash/components/arc/session/arc_container_client_adapter.h b/ash/components/arc/session/arc_container_client_adapter.h
new file mode 100644
index 0000000..425b899
--- /dev/null
+++ b/ash/components/arc/session/arc_container_client_adapter.h
@@ -0,0 +1,19 @@
+// Copyright 2018 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_COMPONENTS_ARC_SESSION_ARC_CONTAINER_CLIENT_ADAPTER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_CONTAINER_CLIENT_ADAPTER_H_
+
+#include <memory>
+
+#include "ash/components/arc/session/arc_client_adapter.h"
+
+namespace arc {
+
+// Returns an adapter for talking to session_manager via D-Bus.
+std::unique_ptr<ArcClientAdapter> CreateArcContainerClientAdapter();
+
+}  // namespace arc
+
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_CONTAINER_CLIENT_ADAPTER_H_
diff --git a/components/arc/session/arc_container_client_adapter_unittest.cc b/ash/components/arc/session/arc_container_client_adapter_unittest.cc
similarity index 98%
rename from components/arc/session/arc_container_client_adapter_unittest.cc
rename to ash/components/arc/session/arc_container_client_adapter_unittest.cc
index 7ddbeea..c84fd70 100644
--- a/components/arc/session/arc_container_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_container_client_adapter_unittest.cc
@@ -4,9 +4,9 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_container_client_adapter.h"
 #include "base/callback_helpers.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "components/arc/session/arc_container_client_adapter.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -204,7 +204,6 @@
                          ArcContainerClientAdapterDalvikMemoryProfileTest,
                          ::testing::ValuesIn(kDalvikMemoryProfileTestCases));
 
-
 TEST_P(ArcContainerClientAdapterDalvikMemoryProfileTest, Profile) {
   const auto& test_param = GetParam();
   StartParams start_params;
diff --git a/components/arc/session/arc_data_remover.cc b/ash/components/arc/session/arc_data_remover.cc
similarity index 97%
rename from components/arc/session/arc_data_remover.cc
rename to ash/components/arc/session/arc_data_remover.cc
index 104603f..e7e0e69 100644
--- a/components/arc/session/arc_data_remover.cc
+++ b/ash/components/arc/session/arc_data_remover.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 "components/arc/session/arc_data_remover.h"
+#include "ash/components/arc/session/arc_data_remover.h"
 
 #include <string>
 #include <utility>
diff --git a/components/arc/session/arc_data_remover.h b/ash/components/arc/session/arc_data_remover.h
similarity index 90%
rename from components/arc/session/arc_data_remover.h
rename to ash/components/arc/session/arc_data_remover.h
index 2fdf0f1..a62b085 100644
--- a/components/arc/session/arc_data_remover.h
+++ b/ash/components/arc/session/arc_data_remover.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 COMPONENTS_ARC_SESSION_ARC_DATA_REMOVER_H_
-#define COMPONENTS_ARC_SESSION_ARC_DATA_REMOVER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_DATA_REMOVER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_DATA_REMOVER_H_
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
@@ -56,4 +56,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_DATA_REMOVER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_DATA_REMOVER_H_
diff --git a/components/arc/session/arc_data_remover_unittest.cc b/ash/components/arc/session/arc_data_remover_unittest.cc
similarity index 98%
rename from components/arc/session/arc_data_remover_unittest.cc
rename to ash/components/arc/session/arc_data_remover_unittest.cc
index 486a574c..eb0179e1 100644
--- a/components/arc/session/arc_data_remover_unittest.cc
+++ b/ash/components/arc/session/arc_data_remover_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 "components/arc/session/arc_data_remover.h"
+#include "ash/components/arc/session/arc_data_remover.h"
 
 #include <memory>
 #include <string>
diff --git a/components/arc/session/arc_dlc_installer.cc b/ash/components/arc/session/arc_dlc_installer.cc
similarity index 98%
rename from components/arc/session/arc_dlc_installer.cc
rename to ash/components/arc/session/arc_dlc_installer.cc
index 4411d40a..be81a20 100644
--- a/components/arc/session/arc_dlc_installer.cc
+++ b/ash/components/arc/session/arc_dlc_installer.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 "components/arc/session/arc_dlc_installer.h"
+#include "ash/components/arc/session/arc_dlc_installer.h"
 
 #include "base/callback_helpers.h"
 #include "base/logging.h"
diff --git a/components/arc/session/arc_dlc_installer.h b/ash/components/arc/session/arc_dlc_installer.h
similarity index 95%
rename from components/arc/session/arc_dlc_installer.h
rename to ash/components/arc/session/arc_dlc_installer.h
index d4812a9d..e8033504 100644
--- a/components/arc/session/arc_dlc_installer.h
+++ b/ash/components/arc/session/arc_dlc_installer.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 COMPONENTS_ARC_SESSION_ARC_DLC_INSTALLER_H_
-#define COMPONENTS_ARC_SESSION_ARC_DLC_INSTALLER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_DLC_INSTALLER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_DLC_INSTALLER_H_
 
 #include <string>
 
@@ -109,4 +109,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_DLC_INSTALLER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_DLC_INSTALLER_H_
diff --git a/components/arc/session/arc_dlc_installer_unittest.cc b/ash/components/arc/session/arc_dlc_installer_unittest.cc
similarity index 99%
rename from components/arc/session/arc_dlc_installer_unittest.cc
rename to ash/components/arc/session/arc_dlc_installer_unittest.cc
index 377ebade..4e18a693 100644
--- a/components/arc/session/arc_dlc_installer_unittest.cc
+++ b/ash/components/arc/session/arc_dlc_installer_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 "components/arc/session/arc_dlc_installer.h"
+#include "ash/components/arc/session/arc_dlc_installer.h"
 
 #include <memory>
 #include <string>
diff --git a/components/arc/session/arc_instance_mode.cc b/ash/components/arc/session/arc_instance_mode.cc
similarity index 94%
rename from components/arc/session/arc_instance_mode.cc
rename to ash/components/arc/session/arc_instance_mode.cc
index 26a4793a..568e41c 100644
--- a/components/arc/session/arc_instance_mode.cc
+++ b/ash/components/arc/session/arc_instance_mode.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 "components/arc/session/arc_instance_mode.h"
+#include "ash/components/arc/session/arc_instance_mode.h"
 
 #include <string>
 
diff --git a/components/arc/session/arc_instance_mode.h b/ash/components/arc/session/arc_instance_mode.h
similarity index 81%
rename from components/arc/session/arc_instance_mode.h
rename to ash/components/arc/session/arc_instance_mode.h
index cf04a56d..b0b14e57 100644
--- a/components/arc/session/arc_instance_mode.h
+++ b/ash/components/arc/session/arc_instance_mode.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 COMPONENTS_ARC_SESSION_ARC_INSTANCE_MODE_H_
-#define COMPONENTS_ARC_SESSION_ARC_INSTANCE_MODE_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_INSTANCE_MODE_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_INSTANCE_MODE_H_
 
 #include <ostream>
 
@@ -27,4 +27,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_INSTANCE_MODE_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_INSTANCE_MODE_H_
diff --git a/components/arc/session/arc_instance_mode_unittest.cc b/ash/components/arc/session/arc_instance_mode_unittest.cc
similarity index 95%
rename from components/arc/session/arc_instance_mode_unittest.cc
rename to ash/components/arc/session/arc_instance_mode_unittest.cc
index 67d5386..abb179f6 100644
--- a/components/arc/session/arc_instance_mode_unittest.cc
+++ b/ash/components/arc/session/arc_instance_mode_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 "components/arc/session/arc_instance_mode.h"
+#include "ash/components/arc/session/arc_instance_mode.h"
 
 #include <sstream>
 
diff --git a/components/arc/session/arc_management_transition.cc b/ash/components/arc/session/arc_management_transition.cc
similarity index 93%
rename from components/arc/session/arc_management_transition.cc
rename to ash/components/arc/session/arc_management_transition.cc
index 43c466e..860d2b1 100644
--- a/components/arc/session/arc_management_transition.cc
+++ b/ash/components/arc/session/arc_management_transition.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 "components/arc/session/arc_management_transition.h"
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "base/notreached.h"
 
 namespace arc {
diff --git a/components/arc/session/arc_management_transition.h b/ash/components/arc/session/arc_management_transition.h
similarity index 82%
rename from components/arc/session/arc_management_transition.h
rename to ash/components/arc/session/arc_management_transition.h
index 9a9c3b5..76c77cc8 100644
--- a/components/arc/session/arc_management_transition.h
+++ b/ash/components/arc/session/arc_management_transition.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 COMPONENTS_ARC_SESSION_ARC_MANAGEMENT_TRANSITION_H_
-#define COMPONENTS_ARC_SESSION_ARC_MANAGEMENT_TRANSITION_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_MANAGEMENT_TRANSITION_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_MANAGEMENT_TRANSITION_H_
 
 #include <ostream>
 
@@ -31,4 +31,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_MANAGEMENT_TRANSITION_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_MANAGEMENT_TRANSITION_H_
diff --git a/components/arc/session/arc_management_transition_unittest.cc b/ash/components/arc/session/arc_management_transition_unittest.cc
similarity index 93%
rename from components/arc/session/arc_management_transition_unittest.cc
rename to ash/components/arc/session/arc_management_transition_unittest.cc
index 69c0548..30bd6aa7 100644
--- a/components/arc/session/arc_management_transition_unittest.cc
+++ b/ash/components/arc/session/arc_management_transition_unittest.cc
@@ -4,7 +4,7 @@
 
 #include <sstream>
 
-#include "components/arc/session/arc_management_transition.h"
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
diff --git a/components/arc/session/arc_service_manager.cc b/ash/components/arc/session/arc_service_manager.cc
similarity index 82%
rename from components/arc/session/arc_service_manager.cc
rename to ash/components/arc/session/arc_service_manager.cc
index 78de8c1..ceff126 100644
--- a/components/arc/session/arc_service_manager.cc
+++ b/ash/components/arc/session/arc_service_manager.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 "components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "base/check_op.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/arc_session_runner.h"
 
 namespace arc {
 namespace {
diff --git a/components/arc/session/arc_service_manager.h b/ash/components/arc/session/arc_service_manager.h
similarity index 94%
rename from components/arc/session/arc_service_manager.h
rename to ash/components/arc/session/arc_service_manager.h
index ac23446..08931c5 100644
--- a/components/arc/session/arc_service_manager.h
+++ b/ash/components/arc/session/arc_service_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 COMPONENTS_ARC_SESSION_ARC_SERVICE_MANAGER_H_
-#define COMPONENTS_ARC_SESSION_ARC_SERVICE_MANAGER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_SERVICE_MANAGER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_SERVICE_MANAGER_H_
 
 #include <memory>
 
@@ -85,4 +85,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_SERVICE_MANAGER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_SERVICE_MANAGER_H_
diff --git a/components/arc/session/arc_session.cc b/ash/components/arc/session/arc_session.cc
similarity index 89%
rename from components/arc/session/arc_session.cc
rename to ash/components/arc/session/arc_session.cc
index cbd54fd..1ff35aeb 100644
--- a/components/arc/session/arc_session.cc
+++ b/ash/components/arc/session/arc_session.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_session.h"
 
-#include "components/arc/session/arc_session_impl.h"
+#include "ash/components/arc/session/arc_session_impl.h"
 
 namespace arc {
 
diff --git a/components/arc/session/arc_session.h b/ash/components/arc/session/arc_session.h
similarity index 90%
rename from components/arc/session/arc_session.h
rename to ash/components/arc/session/arc_session.h
index 7dd8728..aa5c5d0 100644
--- a/components/arc/session/arc_session.h
+++ b/ash/components/arc/session/arc_session.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_SESSION_H_
-#define COMPONENTS_ARC_SESSION_ARC_SESSION_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_H_
 
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/adb_sideloading_availability_delegate.h"
+#include "ash/components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
+#include "ash/components/arc/session/arc_upgrade_params.h"
 #include "base/callback_forward.h"
 #include "base/observer_list.h"
-#include "components/arc/session/adb_sideloading_availability_delegate.h"
-#include "components/arc/session/arc_client_adapter.h"
-#include "components/arc/session/arc_stop_reason.h"
-#include "components/arc/session/arc_upgrade_params.h"
 
 namespace chromeos {
 class SchedulerConfigurationManagerBase;
@@ -119,4 +119,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_SESSION_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_H_
diff --git a/components/arc/session/arc_session_impl.cc b/ash/components/arc/session/arc_session_impl.cc
similarity index 98%
rename from components/arc/session/arc_session_impl.cc
rename to ash/components/arc/session/arc_session_impl.cc
index 9160fdb..f0e4640 100644
--- a/components/arc/session/arc_session_impl.cc
+++ b/ash/components/arc/session/arc_session_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 "components/arc/session/arc_session_impl.h"
+#include "ash/components/arc/session/arc_session_impl.h"
 
 #include <fcntl.h>
 #include <grp.h>
@@ -14,6 +14,8 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/session/arc_bridge_host_impl.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
@@ -34,8 +36,6 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/memory/memory.h"
 #include "chromeos/system/scheduler_configuration_manager_base.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
-#include "components/arc/session/arc_bridge_host_impl.h"
 #include "components/user_manager/user_manager.h"
 #include "components/version_info/channel.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -215,8 +215,7 @@
 ArcSessionDelegateImpl::ArcSessionDelegateImpl(
     ArcBridgeService* arc_bridge_service,
     version_info::Channel channel)
-    : arc_bridge_service_(arc_bridge_service),
-      channel_(channel) {}
+    : arc_bridge_service_(arc_bridge_service), channel_(channel) {}
 
 void ArcSessionDelegateImpl::CreateSocket(CreateSocketCallback callback) {
   base::ThreadPool::PostTaskAndReplyWithResult(
diff --git a/components/arc/session/arc_session_impl.h b/ash/components/arc/session/arc_session_impl.h
similarity index 97%
rename from components/arc/session/arc_session_impl.h
rename to ash/components/arc/session/arc_session_impl.h
index dba14bf8..0195945 100644
--- a/components/arc/session/arc_session_impl.h
+++ b/ash/components/arc/session/arc_session_impl.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_SESSION_IMPL_H_
-#define COMPONENTS_ARC_SESSION_ARC_SESSION_IMPL_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_IMPL_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_IMPL_H_
 
 #include <memory>
 #include <ostream>
 #include <string>
 
+#include "ash/components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/arc_session.h"
 #include "base/callback.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "chromeos/system/scheduler_configuration_manager_base.h"
-#include "components/arc/session/arc_client_adapter.h"
-#include "components/arc/session/arc_session.h"
 
 namespace base {
 struct SystemMemoryInfoKB;
@@ -305,4 +305,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_SESSION_IMPL_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_IMPL_H_
diff --git a/components/arc/session/arc_session_impl_unittest.cc b/ash/components/arc/session/arc_session_impl_unittest.cc
similarity index 99%
rename from components/arc/session/arc_session_impl_unittest.cc
rename to ash/components/arc/session/arc_session_impl_unittest.cc
index 85670c8..bf4b21bd 100644
--- a/components/arc/session/arc_session_impl_unittest.cc
+++ b/ash/components/arc/session/arc_session_impl_unittest.cc
@@ -10,6 +10,10 @@
 #include <utility>
 
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/arc_session_impl.h"
+#include "ash/components/arc/session/arc_start_params.h"
+#include "ash/components/arc/session/arc_upgrade_params.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_bridge_host.h"
 #include "ash/constants/ash_switches.h"
@@ -22,10 +26,6 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/system/scheduler_configuration_manager_base.h"
-#include "components/arc/session/arc_client_adapter.h"
-#include "components/arc/session/arc_session_impl.h"
-#include "components/arc/session/arc_start_params.h"
-#include "components/arc/session/arc_upgrade_params.h"
 #include "components/version_info/channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/arc/session/arc_session_runner.cc b/ash/components/arc/session/arc_session_runner.cc
similarity index 99%
rename from components/arc/session/arc_session_runner.cc
rename to ash/components/arc/session/arc_session_runner.cc
index b7505f4..4e09219 100644
--- a/components/arc/session/arc_session_runner.cc
+++ b/ash/components/arc/session/arc_session_runner.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 "components/arc/session/arc_session_runner.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 
 #include <utility>
 
diff --git a/components/arc/session/arc_session_runner.h b/ash/components/arc/session/arc_session_runner.h
similarity index 93%
rename from components/arc/session/arc_session_runner.h
rename to ash/components/arc/session/arc_session_runner.h
index 6e071b7..a18b131 100644
--- a/components/arc/session/arc_session_runner.h
+++ b/ash/components/arc/session/arc_session_runner.h
@@ -2,23 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_SESSION_RUNNER_H_
-#define COMPONENTS_ARC_SESSION_ARC_SESSION_RUNNER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_RUNNER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_RUNNER_H_
 
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/arc_instance_mode.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
+#include "ash/components/arc/session/arc_upgrade_params.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "components/arc/session/arc_client_adapter.h"
-#include "components/arc/session/arc_instance_mode.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/arc_stop_reason.h"
-#include "components/arc/session/arc_upgrade_params.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace arc {
@@ -190,4 +190,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_SESSION_RUNNER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_SESSION_RUNNER_H_
diff --git a/components/arc/session/arc_session_runner_unittest.cc b/ash/components/arc/session/arc_session_runner_unittest.cc
similarity index 98%
rename from components/arc/session/arc_session_runner_unittest.cc
rename to ash/components/arc/session/arc_session_runner_unittest.cc
index 843da35..3d605c5 100644
--- a/components/arc/session/arc_session_runner_unittest.cc
+++ b/ash/components/arc/session/arc_session_runner_unittest.cc
@@ -6,6 +6,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -15,7 +16,6 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -343,8 +343,7 @@
   ASSERT_TRUE(arc_session());
   EXPECT_TRUE(arc_session()->is_running());
   // Checks if the restart retains the original parameter.
-  EXPECT_EQ(std::string(kDefaultLocale),
-            arc_session()->upgrade_locale_param());
+  EXPECT_EQ(std::string(kDefaultLocale), arc_session()->upgrade_locale_param());
 
   arc_session_runner()->RequestStop();
   EXPECT_FALSE(arc_session());
diff --git a/components/arc/session/arc_start_params.cc b/ash/components/arc/session/arc_start_params.cc
similarity index 87%
rename from components/arc/session/arc_start_params.cc
rename to ash/components/arc/session/arc_start_params.cc
index 5062b95..be210f4 100644
--- a/components/arc/session/arc_start_params.cc
+++ b/ash/components/arc/session/arc_start_params.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 "components/arc/session/arc_start_params.h"
+#include "ash/components/arc/session/arc_start_params.h"
 
 namespace arc {
 
diff --git a/components/arc/session/arc_start_params.h b/ash/components/arc/session/arc_start_params.h
similarity index 94%
rename from components/arc/session/arc_start_params.h
rename to ash/components/arc/session/arc_start_params.h
index 729d194..fd16d34 100644
--- a/components/arc/session/arc_start_params.h
+++ b/ash/components/arc/session/arc_start_params.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 COMPONENTS_ARC_SESSION_ARC_START_PARAMS_H_
-#define COMPONENTS_ARC_SESSION_ARC_START_PARAMS_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_START_PARAMS_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_START_PARAMS_H_
 
 #include <stdint.h>
 
@@ -98,4 +98,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_START_PARAMS_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_START_PARAMS_H_
diff --git a/components/arc/session/arc_stop_reason.cc b/ash/components/arc/session/arc_stop_reason.cc
similarity index 91%
rename from components/arc/session/arc_stop_reason.cc
rename to ash/components/arc/session/arc_stop_reason.cc
index 953fcce..eb9a9fb5 100644
--- a/components/arc/session/arc_stop_reason.cc
+++ b/ash/components/arc/session/arc_stop_reason.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 "components/arc/session/arc_stop_reason.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
 
 namespace arc {
 
diff --git a/components/arc/session/arc_stop_reason.h b/ash/components/arc/session/arc_stop_reason.h
similarity index 87%
rename from components/arc/session/arc_stop_reason.h
rename to ash/components/arc/session/arc_stop_reason.h
index aff37d5..d0adb1cf 100644
--- a/components/arc/session/arc_stop_reason.h
+++ b/ash/components/arc/session/arc_stop_reason.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 COMPONENTS_ARC_SESSION_ARC_STOP_REASON_H_
-#define COMPONENTS_ARC_SESSION_ARC_STOP_REASON_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_STOP_REASON_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_STOP_REASON_H_
 
 #include <ostream>
 
@@ -37,4 +37,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_STOP_REASON_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_STOP_REASON_H_
diff --git a/components/arc/session/arc_stop_reason_unittest.cc b/ash/components/arc/session/arc_stop_reason_unittest.cc
similarity index 93%
rename from components/arc/session/arc_stop_reason_unittest.cc
rename to ash/components/arc/session/arc_stop_reason_unittest.cc
index 967e5c636..fa167d3 100644
--- a/components/arc/session/arc_stop_reason_unittest.cc
+++ b/ash/components/arc/session/arc_stop_reason_unittest.cc
@@ -4,7 +4,7 @@
 
 #include <sstream>
 
-#include "components/arc/session/arc_stop_reason.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
diff --git a/components/arc/session/arc_upgrade_params.cc b/ash/components/arc/session/arc_upgrade_params.cc
similarity index 96%
rename from components/arc/session/arc_upgrade_params.cc
rename to ash/components/arc/session/arc_upgrade_params.cc
index 293e6ee..10989b529 100644
--- a/components/arc/session/arc_upgrade_params.cc
+++ b/ash/components/arc/session/arc_upgrade_params.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 "components/arc/session/arc_upgrade_params.h"
+#include "ash/components/arc/session/arc_upgrade_params.h"
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/constants/ash_switches.h"
diff --git a/components/arc/session/arc_upgrade_params.h b/ash/components/arc/session/arc_upgrade_params.h
similarity index 92%
rename from components/arc/session/arc_upgrade_params.h
rename to ash/components/arc/session/arc_upgrade_params.h
index b326375..4dc07d9 100644
--- a/components/arc/session/arc_upgrade_params.h
+++ b/ash/components/arc/session/arc_upgrade_params.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_UPGRADE_PARAMS_H_
-#define COMPONENTS_ARC_SESSION_ARC_UPGRADE_PARAMS_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_UPGRADE_PARAMS_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_UPGRADE_PARAMS_H_
 
 #include <stdint.h>
 
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "base/files/file_path.h"
-#include "components/arc/session/arc_management_transition.h"
 
 namespace arc {
 
@@ -94,4 +94,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_UPGRADE_PARAMS_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_UPGRADE_PARAMS_H_
diff --git a/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc
similarity index 98%
rename from components/arc/session/arc_vm_client_adapter.cc
rename to ash/components/arc/session/arc_vm_client_adapter.cc
index 467a90f..98b56b9 100644
--- a/components/arc/session/arc_vm_client_adapter.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter.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 "components/arc/session/arc_vm_client_adapter.h"
+#include "ash/components/arc/session/arc_vm_client_adapter.h"
 
 #include <inttypes.h>
 #include <sys/socket.h>
@@ -19,6 +19,12 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_dlc_installer.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/connection_holder.h"
+#include "ash/components/arc/session/file_system_status.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -57,12 +63,6 @@
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/system/core_scheduling.h"
 #include "chromeos/system/statistics_provider.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_dlc_installer.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/connection_holder.h"
-#include "components/arc/session/file_system_status.h"
 #include "components/version_info/version_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/components/arc/session/arc_vm_client_adapter.h b/ash/components/arc/session/arc_vm_client_adapter.h
similarity index 86%
rename from components/arc/session/arc_vm_client_adapter.h
rename to ash/components/arc/session/arc_vm_client_adapter.h
index f5215aa..eb1cae9 100644
--- a/components/arc/session/arc_vm_client_adapter.h
+++ b/ash/components/arc/session/arc_vm_client_adapter.h
@@ -2,21 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
-#define COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
+#define ASH_COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
 
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/arc_client_adapter.h"
+#include "ash/components/arc/session/file_system_status.h"
 #include "base/callback.h"
-#include "components/arc/session/arc_client_adapter.h"
-#include "components/arc/session/file_system_status.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
 struct SystemMemoryInfoKB;
 class TimeDelta;
-}
+}  // namespace base
 
 namespace arc {
 
@@ -71,4 +71,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
similarity index 99%
rename from components/arc/session/arc_vm_client_adapter_unittest.cc
rename to ash/components/arc/session/arc_vm_client_adapter_unittest.cc
index 62b23dc..6264712 100644
--- a/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter_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 "components/arc/session/arc_vm_client_adapter.h"
+#include "ash/components/arc/session/arc_vm_client_adapter.h"
 
 #include <inttypes.h>
 #include <sys/socket.h>
@@ -18,6 +18,11 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_dlc_installer.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/file_system_status.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_host.h"
 #include "ash/components/arc/test/fake_app_instance.h"
@@ -48,11 +53,6 @@
 #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/upstart/fake_upstart_client.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_dlc_installer.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/file_system_status.h"
 #include "components/user_manager/user_names.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/arc/session/connection_holder.h b/ash/components/arc/session/connection_holder.h
similarity index 97%
rename from components/arc/session/connection_holder.h
rename to ash/components/arc/session/connection_holder.h
index cb6ed997..454b4ccf 100644
--- a/components/arc/session/connection_holder.h
+++ b/ash/components/arc/session/connection_holder.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
-#define COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
+#define ASH_COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
 
 #include <memory>
 #include <type_traits>
 #include <utility>
 
+#include "ash/components/arc/session/connection_notifier.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/threading/thread_checker.h"
-#include "components/arc/session/connection_notifier.h"
-#include "components/arc/session/connection_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
 // A macro to call
@@ -345,4 +345,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
diff --git a/components/arc/session/connection_notifier.cc b/ash/components/arc/session/connection_notifier.cc
similarity index 89%
rename from components/arc/session/connection_notifier.cc
rename to ash/components/arc/session/connection_notifier.cc
index 398b07f..3443f770 100644
--- a/components/arc/session/connection_notifier.cc
+++ b/ash/components/arc/session/connection_notifier.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/session/connection_notifier.h"
+#include "ash/components/arc/session/connection_notifier.h"
 
-#include "components/arc/session/connection_observer.h"
+#include "ash/components/arc/session/connection_observer.h"
 
 namespace arc {
 namespace internal {
diff --git a/components/arc/session/connection_notifier.h b/ash/components/arc/session/connection_notifier.h
similarity index 85%
rename from components/arc/session/connection_notifier.h
rename to ash/components/arc/session/connection_notifier.h
index bf82b79..27e47bc 100644
--- a/components/arc/session/connection_notifier.h
+++ b/ash/components/arc/session/connection_notifier.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 COMPONENTS_ARC_SESSION_CONNECTION_NOTIFIER_H_
-#define COMPONENTS_ARC_SESSION_CONNECTION_NOTIFIER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_CONNECTION_NOTIFIER_H_
+#define ASH_COMPONENTS_ARC_SESSION_CONNECTION_NOTIFIER_H_
 
 #include "base/observer_list.h"
 #include "base/threading/thread_checker.h"
@@ -41,4 +41,4 @@
 }  // namespace internal
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_CONNECTION_NOTIFIER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_CONNECTION_NOTIFIER_H_
diff --git a/components/arc/session/connection_observer.h b/ash/components/arc/session/connection_observer.h
similarity index 85%
rename from components/arc/session/connection_observer.h
rename to ash/components/arc/session/connection_observer.h
index a12f2d7..248538f 100644
--- a/components/arc/session/connection_observer.h
+++ b/ash/components/arc/session/connection_observer.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 COMPONENTS_ARC_SESSION_CONNECTION_OBSERVER_H_
-#define COMPONENTS_ARC_SESSION_CONNECTION_OBSERVER_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_CONNECTION_OBSERVER_H_
+#define ASH_COMPONENTS_ARC_SESSION_CONNECTION_OBSERVER_H_
 
 namespace arc {
 namespace internal {
@@ -35,4 +35,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_CONNECTION_OBSERVER_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_CONNECTION_OBSERVER_H_
diff --git a/components/arc/session/file_system_status.cc b/ash/components/arc/session/file_system_status.cc
similarity index 97%
rename from components/arc/session/file_system_status.cc
rename to ash/components/arc/session/file_system_status.cc
index 428b835..411c5e0 100644
--- a/components/arc/session/file_system_status.cc
+++ b/ash/components/arc/session/file_system_status.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 "components/arc/session/file_system_status.h"
+#include "ash/components/arc/session/file_system_status.h"
 
 #include <linux/magic.h>
 #include <sys/statvfs.h>
diff --git a/components/arc/session/file_system_status.h b/ash/components/arc/session/file_system_status.h
similarity index 94%
rename from components/arc/session/file_system_status.h
rename to ash/components/arc/session/file_system_status.h
index c5242ff..d2901c3a 100644
--- a/components/arc/session/file_system_status.h
+++ b/ash/components/arc/session/file_system_status.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 COMPONENTS_ARC_SESSION_FILE_SYSTEM_STATUS_H_
-#define COMPONENTS_ARC_SESSION_FILE_SYSTEM_STATUS_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_FILE_SYSTEM_STATUS_H_
+#define ASH_COMPONENTS_ARC_SESSION_FILE_SYSTEM_STATUS_H_
 
 #include "base/files/file_path.h"
 
@@ -84,4 +84,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_FILE_SYSTEM_STATUS_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_FILE_SYSTEM_STATUS_H_
diff --git a/components/arc/session/file_system_status_unittest.cc b/ash/components/arc/session/file_system_status_unittest.cc
similarity index 97%
rename from components/arc/session/file_system_status_unittest.cc
rename to ash/components/arc/session/file_system_status_unittest.cc
index 70805cf6..1adf615c 100644
--- a/components/arc/session/file_system_status_unittest.cc
+++ b/ash/components/arc/session/file_system_status_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 "components/arc/session/file_system_status.h"
+#include "ash/components/arc/session/file_system_status.h"
 
 #include <string.h>
 
diff --git a/components/arc/session/mojo_channel.h b/ash/components/arc/session/mojo_channel.h
similarity index 89%
rename from components/arc/session/mojo_channel.h
rename to ash/components/arc/session/mojo_channel.h
index 365f500..a012e14 100644
--- a/components/arc/session/mojo_channel.h
+++ b/ash/components/arc/session/mojo_channel.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 COMPONENTS_ARC_SESSION_MOJO_CHANNEL_H_
-#define COMPONENTS_ARC_SESSION_MOJO_CHANNEL_H_
+#ifndef ASH_COMPONENTS_ARC_SESSION_MOJO_CHANNEL_H_
+#define ASH_COMPONENTS_ARC_SESSION_MOJO_CHANNEL_H_
 
 #include <utility>
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/bind.h"
-#include "components/arc/session/connection_holder.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
@@ -66,4 +66,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_SESSION_MOJO_CHANNEL_H_
+#endif  // ASH_COMPONENTS_ARC_SESSION_MOJO_CHANNEL_H_
diff --git a/ash/components/arc/storage_manager/arc_storage_manager.cc b/ash/components/arc/storage_manager/arc_storage_manager.cc
index 05288c8..16d76aab 100644
--- a/ash/components/arc/storage_manager/arc_storage_manager.cc
+++ b/ash/components/arc/storage_manager/arc_storage_manager.cc
@@ -7,9 +7,9 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 namespace {
diff --git a/ash/components/arc/storage_manager/arc_storage_manager_unittest.cc b/ash/components/arc/storage_manager/arc_storage_manager_unittest.cc
index 72a183d1..a13639e 100644
--- a/ash/components/arc/storage_manager/arc_storage_manager_unittest.cc
+++ b/ash/components/arc/storage_manager/arc_storage_manager_unittest.cc
@@ -4,12 +4,12 @@
 
 #include "ash/components/arc/storage_manager/arc_storage_manager.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_storage_manager_instance.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "base/test/bind.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/test/arc_payment_app_bridge_test_support.cc b/ash/components/arc/test/arc_payment_app_bridge_test_support.cc
index eea637d6..ce57aa7 100644
--- a/ash/components/arc/test/arc_payment_app_bridge_test_support.cc
+++ b/ash/components/arc/test/arc_payment_app_bridge_test_support.cc
@@ -4,7 +4,7 @@
 
 #include "ash/components/arc/test/arc_payment_app_bridge_test_support.h"
 
-#include "components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 
diff --git a/ash/components/arc/test/arc_payment_app_bridge_test_support.h b/ash/components/arc/test/arc_payment_app_bridge_test_support.h
index 4b9d183..96a2692c 100644
--- a/ash/components/arc/test/arc_payment_app_bridge_test_support.h
+++ b/ash/components/arc/test/arc_payment_app_bridge_test_support.h
@@ -9,9 +9,9 @@
 #include <string>
 
 #include "ash/components/arc/pay/arc_payment_app_bridge.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "components/arc/mojom/payment_app.mojom.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
diff --git a/ash/components/arc/test/connection_holder_util.h b/ash/components/arc/test/connection_holder_util.h
index 0740ef35..7180729 100644
--- a/ash/components/arc/test/connection_holder_util.h
+++ b/ash/components/arc/test/connection_holder_util.h
@@ -7,9 +7,9 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/callback_helpers.h"
 #include "base/run_loop.h"
-#include "components/arc/session/connection_holder.h"
 
 namespace arc {
 
diff --git a/ash/components/arc/test/fake_adbd_monitor_instance.h b/ash/components/arc/test/fake_adbd_monitor_instance.h
index 7dd4625..417bf5e4 100644
--- a/ash/components/arc/test/fake_adbd_monitor_instance.h
+++ b/ash/components/arc/test/fake_adbd_monitor_instance.h
@@ -5,8 +5,8 @@
 #ifndef ASH_COMPONENTS_ARC_TEST_FAKE_ADBD_MONITOR_INSTANCE_H_
 #define ASH_COMPONENTS_ARC_TEST_FAKE_ADBD_MONITOR_INSTANCE_H_
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "components/arc/mojom/adbd.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
diff --git a/ash/components/arc/test/fake_app_host.h b/ash/components/arc/test/fake_app_host.h
index 810fff8..fc0cf62 100644
--- a/ash/components/arc/test/fake_app_host.h
+++ b/ash/components/arc/test/fake_app_host.h
@@ -5,8 +5,8 @@
 #ifndef ASH_COMPONENTS_ARC_TEST_FAKE_APP_HOST_H_
 #define ASH_COMPONENTS_ARC_TEST_FAKE_APP_HOST_H_
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/connection_holder.h"
 
 namespace arc {
 
diff --git a/ash/components/arc/test/fake_apps_tracker.h b/ash/components/arc/test/fake_apps_tracker.h
index 0813db0..58a96f2 100644
--- a/ash/components/arc/test/fake_apps_tracker.h
+++ b/ash/components/arc/test/fake_apps_tracker.h
@@ -5,8 +5,8 @@
 #ifndef ASH_COMPONENTS_ARC_TEST_FAKE_APPS_TRACKER_H_
 #define ASH_COMPONENTS_ARC_TEST_FAKE_APPS_TRACKER_H_
 
+#include "ash/components/arc/enterprise/arc_apps_tracker.h"
 #include "base/callback.h"
-#include "components/arc/enterprise/arc_apps_tracker.h"
 
 namespace arc {
 namespace data_snapshotd {
diff --git a/ash/components/arc/test/fake_arc_session.h b/ash/components/arc/test/fake_arc_session.h
index 7114f9d..ad0f02a 100644
--- a/ash/components/arc/test/fake_arc_session.h
+++ b/ash/components/arc/test/fake_arc_session.h
@@ -8,8 +8,8 @@
 #include <memory>
 #include <string>
 
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/arc_stop_reason.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
 
 namespace cryptohome {
 class Identification;
diff --git a/ash/components/arc/test/fake_snapshot_reboot_notification.h b/ash/components/arc/test/fake_snapshot_reboot_notification.h
index fa14b34..8f2e0d0 100644
--- a/ash/components/arc/test/fake_snapshot_reboot_notification.h
+++ b/ash/components/arc/test/fake_snapshot_reboot_notification.h
@@ -5,8 +5,8 @@
 #ifndef ASH_COMPONENTS_ARC_TEST_FAKE_SNAPSHOT_REBOOT_NOTIFICATION_H_
 #define ASH_COMPONENTS_ARC_TEST_FAKE_SNAPSHOT_REBOOT_NOTIFICATION_H_
 
+#include "ash/components/arc/enterprise/arc_snapshot_reboot_notification.h"
 #include "base/callback.h"
-#include "components/arc/enterprise/arc_snapshot_reboot_notification.h"
 
 namespace arc {
 namespace data_snapshotd {
diff --git a/ash/components/arc/timer/arc_timer_bridge.cc b/ash/components/arc/timer/arc_timer_bridge.cc
index 197924fe..23582005 100644
--- a/ash/components/arc/timer/arc_timer_bridge.cc
+++ b/ash/components/arc/timer/arc_timer_bridge.cc
@@ -5,6 +5,8 @@
 #include <set>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/timer/arc_timer_bridge.h"
 #include "ash/components/arc/timer/arc_timer_mojom_traits.h"
 #include "base/bind.h"
@@ -15,8 +17,6 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "mojo/public/cpp/system/handle.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/ash/components/arc/timer/arc_timer_bridge.h b/ash/components/arc/timer/arc_timer_bridge.h
index b70b0d18..3275592e 100644
--- a/ash/components/arc/timer/arc_timer_bridge.h
+++ b/ash/components/arc/timer/arc_timer_bridge.h
@@ -10,11 +10,11 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
 #include "components/arc/mojom/timer.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/ash/components/arc/timer/arc_timer_bridge_unittest.cc b/ash/components/arc/timer/arc_timer_bridge_unittest.cc
index c6b85f0675..c5cbb62 100644
--- a/ash/components/arc/timer/arc_timer_bridge_unittest.cc
+++ b/ash/components/arc/timer/arc_timer_bridge_unittest.cc
@@ -7,6 +7,9 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_timer_instance.h"
 #include "ash/components/arc/test/test_browser_context.h"
@@ -21,9 +24,6 @@
 #include "base/time/time.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/mojom/timer.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/test/browser_task_environment.h"
 #include "mojo/public/cpp/system/handle.h"
diff --git a/ash/components/arc/usb/usb_host_bridge.cc b/ash/components/arc/usb/usb_host_bridge.cc
index ad58f03..3bb72cd 100644
--- a/ash/components/arc/usb/usb_host_bridge.cc
+++ b/ash/components/arc/usb/usb_host_bridge.cc
@@ -9,6 +9,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/usb/usb_host_ui_delegate.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -17,7 +18,6 @@
 #include "base/memory/singleton.h"
 #include "base/strings/stringprintf.h"
 #include "chromeos/dbus/permission_broker/permission_broker_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/device_service.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/ash/components/arc/usb/usb_host_bridge.h b/ash/components/arc/usb/usb_host_bridge.h
index 683cb31..72a44d0 100644
--- a/ash/components/arc/usb/usb_host_bridge.h
+++ b/ash/components/arc/usb/usb_host_bridge.h
@@ -9,10 +9,10 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/sequence_checker.h"
 #include "components/arc/mojom/usb_host.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/components/arc/usb/usb_host_bridge_unittest.cc b/ash/components/arc/usb/usb_host_bridge_unittest.cc
index 560b440..acbae22 100644
--- a/ash/components/arc/usb/usb_host_bridge_unittest.cc
+++ b/ash/components/arc/usb/usb_host_bridge_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "ash/components/arc/usb/usb_host_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/arc/video_accelerator/BUILD.gn b/ash/components/arc/video_accelerator/BUILD.gn
similarity index 100%
rename from components/arc/video_accelerator/BUILD.gn
rename to ash/components/arc/video_accelerator/BUILD.gn
diff --git a/components/arc/video_accelerator/DEPS b/ash/components/arc/video_accelerator/DEPS
similarity index 100%
rename from components/arc/video_accelerator/DEPS
rename to ash/components/arc/video_accelerator/DEPS
diff --git a/components/arc/video_accelerator/OWNERS b/ash/components/arc/video_accelerator/OWNERS
similarity index 100%
rename from components/arc/video_accelerator/OWNERS
rename to ash/components/arc/video_accelerator/OWNERS
diff --git a/components/arc/video_accelerator/arc_video_accelerator_util.cc b/ash/components/arc/video_accelerator/arc_video_accelerator_util.cc
similarity index 96%
rename from components/arc/video_accelerator/arc_video_accelerator_util.cc
rename to ash/components/arc/video_accelerator/arc_video_accelerator_util.cc
index bc20a47..faa91d2 100644
--- a/components/arc/video_accelerator/arc_video_accelerator_util.cc
+++ b/ash/components/arc/video_accelerator/arc_video_accelerator_util.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 "components/arc/video_accelerator/arc_video_accelerator_util.h"
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
 
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 #include "base/files/file_util.h"
 #include "base/files/platform_file.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
 #include "media/base/video_frame.h"
 #include "media/gpu/buffer_validation.h"
 #include "media/gpu/macros.h"
diff --git a/components/arc/video_accelerator/arc_video_accelerator_util.h b/ash/components/arc/video_accelerator/arc_video_accelerator_util.h
similarity index 86%
rename from components/arc/video_accelerator/arc_video_accelerator_util.h
rename to ash/components/arc/video_accelerator/arc_video_accelerator_util.h
index b15ea9a6..fd8ec72 100644
--- a/components/arc/video_accelerator/arc_video_accelerator_util.h
+++ b/ash/components/arc/video_accelerator/arc_video_accelerator_util.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
 
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/video_accelerator/video_frame_plane.h"
 #include "base/files/scoped_file.h"
-#include "components/arc/video_accelerator/video_frame_plane.h"
 #include "media/base/color_plane_layout.h"
 #include "media/base/video_types.h"
 #include "mojo/public/cpp/system/handle.h"
@@ -53,4 +53,4 @@
                     const base::ScopedFD& fd);
 
 }  // namespace arc
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
diff --git a/ash/components/arc/video_accelerator/arc_video_accelerator_util_unittest.cc b/ash/components/arc/video_accelerator/arc_video_accelerator_util_unittest.cc
index c342c2c..37cc6a74 100644
--- a/ash/components/arc/video_accelerator/arc_video_accelerator_util_unittest.cc
+++ b/ash/components/arc/video_accelerator/arc_video_accelerator_util_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 "components/arc/video_accelerator/arc_video_accelerator_util.h"
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
 
 #include "base/files/scoped_file.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc b/ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
similarity index 98%
rename from components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
rename to ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
index 8fcba7e..7d87a7b 100644
--- a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
 
 #include <memory>
 #include <utility>
 
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 #include "base/bind.h"
 #include "base/files/scoped_file.h"
 #include "base/metrics/histogram_functions.h"
@@ -15,8 +17,6 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
-#include "components/arc/video_accelerator/arc_video_accelerator_util.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
 #include "media/base/media_log.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_types.h"
diff --git a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h b/ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
similarity index 97%
rename from components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
rename to ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
index 7d30c2e..b0b989e 100644
--- a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
 
 #include <memory>
 #include <queue>
@@ -84,6 +84,7 @@
   void ReusePictureBuffer(int32_t picture_buffer_id) override;
   void Flush(FlushCallback callback) override;
   void Reset(ResetCallback callback) override;
+
  private:
   using PendingCallback =
       base::OnceCallback<void(mojom::VideoDecodeAccelerator::Result)>;
@@ -196,4 +197,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/components/arc/video_accelerator/gpu_arc_video_decoder.cc b/ash/components/arc/video_accelerator/gpu_arc_video_decoder.cc
similarity index 98%
rename from components/arc/video_accelerator/gpu_arc_video_decoder.cc
rename to ash/components/arc/video_accelerator/gpu_arc_video_decoder.cc
index 37115c0..b91d6bc 100644
--- a/components/arc/video_accelerator/gpu_arc_video_decoder.cc
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_decoder.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/video_accelerator/gpu_arc_video_decoder.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_decoder.h"
 
 #include <utility>
 
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 #include "base/bind.h"
 #include "base/files/scoped_file.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
-#include "components/arc/video_accelerator/arc_video_accelerator_util.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
 #include "media/base/media_util.h"
 #include "media/base/video_codecs.h"
 #include "media/base/video_frame.h"
diff --git a/components/arc/video_accelerator/gpu_arc_video_decoder.h b/ash/components/arc/video_accelerator/gpu_arc_video_decoder.h
similarity index 97%
rename from components/arc/video_accelerator/gpu_arc_video_decoder.h
rename to ash/components/arc/video_accelerator/gpu_arc_video_decoder.h
index f32fecc9..e6b02fc 100644
--- a/components/arc/video_accelerator/gpu_arc_video_decoder.h
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_decoder.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
 
 #include <map>
 #include <memory>
@@ -200,4 +200,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
diff --git a/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
similarity index 98%
rename from components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
rename to ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
index aca9d5f..fedac047 100644
--- a/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
 
 #include <utility>
 
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/memory/platform_shared_memory_region.h"
@@ -14,7 +15,6 @@
 #include "base/numerics/safe_conversions.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/system/sys_info.h"
-#include "components/arc/video_accelerator/arc_video_accelerator_util.h"
 #include "media/base/bitrate.h"
 #include "media/base/color_plane_layout.h"
 #include "media/base/format_utils.h"
diff --git a/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
similarity index 92%
rename from components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
rename to ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
index 8376588..ea23d56 100644
--- a/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
 
 #include <memory>
 #include <unordered_map>
 #include <vector>
 
+#include "ash/components/arc/video_accelerator/video_frame_plane.h"
 #include "base/files/scoped_file.h"
 #include "components/arc/mojom/video_encode_accelerator.mojom.h"
-#include "components/arc/video_accelerator/video_frame_plane.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_preferences.h"
 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
@@ -100,4 +100,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
diff --git a/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.cc b/ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.cc
similarity index 88%
rename from components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.cc
rename to ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.cc
index 91fa440e..e1ef580 100644
--- a/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.cc
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h"
 
 #include <limits>
 #include <utility>
 
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_allocator.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 #include "base/files/platform_file.h"
 #include "base/files/scoped_file.h"
 #include "base/numerics/safe_conversions.h"
-#include "components/arc/video_accelerator/arc_video_accelerator_util.h"
-#include "components/arc/video_accelerator/protected_buffer_allocator.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
 #include "media/base/format_utils.h"
 #include "media/gpu/macros.h"
 #include "mojo/public/c/system/types.h"
@@ -29,9 +29,8 @@
           protected_buffer_manager);
   if (!protected_buffer_allocator)
     return nullptr;
-  return std::unique_ptr<GpuArcVideoProtectedBufferAllocator>(
-      new GpuArcVideoProtectedBufferAllocator(
-          std::move(protected_buffer_allocator)));
+  return base::WrapUnique(new GpuArcVideoProtectedBufferAllocator(
+      std::move(protected_buffer_allocator)));
 }
 
 GpuArcVideoProtectedBufferAllocator::GpuArcVideoProtectedBufferAllocator(
diff --git a/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h b/ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
similarity index 87%
rename from components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
rename to ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
index b33df8f..18936fe 100644
--- a/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_PROTECTED_BUFFER_ALLOCATOR_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_PROTECTED_BUFFER_ALLOCATOR_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_PROTECTED_BUFFER_ALLOCATOR_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_PROTECTED_BUFFER_ALLOCATOR_H_
 
 #include <memory>
 
@@ -55,4 +55,4 @@
 };
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_PROTECTED_BUFFER_ALLOCATOR_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_PROTECTED_BUFFER_ALLOCATOR_H_
diff --git a/components/arc/video_accelerator/protected_buffer_allocator.h b/ash/components/arc/video_accelerator/protected_buffer_allocator.h
similarity index 88%
rename from components/arc/video_accelerator/protected_buffer_allocator.h
rename to ash/components/arc/video_accelerator/protected_buffer_allocator.h
index 7834a3a..aab6e0d 100644
--- a/components/arc/video_accelerator/protected_buffer_allocator.h
+++ b/ash/components/arc/video_accelerator/protected_buffer_allocator.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
 
 #include "base/files/scoped_file.h"
 #include "ui/gfx/buffer_types.h"
@@ -41,4 +41,4 @@
 };
 
 }  // namespace arc
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
diff --git a/components/arc/video_accelerator/protected_buffer_manager.cc b/ash/components/arc/video_accelerator/protected_buffer_manager.cc
similarity index 98%
rename from components/arc/video_accelerator/protected_buffer_manager.cc
rename to ash/components/arc/video_accelerator/protected_buffer_manager.cc
index 71bcba0..4cc1bab 100644
--- a/components/arc/video_accelerator/protected_buffer_manager.cc
+++ b/ash/components/arc/video_accelerator/protected_buffer_manager.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 
 #include <utility>
 
+#include "ash/components/arc/video_accelerator/protected_buffer_allocator.h"
 #include "base/bind.h"
 #include "base/bits.h"
 #include "base/logging.h"
@@ -14,7 +15,6 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/system/sys_info.h"
 #include "base/threading/thread_checker.h"
-#include "components/arc/video_accelerator/protected_buffer_allocator.h"
 #include "media/gpu/macros.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/ozone/public/ozone_platform.h"
diff --git a/components/arc/video_accelerator/protected_buffer_manager.h b/ash/components/arc/video_accelerator/protected_buffer_manager.h
similarity index 96%
rename from components/arc/video_accelerator/protected_buffer_manager.h
rename to ash/components/arc/video_accelerator/protected_buffer_manager.h
index 845fad1..e19cdfed 100644
--- a/components/arc/video_accelerator/protected_buffer_manager.h
+++ b/ash/components/arc/video_accelerator/protected_buffer_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 COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
 
 #include <map>
 #include <memory>
@@ -136,4 +136,4 @@
 };
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
diff --git a/components/arc/video_accelerator/protected_buffer_manager_proxy.cc b/ash/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
similarity index 83%
rename from components/arc/video_accelerator/protected_buffer_manager_proxy.cc
rename to ash/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
index b9e3dad..9f0ed997 100644
--- a/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
+++ b/ash/components/arc/video_accelerator/protected_buffer_manager_proxy.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 "components/arc/video_accelerator/protected_buffer_manager_proxy.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager_proxy.h"
 
-#include "components/arc/video_accelerator/arc_video_accelerator_util.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
+#include "ash/components/arc/video_accelerator/arc_video_accelerator_util.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 #include "media/gpu/macros.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/components/arc/video_accelerator/protected_buffer_manager_proxy.h b/ash/components/arc/video_accelerator/protected_buffer_manager_proxy.h
similarity index 82%
rename from components/arc/video_accelerator/protected_buffer_manager_proxy.h
rename to ash/components/arc/video_accelerator/protected_buffer_manager_proxy.h
index 53594a5f..d8fe68f3 100644
--- a/components/arc/video_accelerator/protected_buffer_manager_proxy.h
+++ b/ash/components/arc/video_accelerator/protected_buffer_manager_proxy.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
 
 #include "components/arc/mojom/protected_buffer_manager.mojom.h"
 
@@ -36,4 +36,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
diff --git a/components/arc/video_accelerator/video_frame_plane.h b/ash/components/arc/video_accelerator/video_frame_plane.h
similarity index 61%
rename from components/arc/video_accelerator/video_frame_plane.h
rename to ash/components/arc/video_accelerator/video_frame_plane.h
index 2b45a61..9c3305e 100644
--- a/components/arc/video_accelerator/video_frame_plane.h
+++ b/ash/components/arc/video_accelerator/video_frame_plane.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 COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
+#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
+#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
 
 #include <stdint.h>
 
@@ -16,4 +16,4 @@
 
 }  // namespace arc
 
-#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
+#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
diff --git a/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.cc b/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
index e75d81d..a06cde7 100644
--- a/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
+++ b/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
@@ -8,6 +8,7 @@
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
@@ -17,7 +18,6 @@
 #include "base/task/post_task.h"
 #include "chromeos/disks/disk.h"
 #include "chromeos/disks/disk_mount_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/browser_context.h"
diff --git a/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.h b/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.h
index e12e80c6..f17cba37 100644
--- a/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.h
+++ b/ash/components/arc/volume_mounter/arc_volume_mounter_bridge.h
@@ -7,11 +7,11 @@
 
 #include <string>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/arc/mojom/volume_mounter.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/keyed_service/core/keyed_service_base_factory.h"
 #include "components/prefs/pref_change_registrar.h"
diff --git a/ash/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc b/ash/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc
index 4ba6a8b..0c2fba55 100644
--- a/ash/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc
+++ b/ash/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc
@@ -4,10 +4,10 @@
 
 #include "ash/components/arc/volume_mounter/arc_volume_mounter_bridge.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/arc/wake_lock/arc_wake_lock_bridge.cc b/ash/components/arc/wake_lock/arc_wake_lock_bridge.cc
index 7efc1ef4..466c18fd 100644
--- a/ash/components/arc/wake_lock/arc_wake_lock_bridge.cc
+++ b/ash/components/arc/wake_lock/arc_wake_lock_bridge.cc
@@ -6,13 +6,13 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/wake_lock/arc_wake_lock_bridge.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/device_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
diff --git a/ash/components/arc/wake_lock/arc_wake_lock_bridge.h b/ash/components/arc/wake_lock/arc_wake_lock_bridge.h
index 64c8ea0..b710d00 100644
--- a/ash/components/arc/wake_lock/arc_wake_lock_bridge.h
+++ b/ash/components/arc/wake_lock/arc_wake_lock_bridge.h
@@ -8,9 +8,9 @@
 #include <map>
 #include <memory>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "components/arc/mojom/wake_lock.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/ash/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc b/ash/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
index e4fa5bd..30f7dc1 100644
--- a/ash/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
+++ b/ash/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_power_instance.h"
 #include "ash/components/arc/test/fake_wake_lock_instance.h"
@@ -14,7 +15,6 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "components/arc/mojom/power.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/ash/components/fwupd/firmware_update_manager.cc b/ash/components/fwupd/firmware_update_manager.cc
index fd05f44..1f31043 100644
--- a/ash/components/fwupd/firmware_update_manager.cc
+++ b/ash/components/fwupd/firmware_update_manager.cc
@@ -4,8 +4,11 @@
 
 #include "ash/components/fwupd/firmware_update_manager.h"
 
+#include <utility>
+
 #include "base/check_op.h"
 #include "base/containers/contains.h"
+#include "base/files/scoped_file.h"
 #include "chromeos/dbus/fwupd/fwupd_client.h"
 #include "dbus/message.h"
 
@@ -59,6 +62,14 @@
   chromeos::FwupdClient::Get()->RequestUpdates(device_id);
 }
 
+void FirmwareUpdateManager::InstallUpdate(
+    const std::string& device_id,
+    base::ScopedFD file_descriptor,
+    chromeos::FirmwareInstallOptions options) {
+  chromeos::FwupdClient::Get()->InstallUpdate(
+      device_id, std::move(file_descriptor), options);
+}
+
 void FirmwareUpdateManager::OnDeviceListResponse(
     chromeos::FwupdDeviceList* devices) {
   DCHECK(devices);
@@ -105,4 +116,8 @@
   return updates_;
 }
 
+void FirmwareUpdateManager::OnInstallResponse(bool success) {
+  ++on_install_update_response_count_for_testing_;
+}
+
 }  // namespace ash
diff --git a/ash/components/fwupd/firmware_update_manager.h b/ash/components/fwupd/firmware_update_manager.h
index 7505e05..c49d2e7f 100644
--- a/ash/components/fwupd/firmware_update_manager.h
+++ b/ash/components/fwupd/firmware_update_manager.h
@@ -9,6 +9,7 @@
 
 #include "base/component_export.h"
 #include "base/containers/flat_map.h"
+#include "base/files/scoped_file.h"
 #include "chromeos/dbus/fwupd/fwupd_client.h"
 #include "chromeos/dbus/fwupd/fwupd_device.h"
 #include "chromeos/dbus/fwupd/fwupd_update.h"
@@ -49,6 +50,7 @@
   // it calls this function and passes the response.
   void OnUpdateListResponse(const std::string& device_id,
                             chromeos::FwupdUpdateList* updates) override;
+  void OnInstallResponse(bool success) override;
 
   // Query all updates for all devices.
   void RequestAllUpdates();
@@ -58,12 +60,18 @@
   const std::vector<FirmwareUpdate>& GetCachedUpdatesForTesting();
 
  private:
+  friend class FirmwareUpdateManagerTest;
   // Query the fwupd DBus client for currently connected devices.
   void RequestDevices();
 
   // Query the fwupd DBus client for updates for a certain device.
   void RequestUpdates(const std::string& device_id);
 
+  // Query the fwupd DBus client to install an update for a certain device.
+  void InstallUpdate(const std::string& device_id,
+                     base::ScopedFD file_descriptor,
+                     chromeos::FirmwareInstallOptions options);
+
   // Map of a device ID to `FwupdDevice` which is waiting for the list
   // of updates.
   base::flat_map<std::string, chromeos::FwupdDevice> devices_pending_update_;
@@ -71,6 +79,14 @@
   // List of all available updates. If `devices_pending_update_` is not
   // empty then this list is not yet complete.
   std::vector<FirmwareUpdate> updates_;
+
+ protected:
+  friend class FirmwareUpdateManagerTest;
+  // Temporary auxiliary variables for testing.
+  // TODO(swifton): Replace with mock observers.
+  int on_device_list_response_count_for_testing_ = 0;
+  int on_update_list_response_count_for_testing_ = 0;
+  int on_install_update_response_count_for_testing_ = 0;
 };
 }  // namespace ash
 
diff --git a/ash/components/fwupd/firmware_update_manager_unittest.cc b/ash/components/fwupd/firmware_update_manager_unittest.cc
index 90c14da..e9ca4d5 100644
--- a/ash/components/fwupd/firmware_update_manager_unittest.cc
+++ b/ash/components/fwupd/firmware_update_manager_unittest.cc
@@ -5,7 +5,9 @@
 #include "ash/components/fwupd/firmware_update_manager.h"
 
 #include <deque>
+#include <map>
 #include <memory>
+#include <string>
 
 #include "ash/constants/ash_features.h"
 #include "base/test/scoped_feature_list.h"
@@ -89,6 +91,11 @@
   }
 
  protected:
+  void InstallUpdate(base::ScopedFD fd, std::map<std::string, bool> options) {
+    firmware_update_manager_->InstallUpdate(
+        kFakeDeviceIdForTesting, std::move(fd), std::map<std::string, bool>());
+  }
+
   std::unique_ptr<dbus::Response> CreateEmptyDeviceResponse() {
     auto response = dbus::Response::CreateEmpty();
 
@@ -235,6 +242,18 @@
     return response;
   }
 
+  std::unique_ptr<dbus::Response> CreateBoolResponse(bool success) {
+    auto response = dbus::Response::CreateEmpty();
+    dbus::MessageWriter response_writer(response.get());
+    response_writer.AppendBool(success);
+    return response;
+  }
+
+  int GetOnInstallResponseCallbackCallCountForTesting() {
+    return firmware_update_manager_
+        ->on_install_update_response_count_for_testing_;
+  }
+
   // `FwupdClient` must be be before `FirmwareUpdateManager`.
   std::unique_ptr<FwupdClient> dbus_client_;
   std::unique_ptr<FirmwareUpdateManager> firmware_update_manager_;
@@ -324,4 +343,18 @@
   EXPECT_EQ(kFakeUpdatePriorityForTesting, updates[0].priority);
 }
 
+// TODO(jimmyxgong): Rewrite this test with an observer.
+TEST_F(FirmwareUpdateManagerTest, RequestUpdateList) {
+  EXPECT_CALL(*proxy_, DoCallMethodWithErrorResponse(_, _, _))
+      .WillRepeatedly(Invoke(this, &FirmwareUpdateManagerTest::OnMethodCalled));
+
+  dbus_responses_.push_back(CreateBoolResponse(/**install_success=*/true));
+
+  EXPECT_EQ(0, GetOnInstallResponseCallbackCallCountForTesting());
+  InstallUpdate(base::ScopedFD(0), std::map<std::string, bool>());
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1, GetOnInstallResponseCallbackCallCountForTesting());
+}
+
 }  // namespace ash
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 9a879de..86647fc 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -391,10 +391,6 @@
 const base::Feature kDisableOfficeEditingComponentApp{
     "DisableOfficeEditingComponentApp", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Disables translation services of the Quick Answers V2.
-const base::Feature kDisableQuickAnswersV2Translation{
-    "DisableQuickAnswersV2Translation", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables indicators to hint where displays are connected.
 const base::Feature kDisplayAlignAssist{"DisplayAlignAssist",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
@@ -677,14 +673,14 @@
 // transfer or access it later.
 const base::Feature kHoldingSpaceInProgressDownloadsIntegration{
     "HoldingSpaceInProgressDownloadsIntegration",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables in-progress downloads notification suppression with the productivity
 // feature that aims to reduce context switching by enabling users to collect
 // content and transfer or access it later.
 const base::Feature kHoldingSpaceInProgressDownloadsNotificationSuppression{
     "HoldingSpaceInProgressNotificationSuppression",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables incognito profile integration with the productivity feature that
 // aims to reduce context switching by enabling users to collect content and
@@ -980,10 +976,6 @@
 const base::Feature kProjectorAnnotator{"ProjectorAnnotator",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Controls whether to enable quick answers V2 settings sub-toggles.
-const base::Feature kQuickAnswersV2SettingsSubToggle{
-    "QuickAnswersV2SettingsSubToggle", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables or disables the Quick Settings Network revamp, which updates Network
 // Quick Settings UI and related infrastructure. See https://crbug.com/1169479.
 const base::Feature kQuickSettingsNetworkRevamp{
@@ -1725,14 +1717,6 @@
          base::FeatureList::IsEnabled(kProjectorAnnotator);
 }
 
-bool IsQuickAnswersV2TranslationDisabled() {
-  return base::FeatureList::IsEnabled(kDisableQuickAnswersV2Translation);
-}
-
-bool IsQuickAnswersV2SettingsSubToggleEnabled() {
-  return base::FeatureList::IsEnabled(kQuickAnswersV2SettingsSubToggle);
-}
-
 bool IsQuickSettingsNetworkRevampEnabled() {
   return base::FeatureList::IsEnabled(kQuickSettingsNetworkRevamp);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index c97aa99..d04c6d0c 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -368,10 +368,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kProjectorFeaturePod;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kProjectorAnnotator;
 COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kDisableQuickAnswersV2Translation;
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kQuickAnswersV2SettingsSubToggle;
-COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kQuickSettingsNetworkRevamp;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kQuickUnlockFingerprint;
@@ -594,9 +590,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsProjectorEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsProjectorFeaturePodEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsProjectorAnnotatorEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsQuickAnswersV2Enabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsQuickAnswersV2TranslationDisabled();
-COMPONENT_EXPORT(ASH_CONSTANTS) bool IsQuickAnswersV2SettingsSubToggleEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsQuickSettingsNetworkRevampEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsReduceDisplayNotificationsEnabled();
diff --git a/ash/public/cpp/OWNERS b/ash/public/cpp/OWNERS
index ea1744a..4e2e8a0 100644
--- a/ash/public/cpp/OWNERS
+++ b/ash/public/cpp/OWNERS
@@ -1,3 +1,4 @@
+per-file *desk*template*=file://ash/wm/desks/templates/OWNERS
 per-file *login*=file://ash/login/OWNERS
 per-file *shelf*=file://ash/shelf/OWNERS
 per-file *wallpaper*=file://ash/wallpaper/OWNERS
diff --git a/ash/public/cpp/app_list/app_list_types.cc b/ash/public/cpp/app_list/app_list_types.cc
index 50ec09e..8daaeed 100644
--- a/ash/public/cpp/app_list/app_list_types.cc
+++ b/ash/public/cpp/app_list/app_list_types.cc
@@ -20,19 +20,6 @@
     default;
 AppListItemMetadata::~AppListItemMetadata() = default;
 
-// TODO: This method could be eliminated, by passing the action with result
-// action metadata instead of implicitly relying on order in which actions are
-// listed in SearchResult::actions().
-SearchResultActionType GetSearchResultActionType(int button_index) {
-  if (button_index < 0 ||
-      button_index >= static_cast<int>(
-                          SearchResultActionType::kSearchResultActionTypeMax)) {
-    return SearchResultActionType::kSearchResultActionTypeMax;
-  }
-
-  return static_cast<SearchResultActionType>(button_index);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // SearchResultIconInfo:
 
@@ -66,10 +53,12 @@
 
 SearchResultAction::SearchResultAction() {}
 
-SearchResultAction::SearchResultAction(const gfx::ImageSkia& image,
+SearchResultAction::SearchResultAction(SearchResultActionType type,
+                                       const gfx::ImageSkia& image,
                                        const std::u16string& tooltip_text,
                                        bool visible_on_hover)
-    : image(image),
+    : type(type),
+      image(image),
       tooltip_text(tooltip_text),
       visible_on_hover(visible_on_hover) {}
 
diff --git a/ash/public/cpp/app_list/app_list_types.h b/ash/public/cpp/app_list/app_list_types.h
index 442f1c5a..69fc52f 100644
--- a/ash/public/cpp/app_list/app_list_types.h
+++ b/ash/public/cpp/app_list/app_list_types.h
@@ -314,10 +314,6 @@
   SearchResultIconShape shape = SearchResultIconShape::kDefault;
 };
 
-// Returns SearchResultActionType mapped for |button_index|.
-ASH_PUBLIC_EXPORT SearchResultActionType
-GetSearchResultActionType(int button_index);
-
 // A tagged range in search result text.
 struct ASH_PUBLIC_EXPORT SearchResultTag {
   // Similar to ACMatchClassification::Style, the style values are not
@@ -343,12 +339,14 @@
 // button with the label text will be used.
 struct ASH_PUBLIC_EXPORT SearchResultAction {
   SearchResultAction();
-  SearchResultAction(const gfx::ImageSkia& image,
+  SearchResultAction(SearchResultActionType type,
+                     const gfx::ImageSkia& image,
                      const std::u16string& tooltip_text,
                      bool visible_on_hover);
   SearchResultAction(const SearchResultAction& other);
   ~SearchResultAction();
 
+  SearchResultActionType type;
   gfx::ImageSkia image;
   std::u16string tooltip_text;
   // Visible when button or its parent row in hover state.
diff --git a/ash/public/cpp/capture_mode/capture_mode_delegate.h b/ash/public/cpp/capture_mode/capture_mode_delegate.h
index 14c41789..e167d38d 100644
--- a/ash/public/cpp/capture_mode/capture_mode_delegate.h
+++ b/ash/public/cpp/capture_mode/capture_mode_delegate.h
@@ -87,8 +87,7 @@
   // Returns whether capture of the region defined by |window| and |bounds|
   // is currently allowed by Data Leak Prevention feature.
   virtual bool IsCaptureAllowedByDlp(const aura::Window* window,
-                                     const gfx::Rect& bounds,
-                                     bool for_video) const = 0;
+                                     const gfx::Rect& bounds) const = 0;
 
   // Returns whether screen capture is allowed by an enterprise policy.
   virtual bool IsCaptureAllowedByPolicy() const = 0;
diff --git a/ash/public/cpp/desks_templates_delegate.h b/ash/public/cpp/desks_templates_delegate.h
index 58c5c290..72087fe1 100644
--- a/ash/public/cpp/desks_templates_delegate.h
+++ b/ash/public/cpp/desks_templates_delegate.h
@@ -37,7 +37,7 @@
 class DeskTemplate;
 
 // This delegate is owned by Shell and used by ash/ to communicate with
-// DesksClient in chrome/.
+// DesksTemplatesClient in chrome/.
 class ASH_PUBLIC_EXPORT DesksTemplatesDelegate {
  public:
   virtual ~DesksTemplatesDelegate() = default;
diff --git a/ash/public/cpp/external_arc/BUILD.gn b/ash/public/cpp/external_arc/BUILD.gn
index 80bf86a..42547cd 100644
--- a/ash/public/cpp/external_arc/BUILD.gn
+++ b/ash/public/cpp/external_arc/BUILD.gn
@@ -38,12 +38,12 @@
     "//ash",
     "//ash/components/arc:arc_base_utils",
     "//ash/components/arc:arc_metrics_constants",
+    "//ash/components/arc/session:connection_holder",
     "//ash/constants",
     "//ash/public/cpp",
     "//base",
     "//components/account_id",
     "//components/arc/mojom:notifications",
-    "//components/arc/session:connection_holder",
     "//components/exo",
     "//mojo/public/cpp/system",
     "//ui/accessibility:accessibility",
@@ -73,9 +73,9 @@
     "//ash",
     "//ash:test_support",
     "//ash/components/arc:notification_test_support",
+    "//ash/components/arc/session:connection_holder",
     "//ash/public/cpp",
     "//base/test:test_support",
-    "//components/arc/session:connection_holder",
     "//components/exo",
     "//components/exo:test_support",
     "//testing/gmock",
diff --git a/ash/public/cpp/external_arc/message_center/DEPS b/ash/public/cpp/external_arc/message_center/DEPS
index 1eaaffd..b8dc5c2 100644
--- a/ash/public/cpp/external_arc/message_center/DEPS
+++ b/ash/public/cpp/external_arc/message_center/DEPS
@@ -1,10 +1,10 @@
 include_rules = [
+  "+ash/components/arc/session/connection_holder.h",
+  "+ash/components/arc/session/connection_observer.h",
+  "+ash/components/arc/session/mojo_channel.h",
   "+ash/system/message_center/message_view_factory.h",
   "+components/arc/mojom/notifications.mojom.h",
   "+components/arc/metrics/arc_metrics_constants.h",
-  "+components/arc/session/connection_holder.h",
-  "+components/arc/session/connection_observer.h",
-  "+components/arc/session/mojo_channel.h",
   "+components/arc/test/connection_holder_util.h",
   "+components/arc/test/fake_notifications_instance.h",
 ]
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc b/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc
index a93147b..e660d24 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_manager.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "ash/components/arc/session/mojo_channel.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/arc_app_id_provider.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_delegate.h"
@@ -19,7 +20,6 @@
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/strings/utf_string_conversions.h"
-#include "components/arc/session/mojo_channel.h"
 #include "ui/message_center/lock_screen/lock_screen_controller.h"
 #include "ui/message_center/message_center_impl.h"
 #include "ui/message_center/message_center_observer.h"
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_manager.h b/ash/public/cpp/external_arc/message_center/arc_notification_manager.h
index 319b7e3b..adf0edbe7 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_manager.h
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_manager.h
@@ -9,13 +9,13 @@
 #include <string>
 #include <unordered_map>
 
+#include "ash/components/arc/session/connection_holder.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/public/cpp/message_center/arc_notification_manager_base.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list_types.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/mojom/notifications.mojom.h"
-#include "components/arc/session/connection_holder.h"
-#include "components/arc/session/connection_observer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "ui/message_center/message_center.h"
 
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_manager_unittest.cc b/ash/public/cpp/external_arc/message_center/arc_notification_manager_unittest.cc
index 34d7d26..e40b37a 100644
--- a/ash/public/cpp/external_arc/message_center/arc_notification_manager_unittest.cc
+++ b/ash/public/cpp/external_arc/message_center/arc_notification_manager_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_notifications_instance.h"
 #include "ash/public/cpp/arc_app_id_provider.h"
@@ -15,7 +16,6 @@
 #include "ash/public/cpp/message_center/arc_notification_manager_delegate.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
-#include "components/arc/session/connection_holder.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ash/system/accessibility/floating_menu_button.h b/ash/system/accessibility/floating_menu_button.h
index 0c3f6d8..3bc1aee 100644
--- a/ash/system/accessibility/floating_menu_button.h
+++ b/ash/system/accessibility/floating_menu_button.h
@@ -77,7 +77,9 @@
 VIEW_BUILDER_PROPERTY(bool, A11yTogglable)
 VIEW_BUILDER_PROPERTY(bool, DrawHighlight)
 VIEW_BUILDER_PROPERTY(bool, Toggled)
-VIEW_BUILDER_PROPERTY(const gfx::VectorIcon&, VectorIcon)
+VIEW_BUILDER_PROPERTY(const gfx::VectorIcon&,
+                      VectorIcon,
+                      const gfx::VectorIcon&)
 END_VIEW_BUILDER
 
 }  // namespace ash
diff --git a/ash/system/time/calendar_event_list_item_view.cc b/ash/system/time/calendar_event_list_item_view.cc
new file mode 100644
index 0000000..f53f227
--- /dev/null
+++ b/ash/system/time/calendar_event_list_item_view.cc
@@ -0,0 +1,98 @@
+// 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 "ash/system/time/calendar_event_list_item_view.h"
+
+#include "ash/public/cpp/ash_typography.h"
+#include "ash/system/time/calendar_utils.h"
+#include "ash/system/tray/tray_popup_utils.h"
+#include "ash/system/tray/tri_view.h"
+#include "base/i18n/time_formatting.h"
+#include "base/strings/utf_string_conversions.h"
+#include "google_apis/calendar/calendar_api_response_types.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/events/event.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/vector_icons.h"
+#include "ui/views/view.h"
+
+namespace ash {
+namespace {
+
+// The meeting title is too long, it is truncated in this length.
+constexpr int kTruncatedTitleLength = 20;
+
+// Paddings in this view.
+constexpr int kEntryHorizontalPadding = 20;
+
+// Sets up the event label.
+void SetUpLabel(views::Label* label) {
+  label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_CENTER);
+  label->SetAutoColorReadabilityEnabled(false);
+  label->SetElideBehavior(gfx::NO_ELIDE);
+  label->SetSubpixelRenderingEnabled(false);
+  label->SetTextContext(CONTEXT_CALENDAR_DATE);
+}
+
+}  // namespace
+
+CalendarEventListItemView::CalendarEventListItemView(
+    google_apis::calendar::CalendarEvent event)
+    : ActionableView(TrayPopupInkDropStyle::FILL_BOUNDS),
+      summary_(new views::Label()),
+      time_range_(new views::Label()) {
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+  GetViewAccessibility().OverrideName(GetClassName());
+
+  // TODO(https://crbug.com/1238927) Implement the event color dot. Here an
+  // info icon is used as a place holder.
+  auto* color_dot = new views::ImageView();
+  color_dot->SetImage(gfx::CreateVectorIcon(
+      views::kInfoIcon, calendar_utils::GetPrimaryTextColor()));
+
+  summary_->SetText(base::UTF8ToUTF16(event.summary()));
+  SetUpLabel(summary_);
+  summary_->SetTruncateLength(kTruncatedTitleLength);
+  summary_->SetBorder(
+      views::CreateEmptyBorder(0, kEntryHorizontalPadding, 0, 0));
+
+  auto start_time = event.start_time().date_time();
+  auto end_time = event.end_time().date_time();
+  auto time_string = base::TimeFormatWithPattern(start_time, "h:mm a") +
+                     u" - " + base::TimeFormatWithPattern(end_time, "h:mm a");
+
+  time_range_->SetText(time_string);
+  SetUpLabel(time_range_);
+
+  // Creates a `TriView` which carries the `color_dot` and `summary_` at the
+  // entry start and the `time_range_` at the entry end.
+  TriView* tri_view = TrayPopupUtils::CreateDefaultRowView();
+  tri_view->AddView(TriView::Container::START, color_dot);
+  tri_view->AddView(TriView::Container::START, summary_);
+  tri_view->AddView(TriView::Container::END, time_range_);
+
+  AddChildView(tri_view);
+}
+
+CalendarEventListItemView::~CalendarEventListItemView() = default;
+
+void CalendarEventListItemView::OnThemeChanged() {
+  views::View::OnThemeChanged();
+  summary_->SetEnabledColor(calendar_utils::GetPrimaryTextColor());
+  time_range_->SetEnabledColor(calendar_utils::GetPrimaryTextColor());
+}
+
+bool CalendarEventListItemView::PerformAction(const ui::Event& event) {
+  // TODO(https://crbug.com/1270938): Launch web app implementation.
+  return true;
+}
+
+BEGIN_METADATA(CalendarEventListItemView, views::View);
+END_METADATA
+
+}  // namespace ash
diff --git a/ash/system/time/calendar_event_list_item_view.h b/ash/system/time/calendar_event_list_item_view.h
new file mode 100644
index 0000000..6d7ba0d
--- /dev/null
+++ b/ash/system/time/calendar_event_list_item_view.h
@@ -0,0 +1,56 @@
+// 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 ASH_SYSTEM_TIME_CALENDAR_EVENT_LIST_ITEM_VIEW_H_
+#define ASH_SYSTEM_TIME_CALENDAR_EVENT_LIST_ITEM_VIEW_H_
+
+#include "ash/ash_export.h"
+#include "ash/system/tray/actionable_view.h"
+#include "google_apis/calendar/calendar_api_response_types.h"
+
+namespace ui {
+
+class Event;
+
+}  // namespace ui
+
+namespace views {
+
+class Label;
+
+}  // namespace views
+
+namespace ash {
+
+// This view displays a calendar event entry.
+class ASH_EXPORT CalendarEventListItemView : public ActionableView {
+ public:
+  METADATA_HEADER(CalendarEventListItemView);
+
+  explicit CalendarEventListItemView(
+      google_apis::calendar::CalendarEvent event);
+  CalendarEventListItemView(const CalendarEventListItemView& other) = delete;
+  CalendarEventListItemView& operator=(const CalendarEventListItemView& other) =
+      delete;
+  ~CalendarEventListItemView() override;
+
+  // views::View:
+  void OnThemeChanged() override;
+
+  // ActionableView:
+  bool PerformAction(const ui::Event& event) override;
+
+ private:
+  friend class CalendarViewEventListViewTest;
+
+  // The summary (title) of the meeting event.
+  views::Label* const summary_;
+
+  // The start time and end time of a meeting event.
+  views::Label* const time_range_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_TIME_CALENDAR_EVENT_LIST_ITEM_VIEW_H_
diff --git a/ash/system/time/calendar_event_list_view.cc b/ash/system/time/calendar_event_list_view.cc
new file mode 100644
index 0000000..3ff4ccf
--- /dev/null
+++ b/ash/system/time/calendar_event_list_view.cc
@@ -0,0 +1,94 @@
+// 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 "ash/system/time/calendar_event_list_view.h"
+
+#include "ash/system/time/calendar_utils.h"
+#include "ash/system/time/calendar_view_controller.h"
+#include "ash/system/tray/tray_popup_utils.h"
+#include "ash/system/tray/tri_view.h"
+#include "calendar_event_list_item_view.h"
+#include "google_apis/calendar/calendar_api_response_types.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/vector_icons.h"
+#include "ui/views/view.h"
+
+namespace ash {
+namespace {
+
+// The paddings in `CalendarEventListView`.
+constexpr gfx::Insets kContentInsets{0, 20};
+
+}  // namespace
+
+CalendarEventListView::CalendarEventListView(
+    CalendarViewController* calendar_view_controller)
+    : calendar_view_controller_(calendar_view_controller),
+      close_button_(AddChildView(std::make_unique<views::ImageButton>(
+          views::Button::PressedCallback(base::BindRepeating(
+              &CalendarViewController::CloseEventListView,
+              base::Unretained(calendar_view_controller)))))),
+      scroll_view_(AddChildView(std::make_unique<views::ScrollView>())),
+      content_view_(
+          scroll_view_->SetContents(std::make_unique<views::View>())) {
+  SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical));
+
+  close_button_->SetImage(
+      views::ImageButton::STATE_NORMAL,
+      gfx::CreateVectorIcon(views::kIcCloseIcon,
+                            calendar_utils::GetPrimaryTextColor()));
+  close_button_->SetImageHorizontalAlignment(views::ImageButton::ALIGN_RIGHT);
+  close_button_->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+  close_button_->GetViewAccessibility().OverrideName(GetClassName());
+  close_button_->SetBorder(views::CreateEmptyBorder(kContentInsets));
+  close_button_->SetFocusBehavior(FocusBehavior::ALWAYS);
+  // TODO(https://crbug.com/1238927) set tool tip and accessible label
+  // close_button_->SetAccessibleName(close_button_label);
+  // close_button_->SetTooltipText(close_button_label);
+
+  scroll_view_->SetAllowKeyboardScrolling(false);
+  scroll_view_->SetBackgroundColor(absl::nullopt);
+  scroll_view_->ClipHeightTo(0, INT_MAX);
+  scroll_view_->SetDrawOverflowIndicator(false);
+  scroll_view_->SetVerticalScrollBarMode(
+      views::ScrollView::ScrollBarMode::kHiddenButEnabled);
+
+  content_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical));
+  content_view_->SetBorder(views::CreateEmptyBorder(kContentInsets));
+
+  UpdateListItems();
+
+  scoped_calendar_view_controller_observer_.Observe(calendar_view_controller_);
+}
+
+CalendarEventListView::~CalendarEventListView() = default;
+
+void CalendarEventListView::OnSelectedDateUpdated() {
+  UpdateListItems();
+}
+
+void CalendarEventListView::UpdateListItems() {
+  content_view_->RemoveAllChildViews();
+
+  for (google_apis::calendar::CalendarEvent event :
+       calendar_view_controller_->SelectedDateEvents()) {
+    auto* event_entry = content_view_->AddChildView(
+        std::make_unique<CalendarEventListItemView>(event));
+
+    // Needs to repaint the `content_view_`'s children.
+    event_entry->InvalidateLayout();
+  }
+}
+
+BEGIN_METADATA(CalendarEventListView, views::View);
+END_METADATA
+
+}  // namespace ash
diff --git a/ash/system/time/calendar_event_list_view.h b/ash/system/time/calendar_event_list_view.h
new file mode 100644
index 0000000..a0c6f9b
--- /dev/null
+++ b/ash/system/time/calendar_event_list_view.h
@@ -0,0 +1,59 @@
+// 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 ASH_SYSTEM_TIME_CALENDAR_EVENT_LIST_VIEW_H_
+#define ASH_SYSTEM_TIME_CALENDAR_EVENT_LIST_VIEW_H_
+
+#include "ash/ash_export.h"
+#include "ash/system/time/calendar_view_controller.h"
+#include "base/scoped_observation.h"
+#include "ui/views/view.h"
+
+namespace views {
+class ImageButton;
+}  // namespace views
+
+namespace ash {
+
+// This view displays a scrollable list of `CalendarEventListItemView`.
+class ASH_EXPORT CalendarEventListView
+    : public CalendarViewController::Observer,
+      public views::View {
+ public:
+  METADATA_HEADER(CalendarEventListView);
+
+  explicit CalendarEventListView(
+      CalendarViewController* calendar_view_controller);
+  CalendarEventListView(const CalendarEventListView& other) = delete;
+  CalendarEventListView& operator=(const CalendarEventListView& other) = delete;
+  ~CalendarEventListView() override;
+
+  // CalendarViewController::Observer:
+  void OnSelectedDateUpdated() override;
+
+ private:
+  friend class CalendarViewEventListViewTest;
+
+  // Updates the event list entries.
+  void UpdateListItems();
+
+  // Owned by `CalendarView`.
+  CalendarViewController* calendar_view_controller_;
+
+  // Owned by `CalendarEventListView`.
+  views::ImageButton* const close_button_;
+  views::ScrollView* const scroll_view_;
+
+  // The content of the `scroll_view_`, which carries a list of
+  // `CalendarEventListItemView`. Owned by `CalendarEventListView`.
+  views::View* const content_view_;
+
+  base::ScopedObservation<CalendarViewController,
+                          CalendarViewController::Observer>
+      scoped_calendar_view_controller_observer_{this};
+};
+
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_TIME_CALENDAR_EVENT_LIST_VIEW_H_
diff --git a/ash/system/time/calendar_event_list_view_unittest.cc b/ash/system/time/calendar_event_list_view_unittest.cc
new file mode 100644
index 0000000..1ebe747c
--- /dev/null
+++ b/ash/system/time/calendar_event_list_view_unittest.cc
@@ -0,0 +1,128 @@
+// 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 "ash/system/time/calendar_event_list_view.h"
+
+#include "ash/system/time/calendar_event_list_item_view.h"
+#include "ash/system/time/calendar_unittest_utils.h"
+#include "ash/system/time/calendar_view_controller.h"
+#include "ash/test/ash_test_base.h"
+#include "base/time/time.h"
+#include "ui/views/controls/label.h"
+
+namespace ash {
+
+namespace {
+
+std::unique_ptr<google_apis::calendar::EventList> CreateMockEventList() {
+  auto event_list = std::make_unique<google_apis::calendar::EventList>();
+  event_list->set_time_zone("America/Los_Angeles");
+
+  event_list->InjectItemForTesting(calendar_test_utils::CreateEvent(
+      "id_0", "summary_0", "18 Nov 2021 8:30 GMT", "18 Nov 2021 9:30 GMT"));
+  event_list->InjectItemForTesting(calendar_test_utils::CreateEvent(
+      "id_1", "summary_1", "18 Nov 2021 10:30 GMT", "18 Nov 2021 11:30 GMT"));
+  event_list->InjectItemForTesting(calendar_test_utils::CreateEvent(
+      "id_2", "summary_2", "18 Nov 2021 11:30 GMT", "18 Nov 2021 12:30 GMT"));
+  event_list->InjectItemForTesting(calendar_test_utils::CreateEvent(
+      "id_3", "summary_3", "19 Nov 2021 8:30 GMT", "19 Nov 2021 10:30 GMT"));
+  event_list->InjectItemForTesting(calendar_test_utils::CreateEvent(
+      "id_4", "summary_4", "21 Nov 2021 8:30 GMT", "21 Nov 2021 9:30 GMT"));
+  event_list->InjectItemForTesting(calendar_test_utils::CreateEvent(
+      "id_5", "summary_5", "21 Nov 2021 10:30 GMT", "21 Nov 2021 11:30 GMT"));
+
+  return event_list;
+}
+
+}  // namespace
+
+class CalendarViewEventListViewTest : public AshTestBase {
+ public:
+  CalendarViewEventListViewTest() = default;
+  CalendarViewEventListViewTest(const CalendarViewEventListViewTest&) = delete;
+  CalendarViewEventListViewTest& operator=(
+      const CalendarViewEventListViewTest&) = delete;
+  ~CalendarViewEventListViewTest() override = default;
+
+  void SetUp() override {
+    AshTestBase::SetUp();
+    controller_ = std::make_unique<CalendarViewController>();
+  }
+
+  void TearDown() override {
+    event_list_view_.reset();
+    controller_.reset();
+    AshTestBase::TearDown();
+  }
+
+  void CreateEventListView(base::Time date) {
+    event_list_view_.reset();
+    controller_->UpdateMonth(date);
+    controller_->InsertEvents(CreateMockEventList());
+    event_list_view_ =
+        std::make_unique<CalendarEventListView>(controller_.get());
+  }
+
+  void SetSelectedDate(base::Time::Exploded date) {
+    controller_->selected_date_ = date;
+    controller_->ShowEventListView(date, /*row_index=*/0);
+  }
+
+  CalendarEventListView* event_list_view() { return event_list_view_.get(); }
+  views::View* content_view() { return event_list_view_->content_view_; }
+  CalendarViewController* controller() { return controller_.get(); }
+
+  views::Label* GetSummary(int child_idex) {
+    return static_cast<views::Label*>(
+        static_cast<CalendarEventListItemView*>(
+            content_view()->children()[child_idex])
+            ->summary_);
+  }
+
+ private:
+  std::unique_ptr<CalendarEventListView> event_list_view_;
+  std::unique_ptr<CalendarViewController> controller_;
+};
+
+TEST_F(CalendarViewEventListViewTest, ShowEvents) {
+  base::Time date;
+  ASSERT_TRUE(base::Time::FromString("18 Nov 2021 10:00 GMT", &date));
+
+  CreateEventListView(date);
+
+  EXPECT_EQ(0u, content_view()->children().size());
+
+  base::Time::Exploded selected_date;
+  date.LocalExplode(&selected_date);
+  SetSelectedDate(selected_date);
+
+  // 3 events on 18 Nov 2021.
+  EXPECT_EQ(3u, content_view()->children().size());
+  EXPECT_EQ(u"summary_0", GetSummary(0)->GetText());
+  EXPECT_EQ(u"summary_1", GetSummary(1)->GetText());
+  EXPECT_EQ(u"summary_2", GetSummary(2)->GetText());
+
+  (date + base::Days(1)).LocalExplode(&selected_date);
+  SetSelectedDate(selected_date);
+
+  // 1 event on 19 Nov 2021.
+  EXPECT_EQ(1u, content_view()->children().size());
+  EXPECT_EQ(u"summary_3", GetSummary(0)->GetText());
+
+  (date + base::Days(2)).LocalExplode(&selected_date);
+  SetSelectedDate(selected_date);
+
+  // 0 event on 20 Nov 2021.
+  EXPECT_EQ(0u, content_view()->children().size());
+
+  (date + base::Days(3)).LocalExplode(&selected_date);
+  SetSelectedDate(selected_date);
+
+  // 2 events on 21 Nov 2021.
+  EXPECT_EQ(2u, content_view()->children().size());
+  EXPECT_EQ(u"summary_4", GetSummary(0)->GetText());
+  EXPECT_EQ(u"summary_5", GetSummary(1)->GetText());
+}
+
+}  // namespace ash
diff --git a/ash/system/time/calendar_month_view.cc b/ash/system/time/calendar_month_view.cc
index 5051bed..a352fb9 100644
--- a/ash/system/time/calendar_month_view.cc
+++ b/ash/system/time/calendar_month_view.cc
@@ -9,6 +9,7 @@
 #include "ash/system/time/calendar_utils.h"
 #include "ash/system/time/calendar_view_controller.h"
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
@@ -52,16 +53,22 @@
 CalendarDateCellView::CalendarDateCellView(
     CalendarViewController* calendar_view_controller,
     base::Time::Exploded& date,
-    bool is_grayed_out_date)
+    bool is_grayed_out_date,
+    int row_index)
     : views::LabelButton(
-          views::Button::PressedCallback(base::BindRepeating([]() {
-            // TODO(https://crbug.com/1238927): Add a menthod in the
-            // controller to open the expandable view and call it here.
-          })),
+          views::Button::PressedCallback(
+              is_grayed_out_date
+                  ? base::DoNothing()
+                  : base::BindRepeating(
+                        &CalendarViewController::ShowEventListView,
+                        base::Unretained(calendar_view_controller),
+                        date,
+                        row_index)),
           base::UTF8ToUTF16(base::NumberToString(date.day_of_month)),
           CONTEXT_CALENDAR_DATE),
       date_(date),
       grayed_out_(is_grayed_out_date),
+      row_index_(row_index),
       calendar_view_controller_(calendar_view_controller) {
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
   SetBorder(views::CreateEmptyBorder(calendar_utils::kDateCellInsets));
@@ -76,6 +83,8 @@
                 gfx::Insets(kFocusCirclePadding)));
 
   DisableFocus();
+
+  scoped_calendar_view_controller_observer_.Observe(calendar_view_controller_);
 }
 
 CalendarDateCellView::~CalendarDateCellView() = default;
@@ -91,14 +100,19 @@
 // Draws the background for 'today'. If today is a grayed out date, which is
 // shown in its previous/next month, we won't draw this background.
 void CalendarDateCellView::OnPaintBackground(gfx::Canvas* canvas) {
+  if (grayed_out_)
+    return;
+
   const AshColorProvider* color_provider = AshColorProvider::Get();
   const SkColor bg_color = color_provider->GetControlsLayerColor(
       AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive);
   const SkColor border_color = color_provider->GetControlsLayerColor(
       AshColorProvider::ControlsLayerType::kFocusRingColor);
 
-  // If the view is focused, paint a solid background.
-  if (views::View::HasFocus()) {
+  // If the view is focused or selected, paint a solid background.
+  is_selected_ = calendar_utils::IsTheSameDay(
+      date_, calendar_view_controller_->selected_date());
+  if (views::View::HasFocus() || is_selected_) {
     // Change text color to the background color.
     const SkColor text_color = color_provider->GetBaseLayerColor(
         AshColorProvider::BaseLayerType::kTransparent90);
@@ -121,7 +135,7 @@
   SetEnabledTextColors(grayed_out_ ? calendar_utils::GetSecondaryTextColor()
                                    : calendar_utils::GetPrimaryTextColor());
 
-  if (grayed_out_ || !calendar_utils::IsToday(date_))
+  if (!calendar_utils::IsToday(date_))
     return;
 
   cc::PaintFlags highlight_background;
@@ -143,6 +157,25 @@
   canvas->DrawCircle(center, kTodayRoundedRadius, highlight_border);
 }
 
+void CalendarDateCellView::OnSelectedDateUpdated() {
+  bool is_selected = calendar_utils::IsTheSameDay(
+      date_, calendar_view_controller_->selected_date());
+  // If the selected day changes, repaint the background.
+  if (is_selected_ != is_selected) {
+    is_selected_ = is_selected;
+    SchedulePaint();
+  }
+}
+
+void CalendarDateCellView::CloseEventList() {
+  if (!is_selected_)
+    return;
+
+  // If this date is selected, repaint the background.
+  is_selected_ = false;
+  SchedulePaint();
+}
+
 void CalendarDateCellView::EnableFocus() {
   if (grayed_out_)
     return;
@@ -210,20 +243,23 @@
   while (current_date_exploded.month % 12 ==
          (first_day_of_month_exploded.month - 1) % 12) {
     AddDateCellToLayout(current_date_exploded, column,
-                        /*is_in_current_month=*/false);
+                        /*is_in_current_month=*/false, /*row_index=*/0);
     MoveToNextDay(column, current_date, current_date_exploded);
   }
 
   int row_number = 0;
   // Builds non-gray-out dates of the current month.
   while (current_date_exploded.month == first_day_of_month_exploded.month) {
+    // Count a row when a new row starts.
+    if (column == 0 || current_date_exploded.day_of_month == 1) {
+      ++row_number;
+    }
     auto* cell = AddDateCellToLayout(current_date_exploded, column,
-                                     /*is_in_current_month=*/true);
+                                     /*is_in_current_month=*/true,
+                                     /*row_index=*/row_number - 1);
     // Add the first non-grayed-out cell of the row to the `focused_cells_`.
     if (column == 0 || current_date_exploded.day_of_month == 1) {
       focused_cells_.push_back(cell);
-      // Count a row when a new row starts.
-      ++row_number;
     }
     // If this row has today, updates today's row number and replaces today to
     // the last element in the `focused_cells_`.
@@ -254,7 +290,8 @@
          end_of_row_exploded.day_of_month) {
     // Next column is generated.
     AddDateCellToLayout(current_date_exploded, column,
-                        /*is_in_current_month=*/false);
+                        /*is_in_current_month=*/false,
+                        /*row_index=*/row_number);
     MoveToNextDay(column, current_date, current_date_exploded);
   }
 }
@@ -264,13 +301,14 @@
 CalendarDateCellView* CalendarMonthView::AddDateCellToLayout(
     base::Time::Exploded current_date_exploded,
     int column,
-    bool is_in_current_month) {
+    bool is_in_current_month,
+    int row_index) {
   auto* layout_manager = static_cast<views::TableLayout*>(GetLayoutManager());
   if (column == 0)
     layout_manager->AddRows(1, views::TableLayout::kFixedSize);
   return AddChildView(std::make_unique<CalendarDateCellView>(
       calendar_view_controller_, current_date_exploded,
-      /*is_grayed_out_date=*/!is_in_current_month));
+      /*is_grayed_out_date=*/!is_in_current_month, /*row_index=*/row_index));
 }
 
 void CalendarMonthView::EnableFocus() {
diff --git a/ash/system/time/calendar_month_view.h b/ash/system/time/calendar_month_view.h
index 37e86302..6aadaf55 100644
--- a/ash/system/time/calendar_month_view.h
+++ b/ash/system/time/calendar_month_view.h
@@ -6,22 +6,24 @@
 #define ASH_SYSTEM_TIME_CALENDAR_MONTH_VIEW_H_
 
 #include "ash/ash_export.h"
+#include "ash/system/time/calendar_view_controller.h"
+#include "base/scoped_observation.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/view.h"
 
 namespace ash {
 
-class CalendarViewController;
-
 // Renders a Calendar date cell. Pass in `true` as `is_grayed_out_date` if
 // the date is not in the current month view's month.
-class CalendarDateCellView : public views::LabelButton {
+class CalendarDateCellView : public CalendarViewController::Observer,
+                             public views::LabelButton {
  public:
   METADATA_HEADER(CalendarDateCellView);
 
   CalendarDateCellView(CalendarViewController* calendar_view_controller,
                        base::Time::Exploded& date,
-                       bool is_grayed_out_date);
+                       bool is_grayed_out_date,
+                       int row_index);
   CalendarDateCellView(const CalendarDateCellView& other) = delete;
   CalendarDateCellView& operator=(const CalendarDateCellView& other) = delete;
   ~CalendarDateCellView() override;
@@ -33,12 +35,19 @@
   // shown in its previous/next month, we won't draw this background.
   void OnPaintBackground(gfx::Canvas* canvas) override;
 
+  // CalendarViewController::Observer:
+  void OnSelectedDateUpdated() override;
+  void CloseEventList() override;
+
   // Enables focus behavior of this cell.
   void EnableFocus();
 
   // Disables focus behavior of this cell.
   void DisableFocus();
 
+  // The row index in the date's month view.
+  int row_index() const { return row_index_; }
+
  protected:
   // views::Button:
   void PaintButtonContents(gfx::Canvas* canvas) override;
@@ -55,8 +64,18 @@
 
   const bool grayed_out_;
 
+  // The row index in the current month for this date cell. Starts from 0.
+  const int row_index_;
+
+  // If the current cell is selected.
+  bool is_selected_ = false;
+
   // Owned by UnifiedCalendarViewController.
   CalendarViewController* const calendar_view_controller_;
+
+  base::ScopedObservation<CalendarViewController,
+                          CalendarViewController::Observer>
+      scoped_calendar_view_controller_observer_{this};
 };
 
 //  Container for `CalendarDateCellView` for a single month.
@@ -86,7 +105,8 @@
   CalendarDateCellView* AddDateCellToLayout(
       base::Time::Exploded current_date_exploded,
       int column,
-      bool is_in_current_month);
+      bool is_in_current_month,
+      int row_index);
 
   // Owned by `CalendarView`.
   CalendarViewController* const calendar_view_controller_;
diff --git a/ash/system/time/calendar_unittest_utils.cc b/ash/system/time/calendar_unittest_utils.cc
new file mode 100644
index 0000000..4359d0e
--- /dev/null
+++ b/ash/system/time/calendar_unittest_utils.cc
@@ -0,0 +1,40 @@
+// 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 "ash/system/time/calendar_unittest_utils.h"
+
+#include <string>
+
+#include "base/time/time.h"
+#include "google_apis/calendar/calendar_api_response_types.h"
+
+namespace ash {
+
+namespace calendar_test_utils {
+
+std::unique_ptr<google_apis::calendar::CalendarEvent> CreateEvent(
+    const char* id,
+    const char* summary,
+    const char* start_time,
+    const char* end_time) {
+  std::unique_ptr<google_apis::calendar::CalendarEvent> event =
+      std::make_unique<google_apis::calendar::CalendarEvent>();
+  base::Time start_time_base, end_time_base;
+  google_apis::calendar::DateTime start_time_date, end_time_date;
+  event->set_id(id);
+  event->set_summary(summary);
+  bool result = base::Time::FromString(start_time, &start_time_base);
+  DCHECK(result);
+  result = base::Time::FromString(end_time, &end_time_base);
+  DCHECK(result);
+  start_time_date.set_date_time(start_time_base);
+  end_time_date.set_date_time(end_time_base);
+  event->set_start_time(start_time_date);
+  event->set_end_time(end_time_date);
+  return event;
+}
+
+}  // namespace calendar_test_utils
+
+}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/time/calendar_unittest_utils.h b/ash/system/time/calendar_unittest_utils.h
new file mode 100644
index 0000000..ec7f405c
--- /dev/null
+++ b/ash/system/time/calendar_unittest_utils.h
@@ -0,0 +1,28 @@
+// 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 ASH_SYSTEM_TIME_CALENDAR_UNITTEST_UTILS_H_
+#define ASH_SYSTEM_TIME_CALENDAR_UNITTEST_UTILS_H_
+
+#include <string>
+
+#include "base/time/time.h"
+#include "google_apis/calendar/calendar_api_response_types.h"
+
+namespace ash {
+
+namespace calendar_test_utils {
+
+// Creates a `google_apis::calendar::CalendarEvent` for testing.
+std::unique_ptr<google_apis::calendar::CalendarEvent> CreateEvent(
+    const char* id,
+    const char* summary,
+    const char* start_time,
+    const char* end_time);
+
+}  // namespace calendar_test_utils
+
+}  // namespace ash
+
+#endif  // ASH_SYSTEM_TIME_CALENDAR_UNITTEST_UTILS_H_
diff --git a/ash/system/time/calendar_utils.cc b/ash/system/time/calendar_utils.cc
index 069784e1..35dbff3 100644
--- a/ash/system/time/calendar_utils.cc
+++ b/ash/system/time/calendar_utils.cc
@@ -7,6 +7,7 @@
 #include "ash/style/ash_color_provider.h"
 #include "base/i18n/unicodestring.h"
 #include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/icu/source/i18n/unicode/datefmt.h"
 #include "third_party/icu/source/i18n/unicode/dtptngen.h"
 #include "third_party/icu/source/i18n/unicode/smpdtfmt.h"
@@ -18,9 +19,14 @@
 
 bool IsToday(const base::Time::Exploded& selected_date) {
   base::Time::Exploded today_exploded = GetExplodedLocal(base::Time::Now());
-  return selected_date.year == today_exploded.year &&
-         selected_date.month == today_exploded.month &&
-         selected_date.day_of_month == today_exploded.day_of_month;
+  return IsTheSameDay(selected_date, today_exploded);
+}
+bool IsTheSameDay(absl::optional<base::Time::Exploded> date_a,
+                  absl::optional<base::Time::Exploded> date_b) {
+  if (!date_a.has_value() || !date_b.has_value())
+    return false;
+  return date_a->year == date_b->year && date_a->month == date_b->month &&
+         date_a->day_of_month == date_b->day_of_month;
 }
 
 base::Time::Exploded GetExplodedLocal(const base::Time& date) {
diff --git a/ash/system/time/calendar_utils.h b/ash/system/time/calendar_utils.h
index 7e0efd4..25052d5 100644
--- a/ash/system/time/calendar_utils.h
+++ b/ash/system/time/calendar_utils.h
@@ -6,6 +6,7 @@
 #define ASH_SYSTEM_TIME_CALENDAR_UTILS_H_
 
 #include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/insets.h"
 
@@ -34,6 +35,10 @@
 // Checks if the `selected_date` is local time today.
 bool IsToday(const base::Time::Exploded& selected_date);
 
+// Checks if the two exploded are in the same day.
+bool IsTheSameDay(absl::optional<base::Time::Exploded> date_a,
+                  absl::optional<base::Time::Exploded> date_b);
+
 // Gets the given `date`'s `Exploded` instance, in local time.
 base::Time::Exploded GetExplodedLocal(const base::Time& date);
 
@@ -76,4 +81,4 @@
 
 }  // namespace ash
 
-#endif  // ASH_SYSTEM_TIME_CALENDAR_UTILS_H_
\ No newline at end of file
+#endif  // ASH_SYSTEM_TIME_CALENDAR_UTILS_H_
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc
index d67a399..ddb3fc8 100644
--- a/ash/system/time/calendar_view.cc
+++ b/ash/system/time/calendar_view.cc
@@ -7,6 +7,7 @@
 #include "ash/public/cpp/ash_typography.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/pill_button.h"
+#include "ash/system/time/calendar_event_list_view.h"
 #include "ash/system/time/calendar_month_view.h"
 #include "ash/system/time/calendar_utils.h"
 #include "ash/system/tray/tray_popup_utils.h"
@@ -47,6 +48,11 @@
 // bottom if there's this much pixel left.
 constexpr int kPrepareEndOfView = 30;
 
+// The percentage of a normal row height, which (percentage * row_height) will
+// be used as the `CalendarView` height when the `CalendarEventListView` is
+// expanded.
+constexpr float kExpandedCalendarViewHeightScale = 1.3;
+
 // After the user is finished navigating to a different month, this is how long
 // we wait before fetchiung more events.
 constexpr base::TimeDelta kScrollingSettledTimeout = base::Milliseconds(100);
@@ -334,7 +340,14 @@
   scoped_view_observer_.AddObservation(content_view_);
 }
 
-CalendarView::~CalendarView() = default;
+CalendarView::~CalendarView() {
+  // Removes the month views to remove its dependency from
+  // `CalendarViewController`, since these views are destructed after the
+  // controller.
+  content_view_->RemoveChildViewT(previous_month_);
+  content_view_->RemoveChildViewT(current_month_);
+  content_view_->RemoveChildViewT(next_month_);
+}
 
 void CalendarView::Init() {
   calendar_view_controller_->FetchEvents();
@@ -385,19 +398,35 @@
       AddMonth(calendar_view_controller_->GetNextMonthFirstDayLocal(1));
 }
 
-int CalendarView::PositionOfCurrentMonth() {
+int CalendarView::PositionOfCurrentMonth() const {
   return kContentVerticalPadding +
          previous_label_->GetPreferredSize().height() +
          previous_month_->GetPreferredSize().height() +
          current_label_->GetPreferredSize().height();
 }
 
-int CalendarView::PositionOfToday() {
+int CalendarView::PositionOfToday() const {
   return PositionOfCurrentMonth() +
          calendar_view_controller_->GetTodayRowTopHeight();
 }
 
+int CalendarView::PositionOfSelectedDate() const {
+  DCHECK(calendar_view_controller_->selected_date().has_value());
+  const int row_height = calendar_view_controller_->selected_date_row_index() *
+                         calendar_view_controller_->row_height();
+  // The selected date should be either in the current month or the next month.
+  if (calendar_view_controller_->IsSelectedDateInCurrentMonth())
+    return PositionOfCurrentMonth() + row_height;
+
+  return PositionOfCurrentMonth() +
+         current_month_->GetPreferredSize().height() +
+         next_label_->GetPreferredSize().height() + row_height;
+}
+
 void CalendarView::ResetToToday() {
+  if (event_list_)
+    return;
+
   calendar_view_controller_->UpdateMonth(base::Time::Now());
   content_view_->RemoveChildViewT(previous_label_);
   content_view_->RemoveChildViewT(previous_month_);
@@ -672,6 +701,34 @@
   SchedulePaint();
 }
 
+void CalendarView::OpenEventList() {
+  if (event_list_)
+    return;
+
+  if (!calendar_view_controller_->IsSelectedDateInCurrentMonth())
+    ScrollDownOneMonth();
+  base::AutoReset<bool> is_resetting_scrolling(&is_resetting_scroll_, true);
+  scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(),
+                                 PositionOfSelectedDate());
+
+  scroll_view_->ClipHeightTo(0, kExpandedCalendarViewHeightScale *
+                                    calendar_view_controller_->row_height());
+  scroll_view_->SetVerticalScrollBarMode(
+      views::ScrollView::ScrollBarMode::kDisabled);
+  event_list_ = AddChildView(
+      std::make_unique<CalendarEventListView>(calendar_view_controller_.get()));
+  calendar_view_controller_->OnEventListOpened();
+}
+
+void CalendarView::CloseEventList() {
+  scroll_view_->ClipHeightTo(0, INT_MAX);
+  scroll_view_->SetVerticalScrollBarMode(
+      views::ScrollView::ScrollBarMode::kHiddenButEnabled);
+  RemoveChildViewT(event_list_);
+  event_list_ = nullptr;
+  calendar_view_controller_->OnEventListClosed();
+}
+
 void CalendarView::ScrollUpOneMonth() {
   calendar_view_controller_->UpdateMonth(
       calendar_view_controller_->GetPreviousMonthFirstDayLocal(1));
@@ -762,6 +819,11 @@
 }
 
 void CalendarView::ScrollOneMonthWithAnimation(bool is_scrolling_up) {
+  // TODO(https://crbug.com/1238927). Scroll the height of one row each time if
+  // the event list is shown.
+  if (event_list_)
+    return;
+
   if (is_resetting_scroll_)
     return;
 
diff --git a/ash/system/time/calendar_view.h b/ash/system/time/calendar_view.h
index afe9cb9..a982379 100644
--- a/ash/system/time/calendar_view.h
+++ b/ash/system/time/calendar_view.h
@@ -27,6 +27,7 @@
 
 namespace ash {
 
+class CalendarEventListView;
 class CalendarMonthView;
 
 // The header of the calendar view, which shows the current month and year.
@@ -72,6 +73,8 @@
   // CalendarViewController::Observer:
   void OnMonthChanged(const base::Time::Exploded current_month) override;
   void OnEventsFetched(const google_apis::calendar::EventList* events) override;
+  void OpenEventList() override;
+  void CloseEventList() override;
 
   // views::ViewObserver:
   void OnViewBoundsChanged(views::View* observed_view) override;
@@ -106,10 +109,13 @@
   void SetMonthViews();
 
   // Returns the current month first row position.
-  int PositionOfCurrentMonth();
+  int PositionOfCurrentMonth() const;
 
   // Returns the today's row position.
-  int PositionOfToday();
+  int PositionOfToday() const;
+
+  // Returns the selected date's row position.
+  int PositionOfSelectedDate() const;
 
   // Adds a month label.
   views::View* AddLabelWithId(LabelType type, bool add_at_front = false);
@@ -189,6 +195,7 @@
   views::Button* settings_button_ = nullptr;
   TopShortcutButton* up_button_ = nullptr;
   TopShortcutButton* down_button_ = nullptr;
+  CalendarEventListView* event_list_ = nullptr;
 
   // If it `is_resetting_scroll_`, we don't calculate the scroll position and we
   // don't need to check if we need to update the month or not.
diff --git a/ash/system/time/calendar_view_controller.cc b/ash/system/time/calendar_view_controller.cc
index a622520..5065b52 100644
--- a/ash/system/time/calendar_view_controller.cc
+++ b/ash/system/time/calendar_view_controller.cc
@@ -5,6 +5,7 @@
 #include "ash/system/time/calendar_view_controller.h"
 
 #include <stdlib.h>
+#include <cstddef>
 
 #include "ash/calendar/calendar_client.h"
 #include "ash/calendar/calendar_controller.h"
@@ -244,25 +245,21 @@
   MaybeFetchMonth(GetNextMonthFirstDayUTC(1).UTCMidnight());
 }
 
+SingleDayEventList CalendarViewController::SelectedDateEvents() {
+  if (!selected_date_.has_value())
+    return std::list<google_apis::calendar::CalendarEvent>();
+
+  base::Time date;
+  const bool result =
+      base::Time::FromLocalExploded(selected_date_.value(), &date);
+  DCHECK(result);
+  return FindEvents(date);
+}
+
 bool CalendarViewController::IsDayWithEventsInternal(
     base::Time day,
     SingleDayEventList* events) const {
-  // Early return if we know we have no events for this month.
-  base::Time start_of_month = calendar_utils::GetStartOfMonthUTC(day);
-  auto it = event_months_.find(start_of_month);
-  if (it == event_months_.end())
-    return false;
-
-  // Early return if we know we have no events for this day.
-  base::Time midnight = day.UTCMidnight();
-  const SingleMonthEventMap& month = it->second;
-  auto it2 = month.find(midnight);
-  if (it2 == month.end())
-    return false;
-
-  // Early return if there was a chance that have some events for this day, but
-  // in fact we don't.
-  const SingleDayEventList& list = it2->second;
+  const SingleDayEventList& list = FindEvents(day);
   if (list.empty())
     return false;
 
@@ -284,6 +281,50 @@
   return has_events;
 }
 
+void CalendarViewController::ShowEventListView(
+    base::Time::Exploded selected_date,
+    int row_index) {
+  // Do nothing if selecting on the same date.
+  if (is_event_list_showing_ &&
+      calendar_utils::IsTheSameDay(selected_date, selected_date_)) {
+    return;
+  }
+  selected_date_ = selected_date;
+  selected_date_row_index_ = row_index;
+
+  // Notify observers.
+  for (auto& observer : observers_)
+    observer.OnSelectedDateUpdated();
+
+  if (!is_event_list_showing_) {
+    for (auto& observer : observers_)
+      observer.OpenEventList();
+  }
+}
+
+void CalendarViewController::CloseEventListView() {
+  selected_date_ = absl::nullopt;
+  for (auto& observer : observers_)
+    observer.CloseEventList();
+}
+
+void CalendarViewController::OnEventListOpened() {
+  is_event_list_showing_ = true;
+}
+
+void CalendarViewController::OnEventListClosed() {
+  is_event_list_showing_ = false;
+}
+
+bool CalendarViewController::IsSelectedDateInCurrentMonth() {
+  if (!selected_date_.has_value())
+    return false;
+
+  auto current = calendar_utils::GetExplodedLocal(current_date_);
+  return current.month == selected_date_->month &&
+         current.year == selected_date_->year;
+}
+
 void CalendarViewController::OnCalendarEventsFetched(
     google_apis::ApiErrorCode error,
     std::unique_ptr<google_apis::calendar::EventList> events) {
@@ -348,6 +389,25 @@
     InsertEvent(event.get());
 }
 
+SingleDayEventList CalendarViewController::FindEvents(base::Time day) const {
+  SingleDayEventList event_list;
+
+  // Early return if we know we have no events for this month.
+  base::Time start_of_month = calendar_utils::GetStartOfMonthUTC(day);
+  auto it = event_months_.find(start_of_month);
+  if (it == event_months_.end())
+    return event_list;
+
+  // Early return if we know we have no events for this day.
+  base::Time midnight = day.UTCMidnight();
+  const SingleMonthEventMap& month = it->second;
+  auto it2 = month.find(midnight);
+  if (it2 == month.end())
+    return event_list;
+
+  return it2->second;
+}
+
 void CalendarViewController::PruneEventCache() {
   while (event_months_.size() >= kMaxNumberOfMonthsCached &&
          !prunable_months_mru_.empty()) {
diff --git a/ash/system/time/calendar_view_controller.h b/ash/system/time/calendar_view_controller.h
index b6156690..e70c72d 100644
--- a/ash/system/time/calendar_view_controller.h
+++ b/ash/system/time/calendar_view_controller.h
@@ -20,6 +20,15 @@
 
 namespace ash {
 
+namespace {
+
+// A simple std::list of calendar events, used to store a single day's events
+// in EventMap. Not to be confused with google_apis::calendar::EventList,
+// which represents the return value of a query from the GoogleCalendar API.
+using SingleDayEventList = std::list<google_apis::calendar::CalendarEvent>;
+
+}  // namespace
+
 // Controller of the `CalendarView`.
 class ASH_EXPORT CalendarViewController {
  public:
@@ -29,11 +38,6 @@
       delete;
   virtual ~CalendarViewController();
 
-  // A simple std::list of calendar events, used to store a single day's events
-  // in EventMap.  Not to be confused with google_apis::calendar::EventList,
-  // which represents the return value of a query from the GoogleCalendar API.
-  using SingleDayEventList = std::list<google_apis::calendar::CalendarEvent>;
-
   // Maps a day, i.e. midnight on the day of the event's start_time, to a
   // SingleDayEventList.
   using SingleMonthEventMap = std::map<base::Time, SingleDayEventList>;
@@ -45,11 +49,21 @@
   class Observer : public base::CheckedObserver {
    public:
     // Gets called when `current_date_ ` changes.
-    virtual void OnMonthChanged(const base::Time::Exploded current_month) = 0;
+    virtual void OnMonthChanged(const base::Time::Exploded current_month) {}
 
     // Invoked when a set of events has been fetched.
     virtual void OnEventsFetched(
         const google_apis::calendar::EventList* events) {}
+
+    // Invoked when a date cell is clicked to open the event list.
+    virtual void OpenEventList() {}
+
+    // Invoked when the close button is clicked to close the event list.
+    virtual void CloseEventList() {}
+
+    // Invoked when the selected date is updated in the
+    // `CalendarViewController`.
+    virtual void OnSelectedDateUpdated() {}
   };
 
   void AddObserver(Observer* observer);
@@ -98,6 +112,15 @@
   // to define the animation directions for updating the header and month views.
   bool was_on_later_month() { return was_on_later_month_; }
 
+  // The currently selected date to show the event list.
+  absl::optional<base::Time::Exploded> selected_date() {
+    return selected_date_;
+  }
+
+  // The row index of the currently selected date. This is used for auto
+  // scrolling to this row when the event list is expanded.
+  int selected_date_row_index() { return selected_date_row_index_; }
+
   // Getters of the today's row position, top and bottom.
   int GetTodayRowTopHeight() const;
   int GetTodayRowBottomHeight() const;
@@ -111,6 +134,9 @@
   // Requests more events as needed.
   void FetchEvents();
 
+  // The calendar events of the selected date.
+  SingleDayEventList SelectedDateEvents();
+
   // Same as `IsDayWithEventsInternal`, except that return of any events on
   // `day` constitutes "use" in the most-recently-used sense, so the month that
   // includes day will then be promoted to most-recently-used status.  If you
@@ -118,10 +144,29 @@
   // `IsDayWithEventsInternal`.
   bool IsDayWithEvents(base::Time day, SingleDayEventList* events);
 
+  // A callback passed into the`CalendarDateCellView`, which is called when the
+  // cell is clicked to show the event list view.
+  void ShowEventListView(base::Time::Exploded selected_date, int row_index);
+
+  // A callback passed into the`CalendarEventListView`, which is called when the
+  // close button is clicked to close the event list view.
+  void CloseEventListView();
+
+  // Gets called when the `CalendarEventListView` is opened.
+  void OnEventListOpened();
+
+  // Gets called when the `CalendarEventListView` is closed.
+  void OnEventListClosed();
+
+  // If the selected date in the current month. This is used to inform the
+  // `CalendarView` if the month should be updated when a date is selected.
+  bool IsSelectedDateInCurrentMonth();
+
  private:
   // For unit tests.
   friend class MockCalendarViewController;
   friend class CalendarViewControllerEventsTest;
+  friend class CalendarViewEventListViewTest;
 
   // Insert a single |event| in the EventCache.
   void InsertEvent(const google_apis::calendar::CalendarEvent* event);
@@ -135,6 +180,9 @@
   void InsertEvents(
       const std::unique_ptr<google_apis::calendar::EventList>& events);
 
+  // Find the event list of the given day.
+  SingleDayEventList FindEvents(base::Time day) const;
+
   // Free up months of events as needed to keep us within storage limits.
   void PruneEventCache();
 
@@ -199,6 +247,18 @@
   // If before getting to the on-screen-month, it was showing a later month.
   bool was_on_later_month_ = false;
 
+  // If the event list is expanded.
+  bool is_event_list_showing_ = false;
+
+  // The currently selected date.
+  absl::optional<base::Time::Exploded> selected_date_;
+
+  // The row index of the currently selected date.
+  int selected_date_row_index_;
+
+  // The event list of the currently selected date.
+  SingleDayEventList* selected_date_events_;
+
   base::ObserverList<Observer> observers_;
 
   base::WeakPtrFactory<CalendarViewController> weak_factory_{this};
diff --git a/ash/system/time/calendar_view_controller_unittest.cc b/ash/system/time/calendar_view_controller_unittest.cc
index dcb190fb..86a4f53 100644
--- a/ash/system/time/calendar_view_controller_unittest.cc
+++ b/ash/system/time/calendar_view_controller_unittest.cc
@@ -7,8 +7,10 @@
 #include <string>
 #include <utility>
 
+#include "ash/system/time/calendar_unittest_utils.h"
 #include "ash/test/ash_test_base.h"
 #include "base/time/time.h"
+#include "google_apis/calendar/calendar_api_response_types.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
@@ -178,30 +180,7 @@
     AshTestBase::TearDown();
   }
 
-  std::unique_ptr<google_apis::calendar::CalendarEvent> CreateEvent(
-      const char* id,
-      const char* summary,
-      const char* start_time,
-      const char* end_time) {
-    std::unique_ptr<google_apis::calendar::CalendarEvent> event =
-        std::make_unique<google_apis::calendar::CalendarEvent>();
-    base::Time start_time_base, end_time_base;
-    google_apis::calendar::DateTime start_time_date, end_time_date;
-    event->set_id(id);
-    event->set_summary(summary);
-    bool result = base::Time::FromString(start_time, &start_time_base);
-    DCHECK(result);
-    result = base::Time::FromString(end_time, &end_time_base);
-    DCHECK(result);
-    start_time_date.set_date_time(start_time_base);
-    end_time_date.set_date_time(end_time_base);
-    event->set_start_time(start_time_date);
-    event->set_end_time(end_time_date);
-    return event;
-  }
-
-  bool IsDayWithEvents(const char* day,
-                       CalendarViewController::SingleDayEventList* events) {
+  bool IsDayWithEvents(const char* day, SingleDayEventList* events) {
     base::Time day_base;
 
     bool result = base::Time::FromString(day, &day_base);
@@ -213,9 +192,8 @@
     return controller_->IsDayWithEvents(day_base, events);
   }
 
-  bool IsDayWithEventsInternal(
-      const char* day,
-      CalendarViewController::SingleDayEventList* events) const {
+  bool IsDayWithEventsInternal(const char* day,
+                               SingleDayEventList* events) const {
     base::Time day_base;
 
     bool result = base::Time::FromString(day, &day_base);
@@ -227,8 +205,7 @@
     return controller_->IsDayWithEventsInternal(day_base, events);
   }
 
-  bool IsEventPresent(const char* event_id,
-                      CalendarViewController::SingleDayEventList& events) {
+  bool IsEventPresent(const char* event_id, SingleDayEventList& events) {
     const auto it =
         std::find_if(events.begin(), events.end(),
                      [event_id](google_apis::calendar::CalendarEvent event) {
@@ -268,8 +245,8 @@
       std::make_unique<google_apis::calendar::EventList>();
   event_list->set_time_zone("America/Los_Angeles");
   std::unique_ptr<google_apis::calendar::CalendarEvent> event =
-      CreateEvent(kId, kSummary, kStartTime, kEndTime);
-  CalendarViewController::SingleDayEventList events;
+      calendar_test_utils::CreateEvent(kId, kSummary, kStartTime, kEndTime);
+  SingleDayEventList events;
 
   // Haven't injected anything yet, so no events on kStartTime0.
   events.clear();
@@ -317,10 +294,10 @@
       std::make_unique<google_apis::calendar::EventList>();
   event_list->set_time_zone("America/Los_Angeles");
   std::unique_ptr<google_apis::calendar::CalendarEvent> event0 =
-      CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
+      calendar_test_utils::CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event1 =
-      CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
-  CalendarViewController::SingleDayEventList events;
+      calendar_test_utils::CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
+  SingleDayEventList events;
 
   // Haven't injected anything yet, so no events on kStartTime0 or kStartTime1.
   events.clear();
@@ -375,8 +352,8 @@
       std::make_unique<google_apis::calendar::EventList>();
   event_list->set_time_zone("America/Los_Angeles");
   std::unique_ptr<google_apis::calendar::CalendarEvent> event =
-      CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
-  CalendarViewController::SingleDayEventList events;
+      calendar_test_utils::CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
+  SingleDayEventList events;
 
   // No events at kStartTime0.
   events.clear();
@@ -407,9 +384,9 @@
   event_list = std::make_unique<google_apis::calendar::EventList>();
   event_list->set_time_zone("America/Los_Angeles");
   std::unique_ptr<google_apis::calendar::CalendarEvent> event1 =
-      CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
+      calendar_test_utils::CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event2 =
-      CreateEvent(kId2, kSummary2, kStartTime2, kEndTime2);
+      calendar_test_utils::CreateEvent(kId2, kSummary2, kStartTime2, kEndTime2);
   event_list->InjectItemForTesting(std::move(event1));
   event_list->InjectItemForTesting(std::move(event2));
   controller_->InjectEvents(std::move(event_list));
@@ -457,12 +434,12 @@
       std::make_unique<google_apis::calendar::EventList>();
   event_list->set_time_zone("America/Los_Angeles");
   std::unique_ptr<google_apis::calendar::CalendarEvent> event0 =
-      CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
+      calendar_test_utils::CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event1 =
-      CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
+      calendar_test_utils::CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event2 =
-      CreateEvent(kId2, kSummary2, kStartTime2, kEndTime2);
-  CalendarViewController::SingleDayEventList events;
+      calendar_test_utils::CreateEvent(kId2, kSummary2, kStartTime2, kEndTime2);
+  SingleDayEventList events;
 
   // No events on any day.
   events.clear();
@@ -564,24 +541,24 @@
 
   // A series of events, one in each successive month.
   std::unique_ptr<google_apis::calendar::CalendarEvent> event0 =
-      CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
+      calendar_test_utils::CreateEvent(kId0, kSummary0, kStartTime0, kEndTime0);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event1 =
-      CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
+      calendar_test_utils::CreateEvent(kId1, kSummary1, kStartTime1, kEndTime1);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event2 =
-      CreateEvent(kId2, kSummary2, kStartTime2, kEndTime2);
+      calendar_test_utils::CreateEvent(kId2, kSummary2, kStartTime2, kEndTime2);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event3 =
-      CreateEvent(kId3, kSummary3, kStartTime3, kEndTime3);
+      calendar_test_utils::CreateEvent(kId3, kSummary3, kStartTime3, kEndTime3);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event4 =
-      CreateEvent(kId4, kSummary4, kStartTime4, kEndTime4);
+      calendar_test_utils::CreateEvent(kId4, kSummary4, kStartTime4, kEndTime4);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event5 =
-      CreateEvent(kId5, kSummary5, kStartTime5, kEndTime5);
+      calendar_test_utils::CreateEvent(kId5, kSummary5, kStartTime5, kEndTime5);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event6 =
-      CreateEvent(kId6, kSummary6, kStartTime6, kEndTime6);
+      calendar_test_utils::CreateEvent(kId6, kSummary6, kStartTime6, kEndTime6);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event7 =
-      CreateEvent(kId7, kSummary7, kStartTime7, kEndTime7);
+      calendar_test_utils::CreateEvent(kId7, kSummary7, kStartTime7, kEndTime7);
   std::unique_ptr<google_apis::calendar::CalendarEvent> event8 =
-      CreateEvent(kId8, kSummary8, kStartTime8, kEndTime8);
-  CalendarViewController::SingleDayEventList events;
+      calendar_test_utils::CreateEvent(kId8, kSummary8, kStartTime8, kEndTime8);
+  SingleDayEventList events;
 
   // Inject all events, i.e. pretend the user added all these at some point.
   event_list->InjectItemForTesting(std::move(event0));
diff --git a/ash/webui/PRESUBMIT.py b/ash/webui/PRESUBMIT.py
index c3ec96e4..addb95b 100644
--- a/ash/webui/PRESUBMIT.py
+++ b/ash/webui/PRESUBMIT.py
@@ -13,6 +13,13 @@
   return _CommonChecks(input_api, output_api)
 
 
+SKIP_PRESUBMIT_FILES = set([
+  # The file is generated from FFMpeg by Emscripten, and doesn't pass Chrome JS
+  # style check. In particular, js_checker.VariableNameCheck fails for this.
+  'ash/webui/camera_app_ui/resources/js/lib/ffmpeg.js'
+])
+
+
 def _CommonChecks(input_api, output_api):
   results = input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
                                                         check_js=True)
@@ -22,7 +29,10 @@
     cwd = input_api.PresubmitLocalPath()
     sys.path += [input_api.os_path.join(cwd, '..', '..', 'tools')]
     from web_dev_style import presubmit_support
-    results += presubmit_support.CheckStyle(input_api, output_api)
+    results += presubmit_support.CheckStyle(
+        input_api,
+        output_api,
+        lambda x: x.LocalPath() not in SKIP_PRESUBMIT_FILES)
   finally:
     sys.path = old_sys_path
   return results
diff --git a/ash/webui/camera_app_ui/PRESUBMIT.py b/ash/webui/camera_app_ui/PRESUBMIT.py
index 916b744..27e7ecdc 100644
--- a/ash/webui/camera_app_ui/PRESUBMIT.py
+++ b/ash/webui/camera_app_ui/PRESUBMIT.py
@@ -19,34 +19,9 @@
   affected = input_api.AffectedFiles()
   if any(f for f in affected if f.LocalPath().endswith('.html')):
     results += _CheckHtml(input_api, output_api)
-  results += _CheckWebDevStyle(input_api, output_api)
   return results
 
 
 def _CheckHtml(input_api, output_api):
   return input_api.canned_checks.CheckLongLines(
       input_api, output_api, 80, lambda x: x.LocalPath().endswith('.html'))
-
-
-SKIP_PRESUBMIT_FILES = set([
-  'ash/webui/camera_app_ui/resources/js/lib/ffmpeg.js'
-])
-
-
-def _CheckWebDevStyle(input_api, output_api):
-  results = []
-
-  try:
-    import sys
-    old_sys_path = sys.path[:]
-    cwd = input_api.PresubmitLocalPath()
-    sys.path += [input_api.os_path.join(cwd, '..', '..', '..', 'tools')]
-    from web_dev_style import presubmit_support
-    results += presubmit_support.CheckStyle(
-        input_api,
-        output_api,
-        lambda x: x.LocalPath() not in SKIP_PRESUBMIT_FILES)
-  finally:
-    sys.path = old_sys_path
-
-  return results
diff --git a/ash/webui/file_manager/resources/file_manager_fakes.js b/ash/webui/file_manager/resources/file_manager_fakes.js
index 0eb8f33..e1286de0 100644
--- a/ash/webui/file_manager/resources/file_manager_fakes.js
+++ b/ash/webui/file_manager/resources/file_manager_fakes.js
@@ -2,11 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/** @suppress {checkTypes} */
-window.chrome.extension = {
-  inIncognitoContext: false,
-};
-
 window.DriveSyncHandler = class extends EventTarget {
   /**
    * Returns the completed event name.
diff --git a/ash/webui/personalization_app/resources/BUILD.gn b/ash/webui/personalization_app/resources/BUILD.gn
index 1fc80e1..d04dae1 100644
--- a/ash/webui/personalization_app/resources/BUILD.gn
+++ b/ash/webui/personalization_app/resources/BUILD.gn
@@ -19,16 +19,17 @@
   "common/utils.ts",
 
   "trusted/iframe_api.ts",
-  "trusted/mojo_interface_provider.ts",
   "trusted/personalization_actions.ts",
   "trusted/personalization_app.js",
-  "trusted/personalization_controller.js",
-  "trusted/personalization_message_handler.js",
   "trusted/personalization_reducers.js",
   "trusted/personalization_state.ts",
   "trusted/personalization_store.ts",
   "trusted/personalization_test_api.js",
   "trusted/utils.ts",
+  "trusted/wallpaper/untrusted_message_handler.js",
+  "trusted/wallpaper/wallpaper_controller.js",
+  "trusted/wallpaper/wallpaper_interface_provider.ts",
+  "trusted/wallpaper/wallpaper_subpage.ts",
 
   "untrusted/iframe_api.ts",
   "untrusted/setup.ts",
@@ -38,18 +39,18 @@
   "common/icons.js",
   "common/styles.js",
 
-  "trusted/google_photos_element.js",
-  "trusted/local_images_element.js",
-  "trusted/personalization_grid_item_element.js",
   "trusted/personalization_router_element.js",
   "trusted/personalization_toast_element.js",
-  "trusted/styles.ts",
-  "trusted/wallpaper_breadcrumb_element.js",
-  "trusted/wallpaper_collections_element.js",
-  "trusted/wallpaper_error_element.js",
-  "trusted/wallpaper_fullscreen_element.ts",
-  "trusted/wallpaper_images_element.js",
-  "trusted/wallpaper_selected_element.js",
+  "trusted/personalization_breadcrumb_element.js",
+  "trusted/wallpaper/google_photos_element.js",
+  "trusted/wallpaper/local_images_element.js",
+  "trusted/wallpaper/styles.ts",
+  "trusted/wallpaper/wallpaper_collections_element.js",
+  "trusted/wallpaper/wallpaper_error_element.js",
+  "trusted/wallpaper/wallpaper_fullscreen_element.ts",
+  "trusted/wallpaper/wallpaper_grid_item_element.js",
+  "trusted/wallpaper/wallpaper_images_element.js",
+  "trusted/wallpaper/wallpaper_selected_element.js",
 
   "untrusted/collections_grid.js",
   "untrusted/images_grid.js",
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_app.js b/ash/webui/personalization_app/resources/trusted/personalization_app.js
index 4661557..c8a47d9 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_app.js
+++ b/ash/webui/personalization_app/resources/trusted/personalization_app.js
@@ -9,29 +9,12 @@
  */
 
 import '/strings.m.js';
-import './google_photos_element.js';
-import './local_images_element.js';
-import './personalization_grid_item_element.js';
 import './personalization_router_element.js';
 import './personalization_test_api.js';
 import './personalization_toast_element.js';
-import './wallpaper_breadcrumb_element.js';
-import './wallpaper_collections_element.js';
-import './wallpaper_error_element.js';
-import './wallpaper_fullscreen_element.js';
-import './wallpaper_images_element.js';
-import './wallpaper_selected_element.js';
-import './styles.js';
-import {onMessageReceived} from './personalization_message_handler.js';
+import './personalization_breadcrumb_element.js';
+import './wallpaper/wallpaper_subpage.js';
 import {emptyState} from './personalization_state.js';
 import {PersonalizationStore} from './personalization_store.js';
 
 PersonalizationStore.getInstance().init(emptyState());
-
-window.addEventListener('message', onMessageReceived);
-
-function reload(event) {
-  window.location.reload();
-}
-// Reload when online, in case any images are not loaded.
-window.addEventListener('online', reload);
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_breadcrumb_element.html b/ash/webui/personalization_app/resources/trusted/personalization_breadcrumb_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_breadcrumb_element.html
rename to ash/webui/personalization_app/resources/trusted/personalization_breadcrumb_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_breadcrumb_element.js b/ash/webui/personalization_app/resources/trusted/personalization_breadcrumb_element.js
similarity index 95%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_breadcrumb_element.js
rename to ash/webui/personalization_app/resources/trusted/personalization_breadcrumb_element.js
index c299000..1e9ec13 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper_breadcrumb_element.js
+++ b/ash/webui/personalization_app/resources/trusted/personalization_breadcrumb_element.js
@@ -22,9 +22,9 @@
 
 
 /** @polymer */
-export class WallpaperBreadcrumb extends WithPersonalizationStore {
+export class PersonalizationBreadcrumb extends WithPersonalizationStore {
   static get is() {
-    return 'wallpaper-breadcrumb';
+    return 'personalization-breadcrumb';
   }
 
   static get template() {
@@ -173,4 +173,4 @@
   }
 }
 
-customElements.define(WallpaperBreadcrumb.is, WallpaperBreadcrumb);
+customElements.define(PersonalizationBreadcrumb.is, PersonalizationBreadcrumb);
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_reducers.js b/ash/webui/personalization_app/resources/trusted/personalization_reducers.js
index 9a1e0a43..72e5674 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_reducers.js
+++ b/ash/webui/personalization_app/resources/trusted/personalization_reducers.js
@@ -8,7 +8,6 @@
  * @see [redux tutorial]{@link https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers}
  */
 
-import './mojo_interface_provider.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {Action} from 'chrome://resources/js/cr/ui/store.js';
 import {ActionName} from './personalization_actions.js';
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html
index 19728e3c..b623e6f2 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html
+++ b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html
@@ -24,7 +24,7 @@
   #rightspacer {
     grid-area: rightspacer;
   }
-  wallpaper-breadcrumb {
+  personalization-breadcrumb {
     grid-area: breadcrumb;
   }
   wallpaper-selected {
@@ -67,10 +67,10 @@
     <div id="wallpaperContainer">
       <!-- Prevent left margin from collapsing on narrow window in RTL -->
       <div id="leftspacer"></div>
-      <wallpaper-breadcrumb path="[[path_]]"
+      <personalization-breadcrumb path="[[path_]]"
           collection-id="[[queryParams_.id]]"
           google-photos-album-id="[[queryParams_.googlePhotosAlbumId]]">
-      </wallpaper-breadcrumb>
+      </personalization-breadcrumb>
       <wallpaper-selected path="[[path_]]" collection-id="[[queryParams_.id]]">
       </wallpaper-selected>
       <!-- do not use hidden$ here - need to listen on property change in
diff --git a/ash/webui/personalization_app/resources/trusted/google_photos_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_element.html
similarity index 95%
rename from ash/webui/personalization_app/resources/trusted/google_photos_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_element.html
index a334138..40410a55 100644
--- a/ash/webui/personalization_app/resources/trusted/google_photos_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_element.html
@@ -112,11 +112,11 @@
             on-focus="onPhotosGridRowFocused_"
             on-keydown="onPhotosGridRowKeyDown_">
             <template is="dom-repeat" items="[[row]]" as="photo">
-              <personalization-grid-item>
+              <wallpaper-grid-item>
                 <div class="photo" colindex$="[[index]]" tabindex="-1">
                   [[photo]]
                 </div>
-              </personalization-grid-item>
+              </wallpaper-grid-item>
             </template>
           </div>
         </template>
@@ -127,14 +127,14 @@
     <div id="albumsContent" hidden$="[[!isAlbumsTabSelected_(tab_)]]">
       <iron-list id="albumsGrid" items="[[albums_]]" as="album" grid>
         <template>
-            <personalization-grid-item>
+            <wallpaper-grid-item>
               <template is="dom-if" if="[[album]]">
                 <div class="album" tabindex$="[[tabIndex]]"
                   on-click="onAlbumSelected_" on-keypress="onAlbumSelected_">
                   [[album.name]]
                 </div>
               </template>
-            </personalization-grid-item>
+            </wallpaper-grid-item>
         </template>
       </iron-list>
     </div>
diff --git a/ash/webui/personalization_app/resources/trusted/google_photos_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_element.js
similarity index 96%
rename from ash/webui/personalization_app/resources/trusted/google_photos_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_element.js
index 5621246..c77f3d3 100644
--- a/ash/webui/personalization_app/resources/trusted/google_photos_element.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_element.js
@@ -10,14 +10,17 @@
 import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import './styles.js';
-import '../common/styles.js';
+import '/common/styles.js';
+
+import {getNumberOfGridItemsPerRow, isNonEmptyArray, isSelectionEvent, normalizeKeyForRTL} from '/common/utils.js';
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getNumberOfGridItemsPerRow, isNonEmptyArray, isSelectionEvent, normalizeKeyForRTL} from '../common/utils.js';
-import {getWallpaperProvider} from './mojo_interface_provider.js';
-import {initializeGooglePhotosData} from './personalization_controller.js';
-import {PersonalizationRouter} from './personalization_router_element.js';
-import {WithPersonalizationStore} from './personalization_store.js';
+
+import {PersonalizationRouter} from '../personalization_router_element.js';
+import {WithPersonalizationStore} from '../personalization_store.js';
+
+import {initializeGooglePhotosData} from './wallpaper_controller.js';
+import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
 /**
  * Enumeration of supported tabs.
diff --git a/ash/webui/personalization_app/resources/trusted/local_images_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/local_images_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/local_images_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.js
similarity index 92%
rename from ash/webui/personalization_app/resources/trusted/local_images_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.js
index 9491c19..ebc99401 100644
--- a/ash/webui/personalization_app/resources/trusted/local_images_element.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.js
@@ -13,16 +13,18 @@
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
 import './styles.js';
-import '../common/icons.js';
-import '../common/styles.js';
+import '/common/icons.js';
+import '/common/styles.js';
+
+import {getLoadingPlaceholderAnimationDelay} from '/common/utils.js';
+import {isSelectionEvent} from '/common/utils.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {getLoadingPlaceholderAnimationDelay} from '../common/utils.js';
-import {isSelectionEvent} from '../common/utils.js';
-import {getWallpaperProvider} from './mojo_interface_provider.js';
-import {fetchLocalData, selectWallpaper} from './personalization_controller.js';
-import {DisplayableImage} from './personalization_reducers.js';
-import {WithPersonalizationStore} from './personalization_store.js';
+
+import {WithPersonalizationStore} from '../personalization_store.js';
+
+import {fetchLocalData, selectWallpaper} from './wallpaper_controller.js';
+import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
 /** @polymer */
 export class LocalImages extends WithPersonalizationStore {
@@ -202,12 +204,12 @@
    * @return {string}
    * @private
    */
-   getAriaLabel_(image) {
-     if (!image || !image.path) {
-       return '';
-     }
+  getAriaLabel_(image) {
+    if (!image || !image.path) {
+      return '';
+    }
     const path = image.path;
-    return path.substring(path.lastIndexOf('/')+1);
+    return path.substring(path.lastIndexOf('/') + 1);
   }
 
   /**
diff --git a/ash/webui/personalization_app/resources/trusted/styles.html b/ash/webui/personalization_app/resources/trusted/wallpaper/styles.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/styles.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/styles.html
diff --git a/ash/webui/personalization_app/resources/trusted/styles.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/styles.ts
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/styles.ts
rename to ash/webui/personalization_app/resources/trusted/wallpaper/styles.ts
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_message_handler.js b/ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.js
similarity index 77%
rename from ash/webui/personalization_app/resources/trusted/personalization_message_handler.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.js
index 6e37030..4bf70331 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_message_handler.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/untrusted_message_handler.js
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {EventType, untrustedOrigin} from '/common/constants.js';
+import {validateReceivedSelection} from '/trusted/iframe_api.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
-import {EventType, untrustedOrigin} from '../common/constants.js';
-import {validateReceivedSelection} from '../trusted/iframe_api.js';
-import {getWallpaperProvider} from './mojo_interface_provider.js';
-import {selectWallpaper} from './personalization_controller.js';
-import {PersonalizationRouter} from './personalization_router_element.js';
-import {PersonalizationStore} from './personalization_store.js';
+
+import {PersonalizationRouter} from '../personalization_router_element.js';
+import {PersonalizationStore} from '../personalization_store.js';
+
+import {selectWallpaper} from './wallpaper_controller.js';
+import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
 /**
  * @fileoverview message handler that receives data from untrusted.
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_collections_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_collections_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_collections_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.js
similarity index 97%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_collections_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.js
index dbc49f1..1c7fa67 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper_collections_element.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_collections_element.js
@@ -10,15 +10,15 @@
 
 import './styles.js';
 
+import {kMaximumLocalImagePreviews} from '/common/constants.js';
+import {isNonEmptyArray, isNullOrArray, isNullOrNumber, promisifyOnload} from '/common/utils.js';
+import {sendCollections, sendGooglePhotosCount, sendGooglePhotosPhotos, sendImageCounts, sendLocalImageData, sendLocalImages, sendVisible} from '/trusted/iframe_api.js';
 import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {kMaximumLocalImagePreviews} from '../common/constants.js';
-import {isNonEmptyArray, isNullOrArray, isNullOrNumber, promisifyOnload} from '../common/utils.js';
-import {sendCollections, sendGooglePhotosCount, sendGooglePhotosPhotos, sendImageCounts, sendLocalImageData, sendLocalImages, sendVisible} from '../trusted/iframe_api.js';
+import {WithPersonalizationStore} from '../personalization_store.js';
 
-import {getWallpaperProvider} from './mojo_interface_provider.js';
-import {initializeBackdropData} from './personalization_controller.js';
-import {WithPersonalizationStore} from './personalization_store.js';
+import {initializeBackdropData} from './wallpaper_controller.js';
+import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
 let sendCollectionsFunction = sendCollections;
 let sendGooglePhotosCountFunction = sendGooglePhotosCount;
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_controller.js b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.js
similarity index 97%
rename from ash/webui/personalization_app/resources/trusted/personalization_controller.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.js
index 642bddf3..b1132ea 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_controller.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.js
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {isNonEmptyArray} from '/common/utils.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
-import {isNonEmptyArray} from '../common/utils.js';
-import * as action from './personalization_actions.js';
-import {WallpaperCollection, WallpaperLayout, WallpaperType} from './personalization_app.mojom-webui.js';
-import {PersonalizationStore} from './personalization_store.js';
+
+import * as action from '../personalization_actions.js';
+import {WallpaperCollection, WallpaperLayout, WallpaperType} from '../personalization_app.mojom-webui.js';
+import {PersonalizationStore} from '../personalization_store.js';
 
 /**
  * @fileoverview contains all of the functions to interact with C++ side through
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_error_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_error_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_error_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_error_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_error_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_error_element.js
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_error_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_error_element.js
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_fullscreen_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_fullscreen_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_fullscreen_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts
similarity index 93%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_fullscreen_element.ts
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts
index 498bcf8f..7f1b714 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper_fullscreen_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts
@@ -10,18 +10,19 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
-import '../common/icons.js';
+import '/common/icons.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js';
 import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {getWallpaperProvider} from './mojo_interface_provider.js';
-import {setFullscreenEnabledAction} from './personalization_actions.js';
-import {CurrentWallpaper, WallpaperImage, WallpaperLayout, WallpaperProviderInterface} from './personalization_app.mojom-webui.js';
-import {cancelPreviewWallpaper, confirmPreviewWallpaper, selectWallpaper} from './personalization_controller.js';
-import {WithPersonalizationStore} from './personalization_store.js';
-import {getWallpaperLayoutEnum} from './utils.js';
+import {setFullscreenEnabledAction} from '../personalization_actions.js';
+import {CurrentWallpaper, WallpaperImage, WallpaperLayout, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js';
+import {WithPersonalizationStore} from '../personalization_store.js';
+import {getWallpaperLayoutEnum} from '../utils.js';
+
+import {cancelPreviewWallpaper, confirmPreviewWallpaper, selectWallpaper} from './wallpaper_controller.js';
+import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
 const fullscreenClass = 'fullscreen-preview';
 
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_grid_item_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_grid_item_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/personalization_grid_item_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_grid_item_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_grid_item_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_grid_item_element.js
similarity index 65%
rename from ash/webui/personalization_app/resources/trusted/personalization_grid_item_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_grid_item_element.js
index 9a55de3..9bf0663d 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_grid_item_element.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_grid_item_element.js
@@ -6,13 +6,14 @@
  * @fileoverview Polymer element that displays a single grid item.
  */
 
-import '../common/styles.js';
+import '/common/styles.js';
+
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 /** @polymer */
-export class PersonalizationGridItemElement extends PolymerElement {
+export class WallpaperGridItemElement extends PolymerElement {
   static get is() {
-    return 'personalization-grid-item';
+    return 'wallpaper-grid-item';
   }
 
   static get template() {
@@ -20,5 +21,4 @@
   }
 }
 
-customElements.define(
-    PersonalizationGridItemElement.is, PersonalizationGridItemElement);
+customElements.define(WallpaperGridItemElement.is, WallpaperGridItemElement);
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_images_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_images_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_images_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.js
similarity index 96%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_images_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.js
index 2f823f8..2f74138 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper_images_element.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_images_element.js
@@ -12,15 +12,14 @@
 import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js';
 import './styles.js';
 
+import {ImageTile} from '/common/constants.js';
+import {isNonEmptyArray, promisifyOnload} from '/common/utils.js';
+import {sendCurrentWallpaperAssetId, sendImageTiles, sendPendingWallpaperAssetId, sendVisible} from '/trusted/iframe_api.js';
 import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {ImageTile} from '../common/constants.js';
-import {isNonEmptyArray, promisifyOnload} from '../common/utils.js';
-import {sendCurrentWallpaperAssetId, sendImageTiles, sendPendingWallpaperAssetId, sendVisible} from '../trusted/iframe_api.js';
-
-import {DisplayableImage, OnlineImageType, WallpaperType} from './personalization_app.mojom-webui.js';
-import {PersonalizationRouter} from './personalization_router_element.js';
-import {WithPersonalizationStore} from './personalization_store.js';
+import {DisplayableImage, OnlineImageType, WallpaperType} from '../personalization_app.mojom-webui.js';
+import {PersonalizationRouter} from '../personalization_router_element.js';
+import {WithPersonalizationStore} from '../personalization_store.js';
 
 let sendCurrentWallpaperAssetIdFunction = sendCurrentWallpaperAssetId;
 let sendImageTilesFunction = sendImageTiles;
diff --git a/ash/webui/personalization_app/resources/trusted/mojo_interface_provider.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_interface_provider.ts
similarity index 91%
rename from ash/webui/personalization_app/resources/trusted/mojo_interface_provider.ts
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_interface_provider.ts
index cc870497..d7035ab 100644
--- a/ash/webui/personalization_app/resources/trusted/mojo_interface_provider.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_interface_provider.ts
@@ -11,7 +11,7 @@
 import 'chrome://resources/mojo/mojo/public/js/bindings.js';
 import 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
 
-import {WallpaperProvider, WallpaperProviderInterface} from './personalization_app.mojom-webui.js';
+import {WallpaperProvider, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js';
 
 let wallpaperProvider: WallpaperProviderInterface|null = null;
 
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_selected_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.html
similarity index 100%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_selected_element.html
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.html
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper_selected_element.js b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.js
similarity index 96%
rename from ash/webui/personalization_app/resources/trusted/wallpaper_selected_element.js
rename to ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.js
index 3033f68..95d26ed 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper_selected_element.js
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.js
@@ -10,21 +10,21 @@
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
+import '/common/icons.js';
 import './styles.js';
-import '../common/icons.js';
 
+import {isNonEmptyArray} from '/common/utils.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {isNonEmptyArray} from '../common/utils.js';
+import {beginLoadSelectedImageAction, setSelectedImageAction} from '../personalization_actions.js';
+import {WallpaperLayout, WallpaperObserverReceiver, WallpaperType} from '../personalization_app.mojom-webui.js';
+import {Paths} from '../personalization_router_element.js';
+import {WithPersonalizationStore} from '../personalization_store.js';
+import {getWallpaperLayoutEnum} from '../utils.js';
 
-import {getWallpaperProvider} from './mojo_interface_provider.js';
-import {beginLoadSelectedImageAction, setFullscreenEnabledAction, setSelectedImageAction} from './personalization_actions.js';
-import {WallpaperLayout, WallpaperObserverReceiver, WallpaperType} from './personalization_app.mojom-webui.js';
-import {getDailyRefreshCollectionId, setCustomWallpaperLayout, setDailyRefreshCollectionId, updateDailyRefreshWallpaper} from './personalization_controller.js';
-import {Paths} from './personalization_router_element.js';
-import {WithPersonalizationStore} from './personalization_store.js';
-import {getWallpaperLayoutEnum} from './utils.js';
+import {getDailyRefreshCollectionId, setCustomWallpaperLayout, setDailyRefreshCollectionId, updateDailyRefreshWallpaper} from './wallpaper_controller.js';
+import {getWallpaperProvider} from './wallpaper_interface_provider.js';
 
 let setTimeout = window.setTimeout;
 let clearTimeout = window.clearTimeout;
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage.ts
new file mode 100644
index 0000000..63c135e4
--- /dev/null
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage.ts
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './google_photos_element.js';
+import './local_images_element.js';
+import './wallpaper_grid_item_element.js';
+import './wallpaper_collections_element.js';
+import './wallpaper_error_element.js';
+import './wallpaper_fullscreen_element.js';
+import './wallpaper_images_element.js';
+import './wallpaper_selected_element.js';
+import './styles.js';
+import {onMessageReceived} from './untrusted_message_handler.js';
+
+window.addEventListener('message', onMessageReceived);
+
+function reload(): void {
+  window.location.reload();
+}
+// Reload when online, in case any images are not loaded.
+window.addEventListener('online', reload);
diff --git a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
index ba524fe9..468b568 100644
--- a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
+++ b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
@@ -3,11 +3,11 @@
 
 <base-page>
   <div slot="header">
-    <!-- TODO(gavindodd): Update text for i18n -->
-    <h1 hidden$="[[!reimageRequired_]]">Select an option for firmware reimaging</h1>
+    <h1 hidden$="[[!reimageRequired_]]">
+      [[i18n('firmwareReimagingTitleReimageRequired')]]
+    </h1>
     <h1 hidden$="[[reimageRequired_]]">
-      This device doesn't require firmware reimaging.
-      Would you like to reimage the firmware anyway?
+      [[i18n('firmwareReimagingTitleReimageNotRequired')]]
     </h1>
   </div>
   <div slot="body">
@@ -19,21 +19,25 @@
           id="firmwareReimageDownload">
         [[firmwareReimageDownloadMessage_(reimageRequired_)]]
       </cr-radio-button>
-      <p class="indented-description">Requires internet access</p>
+      <p class="indented-description">
+        [[i18n('firmwareReimagingInternetAccess')]]
+      </p>
       <cr-radio-button
           name="firmwareReimageUsb"
           id="firmwareReimageUsb">
         [[firmwareReimageUsbMessage_(reimageRequired_)]]
       </cr-radio-button>
       <p class="indented-description">
-        Requires a Thumbdrive configured for
-        <a href="#" on-click="linkToRecoveryClicked_">Chromebook Recovery</a>
+        [[i18n('firmwareReimagingThumbdrive1')]]
+        <a href="#" on-click="linkToRecoveryClicked_">
+          [[i18n('firmwareReimagingThumbdrive2')]]
+        </a>
       </p>
       <cr-radio-button
           name="firmwareReimageSkip"
           id="firmwareReimageSkip"
           hidden$="[[reimageRequired_]]">
-        No, skip it for now.
+          [[i18n('firmwareReimagingSkip')]]
       </cr-radio-button>
     </cr-radio-group>
   </div>
diff --git a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js
index d21c4bb..750fa8c 100644
--- a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js
+++ b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js
@@ -5,7 +5,8 @@
 import './shimless_rma_shared_css.js';
 import './base_page.js';
 
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
+import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getShimlessRmaService} from './mojo_interface_provider.js';
 import {ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js';
@@ -16,7 +17,18 @@
  * internet or recovery shim.
  * The reimage may be optional in which case skip reimage will be available.
  */
-export class ReimagingFirmwareUpdatePageElement extends PolymerElement {
+
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {I18nBehaviorInterface}
+ */
+const ReimagingFirmwareUpdatePageBase =
+    mixinBehaviors([I18nBehavior], PolymerElement);
+
+/** @polymer */
+export class ReimagingFirmwareUpdatePageElement extends
+    ReimagingFirmwareUpdatePageBase {
   static get is() {
     return 'reimaging-firmware-update-page';
   }
@@ -75,11 +87,10 @@
    * @returns {string}
    */
   firmwareReimageDownloadMessage_(reimageRequired) {
-    // TODO(gavindodd): Update text for i18n
     if (reimageRequired) {
-      return 'Download the firmware image';
+      return this.i18n('firmwareReimagingDownloadReimageRequired');
     } else {
-      return 'Yes, download the firmware image';
+      return this.i18n('firmwareReimagingDownloadReimageNotRequired');
     }
   }
 
@@ -89,11 +100,10 @@
    * @returns {string}
    */
   firmwareReimageUsbMessage_(reimageRequired) {
-    // TODO(gavindodd): Update text for i18n
     if (reimageRequired) {
-      return 'Use the Chromebook Recovery Utility';
+      return this.i18n('firmwareReimagingRecoveryReimageRequired');
     } else {
-      return 'Yes, use the Chromebook Recovery Utility';
+      return this.i18n('firmwareReimagingRecoveryReimageNotRequired');
     }
   }
 
diff --git a/ash/webui/shimless_rma/shimless_rma.cc b/ash/webui/shimless_rma/shimless_rma.cc
index 49ccd14..691ef6e 100644
--- a/ash/webui/shimless_rma/shimless_rma.cc
+++ b/ash/webui/shimless_rma/shimless_rma.cc
@@ -247,6 +247,26 @@
        IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_RESET_BUTTON_LABEL},
       {"confirmDeviceInfoSkuWarning",
        IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_SKU_WARNING},
+      // Firmware reimaging page
+      {"firmwareReimagingTitleReimageRequired",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_TITLE_REIMAGE_REQUIRED},
+      {"firmwareReimagingTitleReimageNotRequired",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_TITLE_REIMAGE_NOT_REQUIRED},
+      {"firmwareReimagingInternetAccess",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_INTERNET_ACCESS},
+      {"firmwareReimagingThumbdrive1",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_THUMBDRIVE_1},
+      {"firmwareReimagingThumbdrive2",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_THUMBDRIVE_2},
+      {"firmwareReimagingSkip", IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_SKIP},
+      {"firmwareReimagingDownloadReimageRequired",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_DOWNLOAD_REIMAGE_REQUIRED},
+      {"firmwareReimagingDownloadReimageNotRequired",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_DOWNLOAD_REIMAGE_NOT_REQUIRED},
+      {"firmwareReimagingRecoveryReimageRequired",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_RECOVERY_REIMAGE_REQUIRED},
+      {"firmwareReimagingRecoveryReimageNotRequired",
+       IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_RECOVERY_REIMAGE_NOT_REQUIRED},
   };
 
   html_source->AddLocalizedStrings(kLocalizedStrings);
diff --git a/ash/wm/desks/templates/desks_templates_icon_view.cc b/ash/wm/desks/templates/desks_templates_icon_view.cc
index e15815d..2d6c6d5 100644
--- a/ash/wm/desks/templates/desks_templates_icon_view.cc
+++ b/ash/wm/desks/templates/desks_templates_icon_view.cc
@@ -128,11 +128,12 @@
 void DesksTemplatesIconView::OnFaviconLoaded(
     const favicon_base::FaviconRawBitmapResult& image_result) {
   if (image_result.is_valid()) {
-    icon_view_->SetImage(
+    icon_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage(
         favicon_base::SelectFaviconFramesFromPNGs(
             std::vector<favicon_base::FaviconRawBitmapResult>{image_result},
             favicon_base::GetFaviconScales(), kIconSize)
-            .AsImageSkia());
+            .AsImageSkia(),
+        skia::ImageOperations::RESIZE_BEST, gfx::Size(kIconSize, kIconSize)));
     return;
   }
   LoadDefaultIcon();
@@ -146,7 +147,9 @@
 
   gfx::ImageSkia image_result = icon_value->uncompressed;
   if (!icon_value->is_placeholder_icon && !image_result.isNull()) {
-    icon_view_->SetImage(image_result, gfx::Size(kIconSize, kIconSize));
+    icon_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage(
+        image_result, skia::ImageOperations::RESIZE_BEST,
+        gfx::Size(kIconSize, kIconSize)));
     return;
   }
   LoadDefaultIcon();
diff --git a/ash/wm/desks/templates/desks_templates_unittest.cc b/ash/wm/desks/templates/desks_templates_unittest.cc
index 2ffd18c..c065f6ac 100644
--- a/ash/wm/desks/templates/desks_templates_unittest.cc
+++ b/ash/wm/desks/templates/desks_templates_unittest.cc
@@ -1216,4 +1216,27 @@
   ASSERT_EQ(1ul, GetAllEntries().size());
 }
 
+// Tests that if there is a window minimized in overview, we don't crash when
+// launching a template. Regression test for https://crbug.com/1271337.
+TEST_F(DesksTemplatesTest, LaunchTemplateWithMinimizedOverviewWindow) {
+  // Create a test minimized window.
+  auto window = CreateAppWindow();
+  WindowState::Get(window.get())->Minimize();
+
+  // Open overview and save a template.
+  OpenOverviewAndSaveTemplate(Shell::Get()->GetPrimaryRootWindow());
+  ASSERT_EQ(1ul, GetAllEntries().size());
+
+  // Click on the grid item to launch the template. We should exit overview and
+  // there should be no crash.
+  DeskSwitchAnimationWaiter waiter;
+  ClickOnView(GetItemViewFromOverviewGrid(/*grid_item_index=*/0));
+  // Launching a template fetches it from the desk model asynchronously. Make
+  // sure the async call is done before waiting.
+  WaitForUI();
+  waiter.Wait();
+
+  EXPECT_FALSE(InOverviewSession());
+}
+
 }  // namespace ash
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index 77041f26..fff7468 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -208,7 +208,7 @@
 }
 
 void OverviewItem::HideForDesksTemplatesGrid() {
-  transform_window_.window()->layer()->SetOpacity(0.0f);
+  DCHECK(item_widget_);
   item_widget_->GetLayer()->SetOpacity(0.0f);
 
   for (aura::Window* transient_child :
@@ -222,8 +222,9 @@
 }
 
 void OverviewItem::RevertHideForDesksTemplatesGrid() {
-  transform_window_.window()->layer()->SetOpacity(1.0f);
-  item_widget_->GetLayer()->SetOpacity(1.0f);
+  // `item_widget_` may be null during shutdown if the window is minimized.
+  if (item_widget_)
+    item_widget_->GetLayer()->SetOpacity(1.0f);
 
   for (aura::Window* transient_child :
        GetTransientTreeIterator(transform_window_.window())) {
diff --git a/base/OWNERS b/base/OWNERS
index 61226ac..dbc0afd 100644
--- a/base/OWNERS
+++ b/base/OWNERS
@@ -3,7 +3,6 @@
 set noparent
 # NOTE: keep this in sync with lsc-owners-override@chromium.org owners
 # by emailing lsc-policy@chromium.org when this list changes.
-ajwong@chromium.org
 danakj@chromium.org
 dcheng@chromium.org
 fdoray@chromium.org
diff --git a/base/allocator/partition_allocator/OWNERS b/base/allocator/partition_allocator/OWNERS
index a27ea5b2..3bb0136 100644
--- a/base/allocator/partition_allocator/OWNERS
+++ b/base/allocator/partition_allocator/OWNERS
@@ -1,4 +1,3 @@
-ajwong@chromium.org
 bartekn@chromium.org
 haraken@chromium.org
 lizeb@chromium.org
diff --git a/base/feature_list.cc b/base/feature_list.cc
index d62c7856..77a466b 100644
--- a/base/feature_list.cc
+++ b/base/feature_list.cc
@@ -101,7 +101,7 @@
 // are used in command-line API functions that require ASCII) and whether there
 // are any reserved characters present, returning true if the string is valid.
 // Only called in DCHECKs.
-bool IsValidFeatureOrFieldTrialName(const std::string& name) {
+bool IsValidFeatureOrFieldTrialName(StringPiece name) {
   return IsStringASCII(name) && name.find_first_of(",<*") == std::string::npos;
 }
 
@@ -547,7 +547,15 @@
   DCHECK(IsValidFeatureOrFieldTrialName(feature.name)) << feature.name;
   DCHECK(CheckFeatureIdentity(feature)) << feature.name;
 
-  auto it = overrides_.find(feature.name);
+  return GetOverrideStateByFeatureName(feature.name);
+}
+
+FeatureList::OverrideState FeatureList::GetOverrideStateByFeatureName(
+    StringPiece feature_name) {
+  DCHECK(initialized_);
+  DCHECK(IsValidFeatureOrFieldTrialName(feature_name)) << feature_name;
+
+  auto it = overrides_.find(feature_name);
   if (it != overrides_.end()) {
     const OverrideEntry& entry = it->second;
 
@@ -573,7 +581,7 @@
 const base::FeatureList::OverrideEntry*
 FeatureList::GetOverrideEntryByFeatureName(StringPiece name) {
   DCHECK(initialized_);
-  DCHECK(IsValidFeatureOrFieldTrialName(std::string(name))) << name;
+  DCHECK(IsValidFeatureOrFieldTrialName(name)) << name;
 
   auto it = overrides_.find(name);
   if (it != overrides_.end()) {
@@ -607,6 +615,17 @@
   return nullptr;
 }
 
+std::unique_ptr<FeatureList::Accessor> FeatureList::ConstructAccessor() {
+  if (initialized_) {
+    // This function shouldn't be called after initialization.
+    NOTREACHED();
+    return nullptr;
+  }
+  // Use new and WrapUnique because we want to restrict access to the Accessor's
+  // constructor.
+  return base::WrapUnique(new Accessor(this));
+}
+
 void FeatureList::RegisterOverridesFromCommandLine(
     const std::string& feature_list,
     OverrideState overridden_state) {
@@ -719,4 +738,12 @@
       field_trial(field_trial),
       overridden_by_field_trial(field_trial != nullptr) {}
 
+FeatureList::Accessor::Accessor(FeatureList* feature_list)
+    : feature_list_(feature_list) {}
+
+FeatureList::OverrideState FeatureList::Accessor::GetOverrideStateByFeatureName(
+    StringPiece feature_name) {
+  return feature_list_->GetOverrideStateByFeatureName(feature_name);
+}
+
 }  // namespace base
diff --git a/base/feature_list.h b/base/feature_list.h
index cd918afa..b7c4ed28 100644
--- a/base/feature_list.h
+++ b/base/feature_list.h
@@ -127,6 +127,32 @@
     OVERRIDE_ENABLE_FEATURE,
   };
 
+  // Accessor class, used to look up features by _name_ rather than by Feature
+  // object.
+  // Should only be used in limited cases. See ConstructAccessor() for details.
+  class BASE_EXPORT Accessor {
+   public:
+    Accessor(const Accessor&) = delete;
+    Accessor& operator=(const Accessor&) = delete;
+
+    // Looks up the feature, returning only its override state, rather than
+    // falling back on a default value (since there is no default value given).
+    // Callers of this MUST ensure that there is a consistent, compile-time
+    // default value associated.
+    FeatureList::OverrideState GetOverrideStateByFeatureName(
+        StringPiece feature_name);
+
+   private:
+    // Allow FeatureList to construct this class.
+    friend class FeatureList;
+
+    explicit Accessor(FeatureList* feature_list);
+
+    // Unowned pointer to the FeatureList object we use to look up feature
+    // enablement.
+    FeatureList* feature_list_;
+  };
+
   // Describes a feature override. The first member is a Feature that will be
   // overridden with the state given by the second member.
   using FeatureOverrideInfo =
@@ -234,6 +260,13 @@
   // enables it.
   FieldTrial* GetEnabledFieldTrialByFeatureName(StringPiece name);
 
+  // Construct an accessor allowing access to GetOverrideStateByFeatureName().
+  // This can only be called before the FeatureList is initialized, and is
+  // intended for very narrow use.
+  // If you're tempted to use it, do so only in consultation with feature_list
+  // OWNERS.
+  std::unique_ptr<Accessor> ConstructAccessor();
+
   // Returns whether the given |feature| is enabled. Must only be called after
   // the singleton instance has been registered via SetInstance(). Additionally,
   // a feature with a given name must only have a single corresponding Feature
@@ -305,6 +338,8 @@
                            StoreAndRetrieveFeaturesFromSharedMemory);
   FRIEND_TEST_ALL_PREFIXES(FeatureListTest,
                            StoreAndRetrieveAssociatedFeaturesFromSharedMemory);
+  // Allow Accessor to access GetOverrideStateByFeatureName().
+  friend class Accessor;
 
   struct OverrideEntry {
     // The overridden enable (on/off) state of the feature.
@@ -354,6 +389,9 @@
   // for when the feature state has been observed, e.g. actvating field trials.
   OverrideState GetOverrideState(const Feature& feature);
 
+  // Same as GetOverrideState(), but without a default value.
+  OverrideState GetOverrideStateByFeatureName(StringPiece feature_name);
+
   // Returns the field trial associated with the given |feature|. This is
   // invoked by the public FeatureList::GetFieldTrial() static function on the
   // global singleton. Requires the FeatureList to have already been fully
diff --git a/base/feature_list_unittest.cc b/base/feature_list_unittest.cc
index 4acc154..8a8e093b 100644
--- a/base/feature_list_unittest.cc
+++ b/base/feature_list_unittest.cc
@@ -674,4 +674,66 @@
   EXPECT_EQ(associated_trial2, trial2);
 }
 
+TEST(FeatureListAccessorTest, DefaultStates) {
+  auto feature_list = std::make_unique<FeatureList>();
+  auto feature_list_accessor = feature_list->ConstructAccessor();
+  test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatureList(std::move(feature_list));
+
+  EXPECT_EQ(feature_list_accessor->GetOverrideStateByFeatureName(
+                kFeatureOnByDefault.name),
+            FeatureList::OVERRIDE_USE_DEFAULT);
+  EXPECT_EQ(feature_list_accessor->GetOverrideStateByFeatureName(
+                kFeatureOffByDefault.name),
+            FeatureList::OVERRIDE_USE_DEFAULT);
+}
+
+TEST(FeatureListAccessorTest, InitializeFromCommandLine) {
+  struct {
+    const char* enable_features;
+    const char* disable_features;
+    FeatureList::OverrideState expected_feature_on_state;
+    FeatureList::OverrideState expected_feature_off_state;
+  } test_cases[] = {
+      {"", "", FeatureList::OVERRIDE_USE_DEFAULT,
+       FeatureList::OVERRIDE_USE_DEFAULT},
+      {"OffByDefault", "", FeatureList::OVERRIDE_USE_DEFAULT,
+       FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {"OffByDefault", "OnByDefault", FeatureList::OVERRIDE_DISABLE_FEATURE,
+       FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {"OnByDefault,OffByDefault", "", FeatureList::OVERRIDE_ENABLE_FEATURE,
+       FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {"", "OnByDefault,OffByDefault", FeatureList::OVERRIDE_DISABLE_FEATURE,
+       FeatureList::OVERRIDE_DISABLE_FEATURE},
+      // In the case an entry is both, disable takes precedence.
+      {"OnByDefault", "OnByDefault,OffByDefault",
+       FeatureList::OVERRIDE_DISABLE_FEATURE,
+       FeatureList::OVERRIDE_DISABLE_FEATURE},
+  };
+
+  for (size_t i = 0; i < base::size(test_cases); ++i) {
+    const auto& test_case = test_cases[i];
+    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
+                                    test_case.enable_features,
+                                    test_case.disable_features));
+
+    auto feature_list = std::make_unique<FeatureList>();
+    auto feature_list_accessor = feature_list->ConstructAccessor();
+
+    feature_list->InitializeFromCommandLine(test_case.enable_features,
+                                            test_case.disable_features);
+    test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitWithFeatureList(std::move(feature_list));
+
+    EXPECT_EQ(test_case.expected_feature_on_state,
+              feature_list_accessor->GetOverrideStateByFeatureName(
+                  kFeatureOnByDefault.name))
+        << i;
+    EXPECT_EQ(test_case.expected_feature_off_state,
+              feature_list_accessor->GetOverrideStateByFeatureName(
+                  kFeatureOffByDefault.name))
+        << i;
+  }
+}
+
 }  // namespace base
diff --git a/base/numerics/BUILD.gn b/base/numerics/BUILD.gn
index 0bb8dd10..a6863527 100644
--- a/base/numerics/BUILD.gn
+++ b/base/numerics/BUILD.gn
@@ -21,6 +21,7 @@
     "checked_math.h",
     "clamped_math.h",
     "math_constants.h",
+    "ostream_operators.h",
     "ranges.h",
     "safe_conversions.h",
     "safe_math.h",
diff --git a/base/numerics/clamped_math.h b/base/numerics/clamped_math.h
index 9a3ee4b2..e84d149d 100644
--- a/base/numerics/clamped_math.h
+++ b/base/numerics/clamped_math.h
@@ -192,15 +192,6 @@
   return value;
 }
 
-#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
-// Overload the ostream output operator to make logging work nicely.
-template <typename T>
-std::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) {
-  os << static_cast<T>(value);
-  return os;
-}
-#endif
-
 // These implement the variadic wrapper for the math operations.
 template <template <typename, typename, typename> class M,
           typename L,
diff --git a/base/numerics/ostream_operators.h b/base/numerics/ostream_operators.h
new file mode 100644
index 0000000..cc18f26
--- /dev/null
+++ b/base/numerics/ostream_operators.h
@@ -0,0 +1,35 @@
+// 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 BASE_NUMERICS_OSTREAM_OPERATORS_H_
+#define BASE_NUMERICS_OSTREAM_OPERATORS_H_
+
+#include <ostream>
+
+namespace base {
+namespace internal {
+
+template <typename T>
+class ClampedNumeric;
+template <typename T>
+class StrictNumeric;
+
+// Overload the ostream output operator to make logging work nicely.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
+  os << static_cast<T>(value);
+  return os;
+}
+
+// Overload the ostream output operator to make logging work nicely.
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const ClampedNumeric<T>& value) {
+  os << static_cast<T>(value);
+  return os;
+}
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_NUMERICS_OSTREAM_OPERATORS_H_
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index 34f4cb85..2bc8dd7 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -313,15 +313,6 @@
   return value;
 }
 
-#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
-// Overload the ostream output operator to make logging work nicely.
-template <typename T>
-std::ostream& operator<<(std::ostream& os, const StrictNumeric<T>& value) {
-  os << static_cast<T>(value);
-  return os;
-}
-#endif
-
 #define BASE_NUMERIC_COMPARISON_OPERATORS(CLASS, NAME, OP)              \
   template <typename L, typename R,                                     \
             typename std::enable_if<                                    \
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h
index e30be90..ef5019d 100644
--- a/base/numerics/safe_math.h
+++ b/base/numerics/safe_math.h
@@ -9,4 +9,8 @@
 #include "base/numerics/clamped_math.h"
 #include "base/numerics/safe_conversions.h"
 
+#if !BASE_NUMERICS_DISABLE_OSTREAM_OPERATORS
+#include "base/numerics/ostream_operators.h"
+#endif
+
 #endif  // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/build/android/pylib/local/device/local_device_gtest_run.py b/build/android/pylib/local/device/local_device_gtest_run.py
index ae03db2..ed32431 100644
--- a/build/android/pylib/local/device/local_device_gtest_run.py
+++ b/build/android/pylib/local/device/local_device_gtest_run.py
@@ -590,6 +590,10 @@
     # Delete suspect testcase from tests.
     tests = [test for test in tests if not test in self._crashes]
 
+    # Sort tests by hash.
+    # TODO(crbug.com/1257820): Add sorting logic back to _PartitionTests.
+    tests = self._SortTests(tests)
+
     max_shard_size = self._test_instance.test_launcher_batch_limit
 
     shards.extend(self._PartitionTests(tests, device_count, max_shard_size))
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 5f1d549..ca8a373 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20211122.1.1
+7.20211122.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 5f1d549..ca8a373 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20211122.1.1
+7.20211122.2.1
diff --git a/build/util/lib/common/chrome_test_server_spawner.py b/build/util/lib/common/chrome_test_server_spawner.py
index 61ab9fa..b9d7222 100644
--- a/build/util/lib/common/chrome_test_server_spawner.py
+++ b/build/util/lib/common/chrome_test_server_spawner.py
@@ -38,10 +38,9 @@
 
 
 # Path that are needed to import necessary modules when launching a testserver.
-os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + (':%s:%s:%s'
-    % (os.path.join(_DIR_SOURCE_ROOT, 'third_party'),
-       os.path.join(_DIR_SOURCE_ROOT, 'third_party', 'tlslite'),
-       os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver')))
+os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + (
+    ':%s:%s' % (os.path.join(_DIR_SOURCE_ROOT, 'third_party'),
+                os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver')))
 
 
 def _GetServerTypeCommandLine(server_type):
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index c408f081..19a0a63 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -82,7 +82,9 @@
     "skia_paint_canvas.h",
     "skia_paint_image_generator.cc",
     "skia_paint_image_generator.h",
+    "skottie_frame_data.cc",
     "skottie_frame_data.h",
+    "skottie_frame_data_provider.h",
     "skottie_resource_metadata.cc",
     "skottie_resource_metadata.h",
     "skottie_transfer_cache_entry.cc",
@@ -109,6 +111,7 @@
     "//cc/debug",
     "//skia",
     "//skia:skcms",
+    "//third_party/abseil-cpp:absl",
     "//ui/gfx:color_space",
     "//ui/gfx/geometry",
     "//ui/gfx/geometry:geometry_skia",
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index ebf995a..f0cd43f4 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -1651,6 +1651,7 @@
     SkCanvas* canvas,
     const PlaybackParams& params,
     SkottieResourceIdHash asset_id,
+    float t_frame,
     sk_sp<SkImage>& sk_image,
     SkSamplingOptions& sampling_out) const {
   auto images_iter = images.find(asset_id);
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 9e362309..22940f9 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -832,6 +832,7 @@
       SkCanvas* canvas,
       const PlaybackParams& params,
       SkottieResourceIdHash asset_id,
+      float t_frame,
       sk_sp<SkImage>& image_out,
       SkSamplingOptions& sampling_out) const;
 
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index f59f090f..853679c 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -1544,9 +1544,10 @@
                                             float t) {
   SkottieFrameDataMap images;
   skottie.Seek(
-      t, base::BindLambdaForTesting([&](SkottieResourceIdHash asset_id,
-                                        sk_sp<SkImage>& image_out,
-                                        SkSamplingOptions& sampling_out) {
+      t,
+      base::BindLambdaForTesting([&](SkottieResourceIdHash asset_id,
+                                     float t_frame, sk_sp<SkImage>& image_out,
+                                     SkSamplingOptions& sampling_out) {
         SkottieFrameData frame_data;
         frame_data.image = CreateBitmapImage(
             gfx::Size(skottie_rect.width() / 2, skottie_rect.height() / 2));
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc
index e0fd5b66..f1aa6fe 100644
--- a/cc/paint/skia_paint_canvas.cc
+++ b/cc/paint/skia_paint_canvas.cc
@@ -329,7 +329,7 @@
         << "Rendering skottie frames with image assets directly to a "
            "SkiaPaintCanvas is currently not supported.";
   }
-  skottie->Draw(canvas_, t, dst, SkottieWrapper::FrameDataCallback());
+  skottie->Draw(canvas_, t, dst);
 }
 
 void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
diff --git a/cc/paint/skottie_frame_data.cc b/cc/paint/skottie_frame_data.cc
new file mode 100644
index 0000000..45e2e2f
--- /dev/null
+++ b/cc/paint/skottie_frame_data.cc
@@ -0,0 +1,14 @@
+// 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 "cc/paint/skottie_frame_data.h"
+
+namespace cc {
+
+bool operator==(const SkottieFrameData& frame_l,
+                const SkottieFrameData& frame_r) {
+  return frame_l.image == frame_r.image && frame_l.quality == frame_r.quality;
+}
+
+}  // namespace cc
diff --git a/cc/paint/skottie_frame_data.h b/cc/paint/skottie_frame_data.h
index ecb4114..c76115f 100644
--- a/cc/paint/skottie_frame_data.h
+++ b/cc/paint/skottie_frame_data.h
@@ -6,6 +6,7 @@
 #define CC_PAINT_SKOTTIE_FRAME_DATA_H_
 
 #include "base/containers/flat_map.h"
+#include "cc/paint/paint_export.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_image.h"
 #include "cc/paint/skottie_resource_metadata.h"
@@ -18,7 +19,7 @@
 //
 // There's currently no use case for |skresources::ImageAsset::FrameData.matrix|
 // so it is omitted for now.
-struct SkottieFrameData {
+struct CC_PAINT_EXPORT SkottieFrameData {
   // PaintImage is preferable at the compositor layer instead of a "raw"
   // SkImage. It not only is more well supported for circulating through the
   // compositor/graphics pipeline, but also gives the client the most
@@ -30,6 +31,9 @@
   PaintFlags::FilterQuality quality;
 };
 
+CC_PAINT_EXPORT bool operator==(const SkottieFrameData& frame_l,
+                                const SkottieFrameData& frame_r);
+
 // Map from asset id to the image to use for that asset.
 using SkottieFrameDataMap =
     base::flat_map<SkottieResourceIdHash, SkottieFrameData>;
diff --git a/cc/paint/skottie_frame_data_provider.h b/cc/paint/skottie_frame_data_provider.h
new file mode 100644
index 0000000..28542f7
--- /dev/null
+++ b/cc/paint/skottie_frame_data_provider.h
@@ -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.
+
+#ifndef CC_PAINT_SKOTTIE_FRAME_DATA_PROVIDER_H_
+#define CC_PAINT_SKOTTIE_FRAME_DATA_PROVIDER_H_
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/string_piece.h"
+#include "cc/paint/paint_export.h"
+#include "cc/paint/skottie_frame_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace cc {
+
+// A Chromium-specific version of the skresources::ResourceProvider API, which
+// allows the code driving the animation to specify which image should be used
+// for each asset in each frame of the animation. Callers rendering Skottie
+// animations that may have images embedded in them must implement this API. In
+// the most basic case where an image asset does not change throughout the
+// course of the animation, the same image can be provided for every frame. But
+// more complex logic such as providing a different image at the start of each
+// animation cycle can be implemented if desired.
+//
+// Implementations are not required to be thread-safe (the provider and its
+// ImageAssets shall always be invoked from the same sequence).
+class CC_PAINT_EXPORT SkottieFrameDataProvider {
+ public:
+  class CC_PAINT_EXPORT ImageAsset
+      : public base::RefCountedThreadSafe<ImageAsset> {
+   public:
+    // Returns the image to use for an asset in a frame of a skottie animation.
+    // If absl::nullopt is returned, the most recently provided image for this
+    // asset is reused when the frame is rendered. Thus, the ImageAsset may
+    // return "null" if: a) The most recent image intentionally should be
+    // reused or b) The provider knows that this particular asset does not
+    // appear at the specified timestamp of the animation.
+    //
+    // |t|: See skresources::ImageAsset::getFrame(). Same semantics. Specifies
+    //      the frame of interest in the animation that's about to be rendered.
+    // |scale_factor|: See |image_scale| in gfx::Canvas. Can be used to generate
+    //                 a PaintImage from a gfx::ImageSkia instance.
+    virtual absl::optional<SkottieFrameData> GetFrameData(
+        float t,
+        float scale_factor) = 0;
+
+   protected:
+    virtual ~ImageAsset() = default;
+
+   private:
+    friend class base::RefCountedThreadSafe<ImageAsset>;
+  };
+
+  virtual ~SkottieFrameDataProvider() = default;
+
+  // Loads the image asset in the animation with the given |resource_id|, as it
+  // appears in the lottie json file. The ImageAsset instance that's returned
+  // for the given |resource_id| gets re-used for the lifetime of the animation;
+  // LoadImageAsset() is not called multiple times for the same |resource_id|.
+  // The returned value must never be null.
+  virtual scoped_refptr<ImageAsset> LoadImageAsset(
+      base::StringPiece resource_id,
+      const base::FilePath& resource_path) = 0;
+};
+
+}  // namespace cc
+
+#endif  // CC_PAINT_SKOTTIE_FRAME_DATA_PROVIDER_H_
diff --git a/cc/paint/skottie_mru_resource_provider.cc b/cc/paint/skottie_mru_resource_provider.cc
index 5a0c59d..8a522d2 100644
--- a/cc/paint/skottie_mru_resource_provider.cc
+++ b/cc/paint/skottie_mru_resource_provider.cc
@@ -30,7 +30,7 @@
   FrameData getFrameData(float t) override {
     FrameData new_frame_data;
     SkottieWrapper::FrameDataFetchResult result = frame_data_cb_.Run(
-        asset_id_, new_frame_data.image, new_frame_data.sampling);
+        asset_id_, t, new_frame_data.image, new_frame_data.sampling);
     switch (result) {
       case SkottieWrapper::FrameDataFetchResult::NEW_DATA_AVAILABLE:
         current_frame_data_ = std::move(new_frame_data);
diff --git a/cc/paint/skottie_mru_resource_provider_unittest.cc b/cc/paint/skottie_mru_resource_provider_unittest.cc
index 39f0d7a..caf0f9f 100644
--- a/cc/paint/skottie_mru_resource_provider_unittest.cc
+++ b/cc/paint/skottie_mru_resource_provider_unittest.cc
@@ -48,6 +48,7 @@
 
   SkottieWrapper::FrameDataFetchResult GetFrameDataForAsset(
       SkottieResourceIdHash asset_id,
+      float t,
       sk_sp<SkImage>& image_out,
       SkSamplingOptions& sampling_out) const {
     if (asset_to_frame_data_.contains(asset_id)) {
diff --git a/cc/paint/skottie_wrapper.h b/cc/paint/skottie_wrapper.h
index 2cbcda1d..64edab1a 100644
--- a/cc/paint/skottie_wrapper.h
+++ b/cc/paint/skottie_wrapper.h
@@ -72,9 +72,11 @@
   };
   // The callback's implementation must synchronously fill the output
   // arguments. |asset_id| is guaranteed to be a valid asset that's present
-  // in GetImageAssetMetadata().
+  // in GetImageAssetMetadata(). See skresources::ImageAsset::getFrame() for
+  // the semantics of |t|.
   using FrameDataCallback = base::RepeatingCallback<FrameDataFetchResult(
       SkottieResourceIdHash asset_id,
+      float t,
       sk_sp<SkImage>& image_out,
       SkSamplingOptions& sampling_out)>;
 
diff --git a/cc/paint/skottie_wrapper_impl.cc b/cc/paint/skottie_wrapper_impl.cc
index e031564..e401994 100644
--- a/cc/paint/skottie_wrapper_impl.cc
+++ b/cc/paint/skottie_wrapper_impl.cc
@@ -121,11 +121,13 @@
 
   FrameDataFetchResult RunCurrentFrameDataCallback(
       SkottieResourceIdHash asset_id_hash,
+      float t,
       sk_sp<SkImage>& image_out,
       SkSamplingOptions& sampling_out) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
     lock_.AssertAcquired();
     DCHECK(current_frame_data_cb_);
-    return current_frame_data_cb_.Run(asset_id_hash, image_out, sampling_out);
+    return current_frame_data_cb_.Run(asset_id_hash, t, image_out,
+                                      sampling_out);
   }
 
   base::Lock lock_;
diff --git a/cc/paint/skottie_wrapper_unittest.cc b/cc/paint/skottie_wrapper_unittest.cc
index eff4215e..61f6a982 100644
--- a/cc/paint/skottie_wrapper_unittest.cc
+++ b/cc/paint/skottie_wrapper_unittest.cc
@@ -42,6 +42,7 @@
   MOCK_METHOD(SkottieWrapper::FrameDataFetchResult,
               OnAssetLoaded,
               (SkottieResourceIdHash asset_id_hash,
+               float t,
                sk_sp<SkImage>& image_out,
                SkSamplingOptions& sampling_out));
 
@@ -129,13 +130,13 @@
   ::testing::NiceMock<MockCanvas> canvas;
   MockFrameDataCallback mock_callback;
   EXPECT_CALL(mock_callback,
-              OnAssetLoaded(HashSkottieResourceId("image_0"), _, _));
+              OnAssetLoaded(HashSkottieResourceId("image_0"), _, _, _));
   skottie->Draw(&canvas, /*t=*/0.25, SkRect::MakeWH(500, 500),
                 mock_callback.Get());
   Mock::VerifyAndClearExpectations(&mock_callback);
 
   EXPECT_CALL(mock_callback,
-              OnAssetLoaded(HashSkottieResourceId("image_1"), _, _));
+              OnAssetLoaded(HashSkottieResourceId("image_1"), _, _, _));
   skottie->Draw(&canvas, /*t=*/0.75, SkRect::MakeWH(500, 500),
                 mock_callback.Get());
   Mock::VerifyAndClearExpectations(&mock_callback);
@@ -158,12 +159,12 @@
   ::testing::NiceMock<MockCanvas> canvas;
   MockFrameDataCallback mock_callback;
   EXPECT_CALL(mock_callback,
-              OnAssetLoaded(HashSkottieResourceId("image_0"), _, _));
+              OnAssetLoaded(HashSkottieResourceId("image_0"), _, _, _));
   skottie->Seek(/*t=*/0.25, mock_callback.Get());
   Mock::VerifyAndClearExpectations(&mock_callback);
 
   EXPECT_CALL(mock_callback,
-              OnAssetLoaded(HashSkottieResourceId("image_1"), _, _));
+              OnAssetLoaded(HashSkottieResourceId("image_1"), _, _, _));
   skottie->Seek(/*t=*/0.75, mock_callback.Get());
   Mock::VerifyAndClearExpectations(&mock_callback);
 }
diff --git a/cc/trees/latency_info_swap_promise.cc b/cc/trees/latency_info_swap_promise.cc
index 183e912..a6110c4 100644
--- a/cc/trees/latency_info_swap_promise.cc
+++ b/cc/trees/latency_info_swap_promise.cc
@@ -34,7 +34,7 @@
   return DidNotSwapAction::BREAK_PROMISE;
 }
 
-int64_t LatencyInfoSwapPromise::TraceId() const {
+int64_t LatencyInfoSwapPromise::GetTraceId() const {
   return latency_.trace_id();
 }
 
@@ -47,11 +47,11 @@
               [this](perfetto::EventContext ctx) {
                 ChromeLatencyInfo* latency_info =
                     ctx.event()->set_chrome_latency_info();
-                latency_info->set_trace_id(TraceId());
+                latency_info->set_trace_id(GetTraceId());
                 latency_info->set_step(
                     ChromeLatencyInfo::STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT);
                 tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT,
-                                       TraceId());
+                                       GetTraceId());
               });
 }
 
diff --git a/cc/trees/latency_info_swap_promise.h b/cc/trees/latency_info_swap_promise.h
index 5891dfe..23e07e8 100644
--- a/cc/trees/latency_info_swap_promise.h
+++ b/cc/trees/latency_info_swap_promise.h
@@ -30,7 +30,7 @@
   DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override;
   void OnCommit() override;
 
-  int64_t TraceId() const override;
+  int64_t GetTraceId() const override;
 
  private:
   ui::LatencyInfo latency_;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 2c3c030..07825bcf 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -745,7 +745,7 @@
   proxy_->SetTargetLocalSurfaceId(target_local_surface_id);
 }
 
-bool LayerTreeHost::RequestedMainFramePendingForTesting() const {
+bool LayerTreeHost::RequestedMainFramePending() const {
   return proxy_->RequestedAnimatePending();
 }
 
@@ -1104,10 +1104,10 @@
         "input,benchmark", "LatencyInfo.Flow",
         [&swap_promise](perfetto::EventContext ctx) {
           ChromeLatencyInfo* info = ctx.event()->set_chrome_latency_info();
-          info->set_trace_id(swap_promise->TraceId());
+          info->set_trace_id(swap_promise->GetTraceId());
           info->set_step(ChromeLatencyInfo::STEP_MAIN_THREAD_SCROLL_UPDATE);
           tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT,
-                                 swap_promise->TraceId());
+                                 swap_promise->GetTraceId());
         });
     swap_promise_manager_.QueueSwapPromise(std::move(swap_promise));
   }
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 2fce4b3..610a9ec 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -277,7 +277,7 @@
 
   // Returns true after SetNeedsAnimate(), SetNeedsUpdateLayers() or
   // SetNeedsCommit(), until it is satisfied.
-  bool RequestedMainFramePendingForTesting() const;
+  bool RequestedMainFramePending() const;
 
   // Requests that the next frame re-chooses crisp raster scales for all layers.
   void SetNeedsRecalculateRasterScales();
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 053391e..c6c3dab 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -562,8 +562,11 @@
     if (pending_tree_) {
       pending_tree_->AppendSwapPromises(std::move(swap_promises));
     } else {
-      for (const auto& swap_promise : swap_promises)
-        swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE);
+      for (const auto& swap_promise : swap_promises) {
+        SwapPromise::DidNotSwapAction action =
+            swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE);
+        DCHECK_EQ(action, SwapPromise::DidNotSwapAction::BREAK_PROMISE);
+      }
     }
   }
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 96fad38..cf9f7843 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -4042,7 +4042,8 @@
   std::unique_ptr<CompositorCommitData> commit_data =
       host_impl_->ProcessCompositorDeltas();
   EXPECT_EQ(1u, commit_data->swap_promises.size());
-  EXPECT_EQ(latency_info.trace_id(), commit_data->swap_promises[0]->TraceId());
+  EXPECT_EQ(latency_info.trace_id(),
+            commit_data->swap_promises[0]->GetTraceId());
 }
 
 // Test that scrolls targeting a layer with a non-null scroll_parent() don't
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 1ad1bd4c..10fab13 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -275,7 +275,7 @@
 
   void NextStep() {
     // The MainFrame request is cleared once a MainFrame happens.
-    EXPECT_FALSE(layer_tree_host()->RequestedMainFramePendingForTesting());
+    EXPECT_FALSE(layer_tree_host()->RequestedMainFramePending());
     switch (layer_tree_host()->SourceFrameNumber()) {
       case 0:
         ADD_FAILURE()
@@ -295,7 +295,7 @@
         return;
     }
     // SetNeeds{Animate,UpdateLayers,Commit}() will mean a MainFrame is pending.
-    EXPECT_TRUE(layer_tree_host()->RequestedMainFramePendingForTesting());
+    EXPECT_TRUE(layer_tree_host()->RequestedMainFramePending());
   }
 };
 
@@ -6079,7 +6079,7 @@
 
   void set_action(DidNotSwapAction action) { action_ = action; }
 
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 
  private:
   // Not owned.
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 215ae8d..d84bacfd 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1774,12 +1774,12 @@
 
   state->BeginArray("swap_promise_trace_ids");
   for (const auto& swap_promise : swap_promise_list_)
-    state->AppendDouble(swap_promise->TraceId());
+    state->AppendDouble(swap_promise->GetTraceId());
   state->EndArray();
 
   state->BeginArray("pinned_swap_promise_trace_ids");
   for (const auto& swap_promise : pinned_swap_promise_list_)
-    state->AppendDouble(swap_promise->TraceId());
+    state->AppendDouble(swap_promise->GetTraceId());
   state->EndArray();
 
   state->BeginArray("layers");
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index 4f02f3a..ce43bcf 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -2282,9 +2282,7 @@
   DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override {
     return DidNotSwapAction::KEEP_ACTIVE;
   }
-
-  void OnCommit() override {}
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 };
 
 class NotPersistentSwapPromise
@@ -2301,9 +2299,7 @@
   DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override {
     return DidNotSwapAction::BREAK_PROMISE;
   }
-
-  void OnCommit() override {}
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 };
 
 }  // namespace
diff --git a/cc/trees/swap_promise.h b/cc/trees/swap_promise.h
index b5638c9..2276ba30 100644
--- a/cc/trees/swap_promise.h
+++ b/cc/trees/swap_promise.h
@@ -63,16 +63,18 @@
   virtual void DidActivate() = 0;
   virtual void WillSwap(viz::CompositorFrameMetadata* metadata) = 0;
   virtual void DidSwap() = 0;
-  // Return |KEEP_ACTIVE| if this promise should remain active (should not be
-  // broken by the owner).
+
+  // Return `DidNotSwapAction::KEEP_ACTIVE` if this promise should remain active
+  // (should not be broken by the owner).
   virtual DidNotSwapAction DidNotSwap(DidNotSwapReason reason) = 0;
+
   // This is called when the main thread starts a (blocking) commit
   virtual void OnCommit() {}
 
   // A non-zero trace id identifies a trace flow object that is embedded in the
   // swap promise. This can be used for registering additional flow steps to
   // visualize the object's path through the system.
-  virtual int64_t TraceId() const = 0;
+  virtual int64_t GetTraceId() const = 0;
 };
 
 }  // namespace cc
diff --git a/cc/trees/swap_promise_manager.cc b/cc/trees/swap_promise_manager.cc
index 5ea992a..0688939 100644
--- a/cc/trees/swap_promise_manager.cc
+++ b/cc/trees/swap_promise_manager.cc
@@ -54,6 +54,7 @@
 void SwapPromiseManager::BreakSwapPromises(
     SwapPromise::DidNotSwapReason reason) {
   std::vector<std::unique_ptr<SwapPromise>> keep_active_swap_promises;
+  keep_active_swap_promises.reserve(swap_promise_list_.size());
   for (auto& swap_promise : swap_promise_list_) {
     if (swap_promise->DidNotSwap(reason) ==
         SwapPromise::DidNotSwapAction::KEEP_ACTIVE) {
diff --git a/cc/trees/swap_promise_manager_unittest.cc b/cc/trees/swap_promise_manager_unittest.cc
index 7d8746e..354e9d2 100644
--- a/cc/trees/swap_promise_manager_unittest.cc
+++ b/cc/trees/swap_promise_manager_unittest.cc
@@ -28,7 +28,7 @@
     return DidNotSwapAction::BREAK_PROMISE;
   }
   MOCK_METHOD0(OnCommit, void());
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 };
 
 TEST(SwapPromiseManagerTest, SwapPromiseMonitors) {
diff --git a/chrome/VERSION b/chrome/VERSION
index 9d56f09..d445d98 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=98
 MINOR=0
-BUILD=4724
+BUILD=4725
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 09a13f2..8f3dd66 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -288,6 +288,7 @@
     "//chrome/browser/policy/android:delegate_public_impl_java",
     "//chrome/browser/ui/android/theme:delegate_public_impl_java",
     "//components/externalauth/android:google_delegate_public_impl_java",
+    "//components/language/android:ulp_delegate_public_java",
   ]
   if (enable_new_feed_hooks) {
     deps += [ "//chrome/browser/feed/android:hooks_public_impl_java" ]
@@ -497,7 +498,7 @@
     "//components/infobars/core:infobar_enums_java",
     "//components/installedapp/android:java",
     "//components/javascript_dialogs/android:java",
-    "//components/language/android:language_bridge_java",
+    "//components/language/android:java",
     "//components/location/android:location_java",
     "//components/location/android:settings_java",
     "//components/media_router/browser/android:java",
@@ -589,6 +590,7 @@
     "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
     "//third_party/android_deps:com_google_guava_listenablefuture_java",
     "//third_party/android_deps:dagger_java",
+    "//third_party/android_deps:guava_android_java",
     "//third_party/android_deps:javax_inject_javax_inject_java",
     "//third_party/android_deps:material_design_java",
     "//third_party/android_deps:protobuf_lite_runtime_java",
@@ -1120,7 +1122,6 @@
     "//third_party/android_deps:dagger_java",
     "//third_party/android_deps:espresso_java",
     "//third_party/android_deps:guava_android_java",
-    "//third_party/android_deps:material_design_java",
     "//third_party/android_deps:protobuf_lite_runtime_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
@@ -1486,6 +1487,8 @@
     "//components/infobars/core:infobar_enums_java",
     "//components/installedapp/android:javatests",
     "//components/javascript_dialogs/android:java",
+    "//components/language/android:java",
+    "//components/language/android:javatests",
     "//components/location/android:location_java",
     "//components/media_router/browser/android:java",
     "//components/media_router/browser/android:test_support_java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index fc382c7..e368df8b 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -95,6 +95,8 @@
   "java/res/drawable-hdpi/tabswitcher_border_frame_decoration.9.png",
   "java/res/drawable-hdpi/tabswitcher_border_frame_inner_shadow.9.png",
   "java/res/drawable-hdpi/tabswitcher_border_frame_shadow.9.png",
+  "java/res/drawable-hdpi/toolbar_shadow_focused.png",
+  "java/res/drawable-hdpi/toolbar_shadow_normal.png",
   "java/res/drawable-hdpi/troy_card.png",
   "java/res/drawable-hdpi/unionpay_card.png",
   "java/res/drawable-hdpi/verify_checkmark.png",
@@ -189,6 +191,8 @@
   "java/res/drawable-mdpi/tabswitcher_border_frame_decoration.9.png",
   "java/res/drawable-mdpi/tabswitcher_border_frame_inner_shadow.9.png",
   "java/res/drawable-mdpi/tabswitcher_border_frame_shadow.9.png",
+  "java/res/drawable-mdpi/toolbar_shadow_focused.png",
+  "java/res/drawable-mdpi/toolbar_shadow_normal.png",
   "java/res/drawable-mdpi/troy_card.png",
   "java/res/drawable-mdpi/unionpay_card.png",
   "java/res/drawable-mdpi/verify_checkmark.png",
@@ -199,6 +203,7 @@
   "java/res/drawable-sw600dp-xhdpi/google_logo.png",
   "java/res/drawable-sw600dp-xxhdpi/google_logo.png",
   "java/res/drawable-sw600dp-xxxhdpi/google_logo.png",
+  "java/res/drawable-sw600dp/toolbar_shadow.xml",
   "java/res/drawable-sw600dp/window_background.xml",
   "java/res/drawable-v21/button_borderless_compat.xml",
   "java/res/drawable-v21/text_cursor_lowend.xml",
@@ -283,6 +288,8 @@
   "java/res/drawable-xhdpi/tabswitcher_border_frame_decoration.9.png",
   "java/res/drawable-xhdpi/tabswitcher_border_frame_inner_shadow.9.png",
   "java/res/drawable-xhdpi/tabswitcher_border_frame_shadow.9.png",
+  "java/res/drawable-xhdpi/toolbar_shadow_focused.png",
+  "java/res/drawable-xhdpi/toolbar_shadow_normal.png",
   "java/res/drawable-xhdpi/troy_card.png",
   "java/res/drawable-xhdpi/unionpay_card.png",
   "java/res/drawable-xhdpi/verify_checkmark.png",
@@ -360,6 +367,8 @@
   "java/res/drawable-xxhdpi/tabswitcher_border_frame_decoration.9.png",
   "java/res/drawable-xxhdpi/tabswitcher_border_frame_inner_shadow.9.png",
   "java/res/drawable-xxhdpi/tabswitcher_border_frame_shadow.9.png",
+  "java/res/drawable-xxhdpi/toolbar_shadow_focused.png",
+  "java/res/drawable-xxhdpi/toolbar_shadow_normal.png",
   "java/res/drawable-xxhdpi/troy_card.png",
   "java/res/drawable-xxhdpi/unionpay_card.png",
   "java/res/drawable-xxhdpi/verify_checkmark.png",
@@ -434,6 +443,8 @@
   "java/res/drawable-xxxhdpi/tabswitcher_border_frame_decoration.9.png",
   "java/res/drawable-xxxhdpi/tabswitcher_border_frame_inner_shadow.9.png",
   "java/res/drawable-xxxhdpi/tabswitcher_border_frame_shadow.9.png",
+  "java/res/drawable-xxxhdpi/toolbar_shadow_focused.png",
+  "java/res/drawable-xxxhdpi/toolbar_shadow_normal.png",
   "java/res/drawable-xxxhdpi/troy_card.png",
   "java/res/drawable-xxxhdpi/unionpay_card.png",
   "java/res/drawable-xxxhdpi/verify_checkmark.png",
@@ -524,6 +535,7 @@
   "java/res/drawable/price_tracking_enabled_filled.xml",
   "java/res/drawable/price_tracking_enabled_outline.xml",
   "java/res/drawable/qr_code.xml",
+  "java/res/drawable/safety_check.xml",
   "java/res/drawable/screenshot.xml",
   "java/res/drawable/send_tab.xml",
   "java/res/drawable/shared_clipboard_zero_state_dark.xml",
@@ -537,6 +549,7 @@
   "java/res/drawable/thumbnail_gradient_top_left.xml",
   "java/res/drawable/thumbnail_gradient_top_right.xml",
   "java/res/drawable/tile_view_hairline_border_background.xml",
+  "java/res/drawable/toolbar_shadow.xml",
   "java/res/drawable/visa_card.xml",
   "java/res/layout-sw360dp/preference_spinner_single_line.xml",
   "java/res/layout-sw600dp/find_toolbar.xml",
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
index 11f4f06..9daaa539 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -505,7 +505,8 @@
     // clang-format off
     @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID,
             ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study",
-            ChromeFeatureList.START_SURFACE_ANDROID + "<Study"})
+            ChromeFeatureList.START_SURFACE_ANDROID + "<Study",
+            ChromeFeatureList.THEME_REFACTOR_ANDROID})
     @CommandLineFlags.Add({ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
             "force-fieldtrials=Study/Group",
             IMMEDIATE_RETURN_PARAMS + "/start_surface_variation/single"})
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 3eadc2f..67725f6 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -28,6 +28,7 @@
     "java/res/anim/iph_touch_point_animation.xml",
     "java/res/anim/iph_touch_point_background_alpha_animation.xml",
     "java/res/anim/iph_touch_point_background_animation.xml",
+    "java/res/color/dark_text_color_list.xml",
     "java/res/drawable-v21/fake_search_box_bg_incognito.xml",
     "java/res/drawable/chevron_right.xml",
     "java/res/drawable/fake_search_box_text_box_bg_incognito.xml",
diff --git a/chrome/android/features/tab_ui/java/res/color/dark_text_color_list.xml b/chrome/android/features/tab_ui/java/res/color/dark_text_color_list.xml
new file mode 100644
index 0000000..fa06562
--- /dev/null
+++ b/chrome/android/features/tab_ui/java/res/color/dark_text_color_list.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="@dimen/default_disabled_alpha"
+        android:color="@color/default_text_color_dark" android:state_enabled="false"/>
+    <item android:color="@color/default_text_color_dark" />
+</selector>
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/res/values/colors.xml b/chrome/android/features/tab_ui/java/res/values/colors.xml
index f535bc4..5d9e5f13 100644
--- a/chrome/android/features/tab_ui/java/res/values/colors.xml
+++ b/chrome/android/features/tab_ui/java/res/values/colors.xml
@@ -5,18 +5,44 @@
 
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Tab Switcher colors. -->
+    <color name="tab_grid_card_view_tint_color">@color/legacy_bg_color_elev_4</color>
+    <color name="tab_grid_card_view_tint_color_incognito">@color/default_bg_color_dark_elev_4</color>
+
+    <color name="tab_grid_card_title_text_color">@color/default_text_color_list</color>
+    <color name="tab_grid_card_title_text_color_incognito">@color/default_text_color_light_list</color>
+
+    <color name="tab_group_number_text_color">@color/default_text_color_list</color>
+    <color name="tab_group_number_text_color_incognito">@color/default_text_color_light</color>
+
+    <color name="tab_grid_card_action_button_tint_color">@color/default_icon_color_baseline</color>
+    <color name="tab_grid_card_action_button_tint_color_incognito">@color/default_icon_color_light</color>
+
     <color name="tab_grid_card_divider_tint_color_incognito">@color/divider_line_bg_color_light</color>
 
     <color name="tab_grid_card_thumbnail_placeholder_color">@color/default_bg_color_secondary</color>
     <color name="tab_grid_card_thumbnail_placeholder_color_incognito">@color/default_bg_color_dark_elev_3</color>
 
+    <color name="tab_grid_card_selected_color">@color/default_control_color_active</color>
+    <color name="tab_grid_card_selected_color_incognito">@color/default_control_color_active_dark</color>
+
     <!-- Tab Group related colors. -->
+    <color name="tab_list_mini_card_default_background_color">@color/default_bg_color_secondary</color>
+    <color name="tab_list_mini_card_default_background_color_incognito">@color/default_bg_color_secondary_dark</color>
+
     <color name="tab_grid_dialog_background_color">@color/legacy_bg_color_elev_1</color>
+    <color name="tab_grid_dialog_background_color_incognito">@color/default_bg_color_dark_elev_1</color>
+
+    <color name="tab_grid_dialog_ungroup_button_text_color">@color/default_icon_color_accent1_baseline</color>
+    <color name="tab_grid_dialog_ungroup_button_text_color_incognito">@color/default_icon_color_blue_light</color>
+    <color name="tab_grid_dialog_ungroup_button_text_color_hovered">@color/default_text_color_light_list</color>
+
+    <color name="ungroup_bar_shadow_color">@android:color/black</color>
 
     <color name="favicon_background_color">@color/default_bg_color_secondary</color>
     <color name="favicon_background_color_incognito">@color/black_alpha_38</color>
 
     <color name="hovered_tab_grid_card_background_color">@color/default_bg_color_secondary</color>
+    <color name="hovered_tab_grid_card_background_color_incognito">@color/default_bg_color_secondary_dark</color>
 
     <color name="new_tab_tile_plus_color">@color/default_icon_color_secondary</color>
     <color name="new_tab_tile_plus_color_incognito">@color/default_icon_color_secondary_light</color>
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml
index 397bff2..1fd75ca 100644
--- a/chrome/android/features/tab_ui/java/res/values/dimens.xml
+++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -9,6 +9,7 @@
     <dimen name="tab_list_selected_margin">7dp</dimen>
     <dimen name="tab_list_card_padding">8dp</dimen>
     <dimen name="tab_list_card_radius">4dp</dimen>
+    <dimen name="tab_list_card_title_height">32dp</dimen>
     <dimen name="tab_grid_price_card_radius">4dp</dimen>
     <dimen name="tab_list_mini_card_radius">4dp</dimen>
     <dimen name="tab_list_mini_card_frame_size">1dp</dimen>
@@ -58,6 +59,7 @@
     <dimen name="tab_grid_card_thumbnail_corner_radius_top">4dp</dimen>
     <dimen name="tab_grid_card_thumbnail_corner_radius_bottom">12dp</dimen>
     <dimen name="tab_grid_card_thumbnail_margin">4dp</dimen>
+    <dimen name="tab_list_card_margin">2dp</dimen>
     <dimen name="tab_list_card_action_button_size">48dp</dimen>
     <dimen name="tab_list_card_action_button_margin">4dp</dimen>
     <dimen name="tab_list_card_title_fading_length">24dp</dimen>
diff --git a/chrome/android/features/tab_ui/java/res/values/styles.xml b/chrome/android/features/tab_ui/java/res/values/styles.xml
index bfc83d99..42f4227 100644
--- a/chrome/android/features/tab_ui/java/res/values/styles.xml
+++ b/chrome/android/features/tab_ui/java/res/values/styles.xml
@@ -13,6 +13,7 @@
         <item name="colorControlHighlight">@color/filled_button_bg_color</item>
     </style>
 
+    <integer name="view_visible">0</integer> <!-- This is VISIBLE -->
     <integer name="view_gone">2</integer> <!-- This is GONE -->
 
     <!-- Theme overlay for theme refactor 2021 -->
@@ -64,11 +65,35 @@
         <item name="android:fadingEdgeLength">@dimen/tab_grid_card_title_fading_length</item>
     </style>
 
+    <style name="TabGridDialogUngroupBarDivider.Shadow" parent="">
+        <item name="android:layout_height">@dimen/toolbar_shadow_height</item>
+        <item name="android:src">@drawable/modern_toolbar_shadow</item>
+        <item name="android:tint">@color/ungroup_bar_shadow_color</item>
+        <item name="android:scaleType">fitXY</item>
+        <item name="android:scaleY">-1</item>
+    </style>
+
     <style name="TabGridDialogUngroupBarDivider.Hairline" parent="">
         <item name="android:layout_height">wrap_content</item>
         <item name="android:src">@drawable/toolbar_hairline</item>
     </style>
 
+    <style name="ThemeRefactorOverlay.Disabled.TabUi" parent="">
+        <item name="tabGridDividerVisible">@integer/view_visible</item>
+        <item name="tabGridHeaderHeight">@dimen/tab_list_card_title_height</item>
+        <item name="tabGridBackground">@drawable/dialog_bg_tinted</item>
+        <item name="tabGridMargin">@dimen/tab_list_card_margin</item>
+
+        <item name="tabGridFaviconStyle">@style/TabGridCardTopFaviconStyle</item>
+        <item name="tabGridActionButtonStyle">@style/TabGridCardActionButtonStyle</item>
+        <item name="tabGridThumbnailStyle">@style/TabGridCardThumbnailStyle</item>
+        <item name="tabGridTitleStyle">@style/TabGridCardTitleStyle</item>
+
+        <item name="tabGridDialogCornerRadius">@dimen/tab_list_card_radius</item>
+        <item name="tabGridDialogAppBarPadding">0dp</item>
+        <item name="tabGridDialogUngroupBarDividerStyle">@style/TabGridDialogUngroupBarDivider.Shadow</item>
+    </style>
+
     <style name="ThemeRefactorOverlay.Enabled.TabUi" parent="">
         <item name="tabGridDividerVisible">@integer/view_gone</item>
         <item name="tabGridHeaderHeight">@dimen/tab_grid_card_header_height</item>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
index df4baf7..99b3136 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
@@ -185,6 +185,11 @@
                     new Rect(0, 0, thumbnail.getWidth(), thumbnail.getHeight()),
                     mThumbnailRects.get(index), mThumbnailBasePaint);
             thumbnail.recycle();
+
+            if (!TabUiThemeProvider.themeRefactorEnabled()) {
+                mCanvas.drawRoundRect(
+                        mThumbnailRects.get(index), mRadius, mRadius, mThumbnailFramePaint);
+            }
         }
 
         private void drawFaviconDrawableOnCanvasWithFrame(Drawable favicon, int index) {
@@ -273,7 +278,7 @@
                 resource.getDimension(R.dimen.tab_grid_thumbnail_favicon_background_down_shift),
                 resource.getColor(R.color.modern_grey_800_alpha_38));
 
-        initializedThumbnailRects(context);
+        initializedThumbnailRects(context, expectedThumbnailAspectRatio);
 
         // Initialize Rects for favicons and favicon frame.
         final float halfFaviconFrameSize =
@@ -336,26 +341,39 @@
     }
 
     /**
-     * Initialize rects used for thumbnails.
+     * Initialize rects used for thumbnails. Depending on whether thene refacotr is enabled, the
+     * padding around the thumbnail is different.
      */
-    private void initializedThumbnailRects(Context context) {
+    private void initializedThumbnailRects(Context context, float expectedThumbnailAspectRatio) {
+        boolean themeRefactorEnabled = TabUiThemeProvider.themeRefactorEnabled();
+
         float thumbnailHorizontalPadding =
                 TabUiThemeProvider.getTabMiniThumbnailPaddingDimension(context);
-        float thumbnailVerticalPadding = thumbnailHorizontalPadding;
+        float thumbnailVerticalPadding = themeRefactorEnabled
+                ? thumbnailHorizontalPadding
+                : thumbnailHorizontalPadding / expectedThumbnailAspectRatio;
+        float multiThumbnailHorizontalPadding =
+                themeRefactorEnabled ? 0 : thumbnailHorizontalPadding;
+        float multiThumbnailVerticalPadding = themeRefactorEnabled ? 0 : thumbnailVerticalPadding;
 
         float centerX = mThumbnailWidth * 0.5f;
         float centerY = mThumbnailHeight * 0.5f;
         float halfThumbnailHorizontalPadding = thumbnailHorizontalPadding / 2;
         float halfThumbnailVerticalPadding = thumbnailVerticalPadding / 2;
 
-        mThumbnailRects.add(new RectF(0, 0, centerX - halfThumbnailHorizontalPadding,
+        mThumbnailRects.add(new RectF(multiThumbnailHorizontalPadding,
+                multiThumbnailVerticalPadding, centerX - halfThumbnailHorizontalPadding,
                 centerY - halfThumbnailVerticalPadding));
-        mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding, 0, mThumbnailWidth,
-                centerY - halfThumbnailVerticalPadding));
-        mThumbnailRects.add(new RectF(0, centerY + halfThumbnailVerticalPadding,
-                centerX - halfThumbnailHorizontalPadding, mThumbnailHeight));
         mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding,
-                centerY + halfThumbnailVerticalPadding, mThumbnailWidth, mThumbnailHeight));
+                multiThumbnailVerticalPadding, mThumbnailWidth - multiThumbnailHorizontalPadding,
+                centerY - halfThumbnailVerticalPadding));
+        mThumbnailRects.add(new RectF(multiThumbnailHorizontalPadding,
+                centerY + halfThumbnailVerticalPadding, centerX - halfThumbnailHorizontalPadding,
+                mThumbnailHeight - multiThumbnailVerticalPadding));
+        mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding,
+                centerY + halfThumbnailVerticalPadding,
+                mThumbnailWidth - multiThumbnailHorizontalPadding,
+                mThumbnailHeight - multiThumbnailVerticalPadding));
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridThumbnailView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridThumbnailView.java
index 778b4596..dfda4ef 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridThumbnailView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridThumbnailView.java
@@ -55,6 +55,11 @@
      * @param isSelected Whether the thumbnail is on a selected tab.
      */
     void setColorThumbnailPlaceHolder(boolean isIncognito, boolean isSelected) {
+        if (!TabUiThemeProvider.themeRefactorEnabled()) {
+            setImageResource(TabUiThemeProvider.getThumbnailPlaceHolderColorResource(isIncognito));
+            return;
+        }
+
         ColorDrawable placeHolder =
                 new ColorDrawable(TabUiThemeProvider.getMiniThumbnailPlaceHolderColor(
                         getContext(), isIncognito, isSelected));
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 3ea7d83..e85e109c 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
@@ -7,16 +7,19 @@
 import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_ALPHA;
 
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import androidx.annotation.ColorInt;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.content.res.ResourcesCompat;
 import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.core.view.ViewCompat;
 import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
@@ -104,10 +107,21 @@
             tabTitleView.setContentDescription(
                     view.getResources().getString(R.string.accessibility_tabstrip_tab, title));
         } else if (TabProperties.IS_SELECTED == propertyKey) {
-            updateColor(view, model.get(TabProperties.IS_INCOGNITO),
-                    model.get(TabProperties.IS_SELECTED));
-            updateThumbnail(view, model);
-            updateFavicon(view, model);
+            if (TabUiThemeProvider.themeRefactorEnabled()) {
+                updateColor(view, model.get(TabProperties.IS_INCOGNITO),
+                        model.get(TabProperties.IS_SELECTED));
+                updateThumbnail(view, model);
+                updateFavicon(view, model);
+            } else {
+                int selectedTabBackground =
+                        model.get(TabProperties.SELECTED_TAB_BACKGROUND_DRAWABLE_ID);
+                Resources res = view.getResources();
+                Resources.Theme theme = view.getContext().getTheme();
+                Drawable drawable = new InsetDrawable(
+                        ResourcesCompat.getDrawable(res, selectedTabBackground, theme),
+                        (int) res.getDimension(R.dimen.tab_list_selected_inset));
+                view.setForeground(model.get(TabProperties.IS_SELECTED) ? drawable : null);
+            }
             if (TabUiFeatureUtilities.ENABLE_SEARCH_CHIP.getValue()) {
                 ChipView pageInfoButton = (ChipView) view.fastFindViewById(R.id.page_info_button);
                 pageInfoButton.getPrimaryTextView().setTextAlignment(
@@ -366,7 +380,7 @@
                 (ChromeImageView) rootView.fastFindViewById(R.id.background_view);
 
         cardView.getBackground().mutate();
-        final @ColorInt int backgroundColor = TabUiThemeProvider.getCardViewBackgroundColor(
+        int backgroundColor = TabUiThemeProvider.getCardViewBackgroundColor(
                 cardView.getContext(), isIncognito, isSelected);
         ViewCompat.setBackgroundTintList(cardView, ColorStateList.valueOf(backgroundColor));
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
index 5c231a8a..8385fc9e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
@@ -37,6 +37,7 @@
 import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.base.Log;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.tab_ui.R;
@@ -222,12 +223,18 @@
         if (mShadowImageView == null) {
             Context context = getContext();
             mShadowImageView = new ImageView(context);
-            Drawable drawable = context.getDrawable(R.drawable.toolbar_hairline);
+            boolean themeRefactorEnabled =
+                    CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID);
+            Drawable drawable =
+                    context.getDrawable(themeRefactorEnabled ? R.drawable.toolbar_hairline
+                                                             : R.drawable.modern_toolbar_shadow);
             mShadowImageView.setImageDrawable(drawable);
             mShadowImageView.setScaleType(ImageView.ScaleType.FIT_XY);
             mShadowImageView.setTag(SHADOW_VIEW_TAG);
             Resources res = context.getResources();
-            int shadowHeight = res.getDimensionPixelSize(R.dimen.toolbar_hairline_height);
+            int shadowHeight =
+                    res.getDimensionPixelSize(themeRefactorEnabled ? R.dimen.toolbar_hairline_height
+                                                                   : R.dimen.toolbar_shadow_height);
             if (getParent() instanceof FrameLayout) {
                 // Add shadow for grid tab switcher.
                 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
index d79604d..003735d63 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
@@ -20,6 +20,8 @@
 import com.google.android.material.elevation.ElevationOverlayProvider;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.styles.SemanticColorUtils;
 
@@ -39,6 +41,15 @@
     @ColorInt
     public static int getCardViewBackgroundColor(
             Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            // Use #getColorStateList to take advantage of reading resource with attributes.
+            return AppCompatResources
+                    .getColorStateList(context,
+                            isIncognito ? R.color.tab_grid_card_view_tint_color_incognito
+                                        : R.color.tab_grid_card_view_tint_color)
+                    .getDefaultColor();
+        }
+
         if (isIncognito) {
             // Incognito does not use dynamic colors, so it can use colors from resources.
             @ColorRes
@@ -68,6 +79,13 @@
     @ColorInt
     public static int getTabGroupNumberTextColor(
             Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            return AppCompatResources
+                    .getColorStateList(context,
+                            isIncognito ? R.color.tab_group_number_text_color_incognito
+                                        : R.color.tab_group_number_text_color)
+                    .getDefaultColor();
+        }
         if (isIncognito) {
             @ColorRes
             int colorRes = isSelected ? R.color.incognito_tab_tile_number_selected_color
@@ -88,6 +106,14 @@
      */
     @ColorInt
     public static int getTitleTextColor(Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            return AppCompatResources
+                    .getColorStateList(context,
+                            isIncognito ? R.color.tab_grid_card_title_text_color_incognito
+                                        : R.color.tab_grid_card_title_text_color)
+                    .getDefaultColor();
+        }
+
         if (isIncognito) {
             @ColorRes
             int colorRes = isSelected ? R.color.incognito_tab_title_selected_color
@@ -110,6 +136,12 @@
      */
     public static ColorStateList getActionButtonTintList(
             Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            return AppCompatResources.getColorStateList(context,
+                    isIncognito ? R.color.tab_grid_card_action_button_tint_color_incognito
+                                : R.color.tab_grid_card_action_button_tint_color);
+        }
+
         if (isIncognito) {
             @ColorRes
             int colorRes = isSelected ? R.color.incognito_tab_action_button_selected_color
@@ -135,6 +167,18 @@
      */
     public static ColorStateList getToggleActionButtonBackgroundTintList(
             Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            @ColorRes
+            int colorRes;
+            if (isSelected) {
+                colorRes = isIncognito ? R.color.tab_grid_card_selected_color_incognito
+                                       : R.color.tab_grid_card_selected_color;
+            } else {
+                colorRes = isIncognito ? R.color.default_icon_color_light
+                                       : R.color.default_icon_color_baseline;
+            }
+            return AppCompatResources.getColorStateList(context, colorRes);
+        }
         return getActionButtonTintList(context, isIncognito, isSelected);
     }
 
@@ -148,6 +192,11 @@
      */
     public static ColorStateList getToggleActionButtonCheckedDrawableTintList(
             Context context, boolean isIncognito) {
+        if (!themeRefactorEnabled()) {
+            return AppCompatResources.getColorStateList(context,
+                    isIncognito ? R.color.default_icon_color_dark
+                                : R.color.default_icon_color_inverse);
+        }
         if (isIncognito) {
             return AppCompatResources.getColorStateList(
                     context, R.color.incognito_tab_bg_selected_color);
@@ -206,6 +255,12 @@
     @ColorInt
     public static int getMiniThumbnailPlaceHolderColor(
             Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            return ApiCompatibilityUtils.getColor(context.getResources(),
+                    isIncognito ? R.color.tab_list_mini_card_default_background_color_incognito
+                                : R.color.tab_list_mini_card_default_background_color);
+        }
+
         if (isIncognito) {
             @ColorRes
             int colorRes = isSelected ? R.color.incognito_tab_thumbnail_placeholder_selected_color
@@ -278,6 +333,11 @@
     @ColorInt
     public static int getChromeOwnedFaviconTintColor(
             Context context, boolean isIncognito, boolean isTabSelected) {
+        if (!themeRefactorEnabled()) {
+            return ApiCompatibilityUtils.getColor(context.getResources(),
+                    isIncognito ? R.color.default_icon_color_light
+                                : R.color.default_icon_color_baseline);
+        }
         return getTitleTextColor(context, isIncognito, isTabSelected);
     }
 
@@ -292,6 +352,12 @@
      */
     public static ColorStateList getHoveredCardBackgroundTintList(
             Context context, boolean isIncognito, boolean isSelected) {
+        if (!themeRefactorEnabled()) {
+            return AppCompatResources.getColorStateList(context,
+                    isIncognito ? R.color.hovered_tab_grid_card_background_color_incognito
+                                : R.color.hovered_tab_grid_card_background_color);
+        }
+
         if (isIncognito) {
             @ColorRes
             int colorRes = isSelected ? R.color.incognito_tab_group_hovered_bg_selected_color
@@ -329,6 +395,12 @@
      */
     @ColorInt
     public static int getTabGridDialogBackgroundColor(Context context, boolean isIncognito) {
+        if (!themeRefactorEnabled()) {
+            return ContextCompat.getColor(context,
+                    isIncognito ? R.color.tab_grid_dialog_background_color_incognito
+                                : R.color.tab_grid_dialog_background_color);
+        }
+
         if (isIncognito) {
             return ApiCompatibilityUtils.getColor(
                     context.getResources(), R.color.incognito_tab_grid_dialog_background_color);
@@ -340,6 +412,19 @@
     @ColorInt
     private static int getTabGridDialogUngroupBarBackgroundColor(
             Context context, boolean isIncognito, boolean isTabHovered) {
+        if (!themeRefactorEnabled()) {
+            @ColorRes
+            int colorRes;
+            if (isTabHovered) {
+                colorRes = isIncognito ? R.color.tab_grid_card_selected_color_incognito
+                                       : R.color.tab_grid_card_selected_color;
+            } else {
+                colorRes = isIncognito ? R.color.tab_grid_dialog_background_color_incognito
+                                       : R.color.tab_grid_dialog_background_color;
+            }
+            return ApiCompatibilityUtils.getColor(context.getResources(), colorRes);
+        }
+
         if (isIncognito) {
             return ApiCompatibilityUtils.getColor(context.getResources(),
                     isTabHovered ? R.color.incognito_tab_grid_dialog_ungroup_bar_bg_hovered_color
@@ -353,6 +438,18 @@
     @ColorInt
     private static int getTabGridDialogUngroupBarTextColor(
             Context context, boolean isIncognito, boolean isTabHovered) {
+        if (!themeRefactorEnabled()) {
+            @ColorRes
+            int colorRes;
+            if (isTabHovered) {
+                colorRes = R.color.tab_grid_dialog_ungroup_button_text_color_hovered;
+            } else {
+                colorRes = isIncognito ? R.color.tab_grid_dialog_ungroup_button_text_color_incognito
+                                       : R.color.tab_grid_dialog_ungroup_button_text_color;
+            }
+            return ApiCompatibilityUtils.getColor(context.getResources(), colorRes);
+        }
+
         if (isIncognito) {
             return ApiCompatibilityUtils.getColor(context.getResources(),
                     isTabHovered ? R.color.incognito_tab_grid_dialog_ungroup_bar_text_hovered_color
@@ -424,11 +521,17 @@
      */
     @ColorInt
     public static int getTabSelectionToolbarBackground(Context context, boolean isIncognito) {
-        if (isIncognito) {
+        if (!themeRefactorEnabled()) {
             return ApiCompatibilityUtils.getColor(context.getResources(),
-                    R.color.incognito_tab_selection_editor_toolbar_bg_color);
+                    isIncognito ? R.color.default_control_color_active_dark
+                                : R.color.default_control_color_active);
         } else {
-            return MaterialColors.getColor(context, R.attr.colorSurface, TAG);
+            if (isIncognito) {
+                return ApiCompatibilityUtils.getColor(context.getResources(),
+                        R.color.incognito_tab_selection_editor_toolbar_bg_color);
+            } else {
+                return MaterialColors.getColor(context, R.attr.colorSurface, TAG);
+            }
         }
     }
 
@@ -442,6 +545,12 @@
      */
     public static ColorStateList getTabSelectionToolbarIconTintList(
             Context context, boolean isIncognito) {
+        if (!themeRefactorEnabled()) {
+            return AppCompatResources.getColorStateList(context,
+                    isIncognito ? R.color.dark_text_color_list
+                                : R.color.default_text_color_inverse_list);
+        }
+
         return AppCompatResources.getColorStateList(context,
                 isIncognito ? R.color.default_text_color_light_list
                             : R.color.default_text_color_list);
@@ -500,7 +609,9 @@
      * @return The padding space around favicon.
      */
     public static float getTabCardTopFaviconPadding(Context context) {
-        return context.getResources().getDimension(R.dimen.tab_grid_card_favicon_padding);
+        return context.getResources().getDimension(themeRefactorEnabled()
+                        ? R.dimen.tab_grid_card_favicon_padding
+                        : R.dimen.tab_list_card_padding);
     }
 
     /**
@@ -509,7 +620,9 @@
      * @return The padding between tab cards in float number.
      */
     public static float getTabCardPaddingDimension(Context context) {
-        return context.getResources().getDimension(R.dimen.tab_grid_card_between_card_padding);
+        return context.getResources().getDimension(themeRefactorEnabled()
+                        ? R.dimen.tab_grid_card_between_card_padding
+                        : R.dimen.tab_list_card_padding);
     }
 
     /**
@@ -518,7 +631,9 @@
      * @return The padding between between mini thumbnails in float number.
      */
     public static float getTabMiniThumbnailPaddingDimension(Context context) {
-        return context.getResources().getDimension(R.dimen.tab_grid_card_thumbnail_margin);
+        return context.getResources().getDimension(themeRefactorEnabled()
+                        ? R.dimen.tab_grid_card_thumbnail_margin
+                        : R.dimen.tab_list_card_padding);
     }
 
     /**
@@ -529,6 +644,10 @@
      * @return The margin between tab cards in float number.
      */
     public static float getTabGridCardMarginForDialogAnimation(Context context) {
+        if (!themeRefactorEnabled()) {
+            return context.getResources().getDimension(R.dimen.tab_list_card_padding);
+        }
+
         int[] attrs = {R.attr.tabGridMargin};
 
         TypedArray ta = context.obtainStyledAttributes(getThemeOverlayStyleResourceId(), attrs);
@@ -546,7 +665,13 @@
      */
     @StyleRes
     public static int getThemeOverlayStyleResourceId() {
-        return R.style.ThemeRefactorOverlay_Enabled_TabUi;
+        return themeRefactorEnabled() ? R.style.ThemeRefactorOverlay_Enabled_TabUi
+                                      : R.style.ThemeRefactorOverlay_Disabled_TabUi;
+    }
+
+    /** Return if theme refactor is enabled. **/
+    static boolean themeRefactorEnabled() {
+        return CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID);
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java
index 8fb36c6..c356fc63 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java
@@ -23,8 +23,6 @@
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.filters.SmallTest;
 
-import com.google.android.material.color.MaterialColors;
-
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
@@ -50,9 +48,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class TabGridPanelViewBinderTest extends DummyUiActivityTestCase {
-    private static final String TAG = "TGPVBT";
     private static final int CONTENT_TOP_MARGIN = 56;
-
     private PropertyModel mModel;
     private PropertyModelChangeProcessor mMCP;
     private TabGroupUiToolbarView mToolbarView;
@@ -294,9 +290,10 @@
     @SmallTest
     @UiThreadTest
     public void testSetDialogBackgroundColor() {
-        int normalColor = MaterialColors.getColor(getActivity(), R.attr.colorSurface, TAG);
+        int normalColor =
+                ContextCompat.getColor(getActivity(), R.color.tab_grid_dialog_background_color);
         int incognitoColor = ContextCompat.getColor(
-                getActivity(), R.color.incognito_tab_grid_dialog_background_color);
+                getActivity(), R.color.tab_grid_dialog_background_color_incognito);
         // Default setup is in normal mode.
         Assert.assertEquals(normalColor, mTabGridDialogView.getBackgroundColorForTesting());
 
@@ -309,9 +306,10 @@
     @SmallTest
     @UiThreadTest
     public void testSetUngroupbarBackgroundColor() {
-        int normalColor = MaterialColors.getColor(getActivity(), R.attr.colorSurface, TAG);
+        int normalColor =
+                ContextCompat.getColor(getActivity(), R.color.tab_grid_dialog_background_color);
         int incognitoColor = ContextCompat.getColor(
-                getActivity(), R.color.incognito_tab_grid_dialog_background_color);
+                getActivity(), R.color.tab_grid_dialog_background_color_incognito);
         // Default setup is in normal mode.
         Assert.assertEquals(
                 normalColor, mTabGridDialogView.getUngroupBarBackgroundColorForTesting());
@@ -326,27 +324,29 @@
     @SmallTest
     @UiThreadTest
     public void testSetUngroupbarHoveredBackgroundColor() {
-        int normalColor = MaterialColors.getColor(getActivity(), R.attr.colorPrimary, TAG);
-        int incognitoColor = ContextCompat.getColor(
-                getActivity(), R.color.incognito_tab_grid_dialog_ungroup_bar_bg_hovered_color);
+        int normalColorId =
+                ContextCompat.getColor(getActivity(), R.color.tab_grid_card_selected_color);
+        int incognitoColorId = ContextCompat.getColor(
+                getActivity(), R.color.tab_grid_card_selected_color_incognito);
         // Default setup is in normal mode.
         Assert.assertEquals(
-                normalColor, mTabGridDialogView.getUngroupBarHoveredBackgroundColorForTesting());
+                normalColorId, mTabGridDialogView.getUngroupBarHoveredBackgroundColorForTesting());
 
-        mModel.set(
-                TabGridPanelProperties.DIALOG_UNGROUP_BAR_HOVERED_BACKGROUND_COLOR, incognitoColor);
+        mModel.set(TabGridPanelProperties.DIALOG_UNGROUP_BAR_HOVERED_BACKGROUND_COLOR,
+                incognitoColorId);
 
-        Assert.assertEquals(
-                incognitoColor, mTabGridDialogView.getUngroupBarHoveredBackgroundColorForTesting());
+        Assert.assertEquals(incognitoColorId,
+                mTabGridDialogView.getUngroupBarHoveredBackgroundColorForTesting());
     }
 
     @Test
     @SmallTest
     @UiThreadTest
     public void testSetUngroupbarTextColor() {
-        int normalColor = MaterialColors.getColor(getActivity(), R.attr.colorPrimary, TAG);
+        int normalColor = ContextCompat.getColor(
+                getActivity(), R.color.tab_grid_dialog_ungroup_button_text_color);
         int incognitoColor = ContextCompat.getColor(
-                getActivity(), R.color.incognito_tab_grid_dialog_ungroup_bar_text_color);
+                getActivity(), R.color.tab_grid_dialog_ungroup_button_text_color_incognito);
         // Default setup is in normal mode.
         Assert.assertEquals(normalColor, mTabGridDialogView.getUngroupBarTextColorForTesting());
 
@@ -359,9 +359,12 @@
     @SmallTest
     @UiThreadTest
     public void testSetUngroupbarHoveredTextColor() {
-        int normalColor = MaterialColors.getColor(getActivity(), R.attr.colorOnPrimary, TAG);
+        int normalColor = ContextCompat.getColor(
+                getActivity(), R.color.tab_grid_dialog_ungroup_button_text_color_hovered);
+        // Another color just for the sake of testing, as the hovered color does not change before
+        // theme refactor.
         int incognitoColor = ContextCompat.getColor(
-                getActivity(), R.color.incognito_tab_grid_dialog_ungroup_bar_text_hovered_color);
+                getActivity(), R.color.tab_grid_dialog_ungroup_button_text_color_incognito);
         // Default setup is in normal mode.
         Assert.assertEquals(
                 normalColor, mTabGridDialogView.getUngroupBarHoveredTextColorForTesting());
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 fddb9c1..18d22a2 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
@@ -11,6 +11,7 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -301,9 +302,9 @@
 
     private void testGridSelected(ViewGroup holder, PropertyModel model) {
         model.set(TabProperties.IS_SELECTED, true);
-        Assert.assertTrue(TabSelectionEditorTestingRobot.isTabViewSelected(holder));
+        Assert.assertNotNull(holder.getForeground());
         model.set(TabProperties.IS_SELECTED, false);
-        Assert.assertFalse(TabSelectionEditorTestingRobot.isTabViewSelected(holder));
+        Assert.assertNull(holder.getForeground());
     }
 
     private void testSelectableTabClickToSelect(
@@ -374,7 +375,8 @@
                 () -> !((ClosableTabGridView) mTabGridView).getIsAnimatingForTesting());
 
         Assert.assertEquals(View.GONE, backgroundView.getVisibility());
-        Assert.assertTrue(TabSelectionEditorTestingRobot.isTabViewSelected(mTabGridView));
+        Drawable selectedDrawable = mTabGridView.getForeground();
+        Assert.assertNotNull(selectedDrawable);
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mGridModel.set(TabProperties.IS_SELECTED, false);
@@ -384,7 +386,9 @@
         CriteriaHelper.pollUiThread(
                 () -> !((ClosableTabGridView) mTabGridView).getIsAnimatingForTesting());
         Assert.assertEquals(View.GONE, backgroundView.getVisibility());
-        Assert.assertFalse(TabSelectionEditorTestingRobot.isTabViewSelected(mTabGridView));
+
+        selectedDrawable = mTabGridView.getForeground();
+        Assert.assertNull(selectedDrawable);
     }
 
     @Test
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
index d87f6c99..e7b885f 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
@@ -28,10 +28,7 @@
 import static org.chromium.chrome.browser.tasks.tab_management.RecyclerViewMatcherUtils.withItemType;
 
 import android.view.View;
-import android.view.ViewGroup;
 
-import androidx.annotation.ColorInt;
-import androidx.core.view.ViewCompat;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.espresso.NoMatchingRootException;
 import androidx.test.espresso.NoMatchingViewException;
@@ -69,7 +66,7 @@
                 mSelectableTabGridView = selectableTabGridView;
 
                 return mSelectableTabGridView.isChecked() && actionButtonSelected()
-                        && isTabViewSelected(mSelectableTabGridView);
+                        && mSelectableTabGridView.getForeground() != null;
             }
 
             @Override
@@ -89,43 +86,6 @@
     }
 
     /**
-     * Infers whether the tab is currently selected, by making assumptions about what the view state
-     * should look like. This method is fairly fragile to changes in implementation.
-     * @param holder The root of the tab {@link View} objects.
-     * @return Whether the tab is currently selected.
-     */
-    public static boolean isTabViewSelected(ViewGroup holder) {
-        // Tab list was not migrated to use new color scheme/logic. Instead having a foreground
-        // Drawable means it is selected.
-        if (holder.getId() == org.chromium.chrome.tab_ui.R.id.selectable_tab_list_card_item) {
-            return holder.getForeground() != null;
-        }
-
-        View cardView = holder.findViewById(org.chromium.chrome.tab_ui.R.id.card_view);
-        final @ColorInt int actualColor =
-                ViewCompat.getBackgroundTintList(cardView).getDefaultColor();
-
-        final @ColorInt int incogSelected = TabUiThemeProvider.getCardViewBackgroundColor(
-                holder.getContext(), /*isIncognito*/ true, /*isSelected*/ true);
-        final @ColorInt int normalSelected = TabUiThemeProvider.getCardViewBackgroundColor(
-                holder.getContext(), /*isIncognito*/ false, /*isSelected*/ true);
-        final @ColorInt int incogNotSelected = TabUiThemeProvider.getCardViewBackgroundColor(
-                holder.getContext(), /*isIncognito*/ true, /*isSelected*/ false);
-        final @ColorInt int normalNotSelected = TabUiThemeProvider.getCardViewBackgroundColor(
-                holder.getContext(), /*isIncognito*/ false, /*isSelected*/ false);
-
-        // This approach only works when there is no overlap between selected and unselected colors.
-        // If this assertion stops holding true, we could try requiring incognito information to be
-        // passed into this method.
-        Assert.assertNotEquals(incogSelected, incogNotSelected);
-        Assert.assertNotEquals(incogSelected, normalNotSelected);
-        Assert.assertNotEquals(normalSelected, incogNotSelected);
-        Assert.assertNotEquals(normalSelected, normalNotSelected);
-
-        return actualColor == incogSelected || actualColor == normalSelected;
-    }
-
-    /**
      * @return A view matcher that matches a divider view.
      */
     public static Matcher<View> isDivider() {
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index 2fd67e6..d1c28f55 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -28,12 +28,6 @@
 import android.view.View;
 import android.widget.EditText;
 
-import androidx.annotation.AttrRes;
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-
-import com.google.android.material.color.MaterialColors;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -44,8 +38,6 @@
 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.Callback;
 import org.chromium.base.ContextUtils;
@@ -85,43 +77,12 @@
  */
 @SuppressWarnings({"ArraysAsListWithZeroOrOneArgument", "ResultOfMethodCallIgnored"})
 @RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE,
-        shadows = {TabGridDialogMediatorUnitTest.ShadowMaterialColors.class})
+@Config(manifest = Config.NONE)
 // clang-format off
 @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
 @Features.DisableFeatures(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID)
-// clang-format on
 public class TabGridDialogMediatorUnitTest {
-    // Cannot easily mock Theme because it is a final class. Instead shadow MaterialColors. The
-    // actual color value doesn't matter, just need to not NPE with Context/Theme/TypedValue object
-    // interactions.
-    @Implements(MaterialColors.class)
-    static class ShadowMaterialColors {
-        @Implementation
-        @ColorInt
-        public static int getColor(@NonNull View view, @AttrRes int colorAttributeResId) {
-            return 0;
-        }
-
-        @ColorInt
-        public static int getColor(
-                Context context, @AttrRes int colorAttributeResId, String errorMessageComponent) {
-            return 0;
-        }
-
-        @ColorInt
-        public static int getColor(
-                @NonNull View view, @AttrRes int colorAttributeResId, @ColorInt int defaultValue) {
-            return 0;
-        }
-
-        @ColorInt
-        public static int getColor(@NonNull Context context, @AttrRes int colorAttributeResId,
-                @ColorInt int defaultValue) {
-            return 0;
-        }
-    }
-
+    // clang-format on
     @Rule
     public TestRule mProcessor = new Features.JUnitProcessor();
 
@@ -184,6 +145,7 @@
 
     @Before
     public void setUp() {
+
         MockitoAnnotations.initMocks(this);
 
         mTab1 = prepareTab(TAB1_ID, TAB1_TITLE);
diff --git a/chrome/android/java/res/drawable-hdpi/toolbar_shadow_focused.png b/chrome/android/java/res/drawable-hdpi/toolbar_shadow_focused.png
new file mode 100644
index 0000000..e380331e
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/toolbar_shadow_focused.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/toolbar_shadow_normal.png b/chrome/android/java/res/drawable-hdpi/toolbar_shadow_normal.png
new file mode 100644
index 0000000..83afe5e
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/toolbar_shadow_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/toolbar_shadow_focused.png b/chrome/android/java/res/drawable-mdpi/toolbar_shadow_focused.png
new file mode 100644
index 0000000..f6160071
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/toolbar_shadow_focused.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/toolbar_shadow_normal.png b/chrome/android/java/res/drawable-mdpi/toolbar_shadow_normal.png
new file mode 100644
index 0000000..a39d3a8
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/toolbar_shadow_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-sw600dp/toolbar_shadow.xml b/chrome/android/java/res/drawable-sw600dp/toolbar_shadow.xml
new file mode 100644
index 0000000..d4108dfb
--- /dev/null
+++ b/chrome/android/java/res/drawable-sw600dp/toolbar_shadow.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2015 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. -->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/toolbar_shadow_normal"
+    android:gravity="top|fill_horizontal" />
diff --git a/chrome/android/java/res/drawable-xhdpi/toolbar_shadow_focused.png b/chrome/android/java/res/drawable-xhdpi/toolbar_shadow_focused.png
new file mode 100644
index 0000000..ace8517
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/toolbar_shadow_focused.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/toolbar_shadow_normal.png b/chrome/android/java/res/drawable-xhdpi/toolbar_shadow_normal.png
new file mode 100644
index 0000000..02e03cf
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/toolbar_shadow_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/toolbar_shadow_focused.png b/chrome/android/java/res/drawable-xxhdpi/toolbar_shadow_focused.png
new file mode 100644
index 0000000..da197d31
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/toolbar_shadow_focused.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/toolbar_shadow_normal.png b/chrome/android/java/res/drawable-xxhdpi/toolbar_shadow_normal.png
new file mode 100644
index 0000000..af20aca0
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/toolbar_shadow_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/toolbar_shadow_focused.png b/chrome/android/java/res/drawable-xxxhdpi/toolbar_shadow_focused.png
new file mode 100644
index 0000000..410b0516
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/toolbar_shadow_focused.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/toolbar_shadow_normal.png b/chrome/android/java/res/drawable-xxxhdpi/toolbar_shadow_normal.png
new file mode 100644
index 0000000..95f647a2
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/toolbar_shadow_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/safety_check.xml b/chrome/android/java/res/drawable/safety_check.xml
new file mode 100644
index 0000000..b9e3717
--- /dev/null
+++ b/chrome/android/java/res/drawable/safety_check.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--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.-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="20dp"
+        android:height="20dp"
+        android:viewportWidth="20.0"
+        android:viewportHeight="20.0">
+    <path android:fillColor="@macro/default_icon_color"
+          android:pathData="M10 1l8 3.273v4.909c0 4.54-3.413 8.787-8 9.818-4.587-1.03-8-5.277-8-9.818v-4.91L10 1zm3.57 5.384l-5.126 5.391-2.014-2.11-1.097 1.153 3.111 3.273 6.223-6.546-1.097-1.161z"/>
+</vector>
diff --git a/chrome/android/java/res/drawable/toolbar_shadow.xml b/chrome/android/java/res/drawable/toolbar_shadow.xml
new file mode 100644
index 0000000..fefb304
--- /dev/null
+++ b/chrome/android/java/res/drawable/toolbar_shadow.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2015 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. -->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <bitmap
+            android:src="@drawable/toolbar_shadow_normal"
+            android:gravity="top|fill_horizontal" />
+    </item>
+    <item>
+        <bitmap
+            android:src="@drawable/toolbar_shadow_focused"
+            android:gravity="top|fill_horizontal" />
+    </item>
+</transition>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 04ff65e..1da1584 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1628,12 +1628,18 @@
 
     @Override
     protected int getToolbarShadowResource() {
-        return R.drawable.toolbar_hairline;
+        final boolean themeRefactorEnabled =
+                CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID);
+        return themeRefactorEnabled ? R.drawable.toolbar_hairline
+                                    : R.drawable.modern_toolbar_shadow;
     }
 
     @Override
     protected int getToolbarShadowLayoutHeight() {
-        return getResources().getDimensionPixelSize(R.dimen.toolbar_hairline_height);
+        final int res = CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID)
+                ? R.dimen.toolbar_hairline_height
+                : R.dimen.toolbar_shadow_height;
+        return getResources().getDimensionPixelSize(res);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
index bf633652..7f0624fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -107,6 +107,7 @@
                 add(ChromeFeatureList.TAB_GROUPS_ANDROID);
                 add(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID);
                 add(ChromeFeatureList.TAB_TO_GTS_ANIMATION);
+                add(ChromeFeatureList.THEME_REFACTOR_ANDROID);
                 add(ChromeFeatureList.TOOLBAR_USE_HARDWARE_BITMAP_DRAW);
                 add(ChromeFeatureList.USE_CHIME_ANDROID_SDK);
                 add(ChromeFeatureList.WEB_APK_TRAMPOLINE_ON_INITIAL_INTENT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java
index 8ecbdc5..8e21e62 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java
@@ -10,6 +10,8 @@
 import androidx.annotation.Nullable;
 import androidx.core.content.res.ResourcesCompat;
 
+import com.google.common.primitives.UnsignedLongs;
+
 import org.chromium.base.CallbackController;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
@@ -89,8 +91,10 @@
         });
 
         if (meta != null) {
+            // Use UnsignedLongs to convert ProductClusterId to avoid overflow.
             mSubscription = new CommerceSubscription(CommerceSubscriptionType.PRICE_TRACK,
-                    Long.toString(mPowerBookmarkMeta.getShoppingSpecifics().getProductClusterId()),
+                    UnsignedLongs.toString(
+                            mPowerBookmarkMeta.getShoppingSpecifics().getProductClusterId()),
                     SubscriptionManagementType.USER_MANAGED, TrackingIdType.PRODUCT_CLUSTER_ID);
         }
         bindBookmarkProperties(mBookmarkId, mPowerBookmarkMeta, mFromExplicitTrackUi);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
index bc322ba..3c432b1b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java
@@ -14,6 +14,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.google.common.primitives.UnsignedLongs;
+
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
 import org.chromium.chrome.R;
@@ -75,8 +77,9 @@
         PowerBookmarkMeta meta = mBookmarkModel.getPowerBookmarkMeta(bookmarkId);
         // TODO(crbug.com/1243383): Pull price updates once they're available.
         ProductPrice currentPrice = meta.getShoppingSpecifics().getCurrentPrice();
+        // Use UnsignedLongs to convert ProductClusterId to avoid overflow.
         mSubscription = new CommerceSubscription(CommerceSubscriptionType.PRICE_TRACK,
-                Long.toString(meta.getShoppingSpecifics().getProductClusterId()),
+                UnsignedLongs.toString(meta.getShoppingSpecifics().getProductClusterId()),
                 SubscriptionManagementType.USER_MANAGED, TrackingIdType.PRODUCT_CLUSTER_ID);
 
         mCurrencyFormatter =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
index 6b6d83c9..807987c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
@@ -43,6 +43,8 @@
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
 import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
 import org.chromium.chrome.browser.flags.ActivityType;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.metrics.UmaSessionStats;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.night_mode.PowerSavingModeMonitor;
@@ -393,7 +395,9 @@
 
     @Override
     protected int getToolbarShadowResource() {
-        return R.drawable.toolbar_hairline;
+        final boolean themeRefactorEnabled =
+                CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID);
+        return themeRefactorEnabled ? R.drawable.toolbar_hairline : R.drawable.toolbar_shadow;
     }
 
     @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
index c1a7fe6..1fe64b4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -1163,7 +1163,6 @@
         new TwoStatePermissionTestCase("AutoDarkWebContent",
                 SiteSettingsCategory.Type.AUTO_DARK_WEB_CONTENT,
                 ContentSettingsType.AUTO_DARK_WEB_CONTENT, true)
-                .withExpectedPrefKeys(SingleCategorySettings.ADD_EXCEPTION_KEY)
                 .run();
 
         Assert.assertTrue("Auto dark should be enabled.", observer.mDefaultValue);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
index cb59221c..ce5e797 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
@@ -60,7 +60,8 @@
             UMAEvent.WWW_MISMATCH_URL_AVAILABLE, UMAEvent.WWW_MISMATCH_URL_NOT_AVAILABLE,
             UMAEvent.SHOW_BAD_CLOCK, UMAEvent.CAPTIVE_PORTAL_CERT_FOUND,
             UMAEvent.WWW_MISMATCH_FOUND_IN_SAN, UMAEvent.SHOW_MITM_SOFTWARE_INTERSTITIAL,
-            UMAEvent.OS_REPORTS_CAPTIVE_PORTAL})
+            UMAEvent.OS_REPORTS_CAPTIVE_PORTAL, UMAEvent.SHOW_BLOCKED_INTERCEPTION_INTERSTITIAL,
+            UMAEvent.SHOW_LEGACY_TLS_INTERSTITIAL})
     @Retention(RetentionPolicy.SOURCE)
     private @interface UMAEvent {
         int HANDLE_ALL = 0;
@@ -76,6 +77,8 @@
         int WWW_MISMATCH_FOUND_IN_SAN = 10;
         int SHOW_MITM_SOFTWARE_INTERSTITIAL = 11;
         int OS_REPORTS_CAPTIVE_PORTAL = 12;
+        int SHOW_BLOCKED_INTERCEPTION_INTERSTITIAL = 13;
+        int SHOW_LEGACY_TLS_INTERSTITIAL = 14; // Deprecated in M98.
     }
 
     @Rule
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 7e805bb..22fceed 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -190,14 +190,6 @@
     Offer new features as they become available
   </message>
 
-  <!-- Android Messages notification strings. -->
-  <message name="IDS_ANDROID_MESSAGES_PAIRING_LOST_NOTIFICATION_TITLE" desc="Title of the notification which alerts the user that they can set up their phones to sync text messages with their Chromebook.">
-    Pair your phone with Messages
-  </message>
-  <message name="IDS_ANDROID_MESSAGES_PAIRING_LOST_NOTIFICATION_MESSAGE" desc="Message for the body of the notification which alerts the user that they can set up their phones to sync text messages with their Chromebook.">
-    Send and receive text messages from your Chromebook
-  </message>
-
   <!-- Update Screen Strings -->
   <message name="IDS_CHECKING_FOR_UPDATES" desc="Notification for checking for update">
     Checking for updates
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 47a027e..b2c25d8 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5040,6 +5040,12 @@
       <message name="IDS_EXTENSIONS_MENU_CANT_ACCESS_SITE_DATA" desc="Longer explanation for section of extensions that can't access the current site's data">
         These extensions don't need to see and change information on this site.
       </message>
+      <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_TAB_TITLE" desc="Title of the site access tab in the Extensions Menu">
+        Permissions
+      </message>
+      <message name="IDS_EXTENSIONS_MENU_EXTENSIONS_TAB_TITLE" desc="Title of the installed extensions tab in the Extensions Menu">
+        Installed
+      </message>
 
       <!-- Settings API bubble -->
       <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE" desc="Title of a bubble warning users that an extension has overridden their home page setting">
@@ -11799,6 +11805,17 @@
       No thanks
     </message>
 
+    <!-- Tailored security Android message for consented primary accounts -->
+    <message name="IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_TITLE" desc="Title shown in the Android message when the account tailored security setting changes for a consented primary account">
+      Enhanced Safe Browsing is on
+    </message>
+    <message name="IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_DESCRIPTION" desc="Description shown in the Android message when the account tailored security setting changes for a consented primary account">
+      You&#x2019;re on Chrome&#x2019;s strongest security
+    </message>
+    <message name="IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_OK_BUTTON" desc="The text on the ok button in the Android message when the account tailored security setting changes for a consented primary account">
+      OK
+    </message>
+
     <!-- Enterprise file system connector service providers' display names -->
     <message name="IDS_FILE_SYSTEM_CONNECTOR_BOX" meaning="box.com" desc="Display name for Box.">
       Box
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_EXTENSIONS_TAB_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_EXTENSIONS_TAB_TITLE.png.sha1
new file mode 100644
index 0000000..4b0f7a39
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_EXTENSIONS_TAB_TITLE.png.sha1
@@ -0,0 +1 @@
+8a1009422dd1ee48f17f72f12b40cc275bf1a9ad
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_TAB_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_TAB_TITLE.png.sha1
new file mode 100644
index 0000000..422a7fd
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_TAB_TITLE.png.sha1
@@ -0,0 +1 @@
+52717e58e96293c4bce6d7a26090a1c1300068a0
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..6ad8cbf
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+90f4324744dfbfcc4af24d269c5d75fcdf2d3804
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_OK_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_OK_BUTTON.png.sha1
new file mode 100644
index 0000000..6ad8cbf
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_OK_BUTTON.png.sha1
@@ -0,0 +1 @@
+90f4324744dfbfcc4af24d269c5d75fcdf2d3804
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_TITLE.png.sha1
new file mode 100644
index 0000000..6ad8cbf
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_TITLE.png.sha1
@@ -0,0 +1 @@
+90f4324744dfbfcc4af24d269c5d75fcdf2d3804
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d3c7fc6..d557921 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4874,6 +4874,7 @@
       "//ash/components/account_manager",
       "//ash/components/arc:arc_base",
       "//ash/components/arc:arc_base_utils",
+      "//ash/components/arc/enterprise",
       "//ash/components/geolocation",
       "//ash/components/settings",
       "//ash/public/cpp",
@@ -4937,7 +4938,6 @@
       "//components/account_manager_core",
       "//components/app_restore",
       "//components/arc",
-      "//components/arc/enterprise",
       "//components/arc/mojom",
       "//components/desks_storage",
       "//components/metrics/structured:neutrino_logging",
@@ -7489,8 +7489,6 @@
     "ssl/ssl_browsertest_util.h",
     "ssl/ssl_client_auth_requestor_mock.cc",
     "ssl/ssl_client_auth_requestor_mock.h",
-    "ssl/tls_deprecation_test_utils.cc",
-    "ssl/tls_deprecation_test_utils.h",
     "translate/translate_test_utils.cc",
     "translate/translate_test_utils.h",
   ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 19f8a14..e8febf8 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2232,100 +2232,6 @@
      base::size(kBackForwardCache_ForceCaching), nullptr},
 };
 
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalFailure2250[] = {
-        {"lcp-limit-in-ms", "2250"},
-        {"intervention-mode", "failure"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalFailure2000[] = {
-        {"lcp-limit-in-ms", "2000"},
-        {"intervention-mode", "failure"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1750[] = {
-        {"lcp-limit-in-ms", "1750"},
-        {"intervention-mode", "failure"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1500[] = {
-        {"lcp-limit-in-ms", "1500"},
-        {"intervention-mode", "failure"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1250[] = {
-        {"lcp-limit-in-ms", "1250"},
-        {"intervention-mode", "failure"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1000[] = {
-        {"lcp-limit-in-ms", "1000"},
-        {"intervention-mode", "failure"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalSwap2250[] = {
-        {"lcp-limit-in-ms", "2250"},
-        {"intervention-mode", "swap"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalSwap2000[] = {
-        {"lcp-limit-in-ms", "2000"},
-        {"intervention-mode", "swap"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1750[] = {
-        {"lcp-limit-in-ms", "1750"},
-        {"intervention-mode", "swap"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1500[] = {
-        {"lcp-limit-in-ms", "1500"},
-        {"intervention-mode", "swap"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1250[] = {
-        {"lcp-limit-in-ms", "1250"},
-        {"intervention-mode", "swap"}};
-const FeatureEntry::FeatureParam
-    kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1000[] = {
-        {"lcp-limit-in-ms", "1000"},
-        {"intervention-mode", "swap"}};
-const FeatureEntry::FeatureVariation
-    kAlignFontDisplayAutoTimeoutWithLCPGoalVariations[] = {
-        {"switch to failure after 2250ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalFailure2250,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalFailure2250),
-         nullptr},
-        {"switch to failure after 2000ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalFailure2000,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalFailure2000),
-         nullptr},
-        {"switch to failure after 1750ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1750,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1750),
-         nullptr},
-        {"switch to failure after 1500ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1500,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1500),
-         nullptr},
-        {"switch to failure after 1250ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1250,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1250),
-         nullptr},
-        {"switch to failure after 1000ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1000,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalFailure1000),
-         nullptr},
-        {"switch to swap after 2250ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalSwap2250,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalSwap2250), nullptr},
-        {"switch to swap after 2000ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalSwap2000,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalSwap2000), nullptr},
-        {"switch to swap after 1750ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1750,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1750), nullptr},
-        {"switch to swap after 1500ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1500,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1500), nullptr},
-        {"switch to swap after 1250ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1250,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1250), nullptr},
-        {"switch to swap after 1000ms since navigation",
-         kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1000,
-         base::size(kAlignFontDisplayAutoTimeoutWithLCPGoalSwap1000), nullptr},
-};
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 const FeatureEntry::Choice kEnableCrOSActionRecorderChoices[] = {
     {flags_ui::kGenericExperimentChoiceDefault, "", ""},
@@ -2603,7 +2509,6 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 constexpr char kPersonalizationHubInternalName[] = "personalization-hub";
-constexpr char kWallpaperWebUIInternalName[] = "wallpaper-webui";
 constexpr char kWallpaperFullScreenPreviewInternalName[] =
     "wallpaper-fullscreen-preview";
 constexpr char kWallpaperPerDeskName[] = "per-desk-wallpaper";
@@ -3984,6 +3889,9 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kToolbarMicIphAndroid,
                                     kIphMicToolbarVariations,
                                     "ToolbarMicIphAndroid")},
+    {"theme-refactor-android", flag_descriptions::kThemeRefactorAndroidName,
+     flag_descriptions::kThemeRefactorAndroidDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kThemeRefactorAndroid)},
 #endif  // OS_ANDROID
     {"disallow-doc-written-script-loads",
      flag_descriptions::kDisallowDocWrittenScriptsUiName,
@@ -4941,6 +4849,11 @@
      flag_descriptions::kSidePanelDragAndDropDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kSidePanelDragAndDrop)},
 
+    {flag_descriptions::kUnifiedSidePanelFlagId,
+     flag_descriptions::kUnifiedSidePanelName,
+     flag_descriptions::kUnifiedSidePanelDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kUnifiedSidePanel)},
+
     {"tab-outlines-in-low-contrast-themes",
      flag_descriptions::kTabOutlinesInLowContrastThemesName,
      flag_descriptions::kTabOutlinesInLowContrastThemesDescription, kOsDesktop,
@@ -5430,6 +5343,11 @@
      flag_descriptions::kReduceHorizontalFlingVelocityDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kReduceHorizontalFlingVelocity)},
 
+    {"enable-css-selector-fragment-anchor",
+     flag_descriptions::kEnableCssSelectorFragmentAnchorName,
+     flag_descriptions::kEnableCssSelectorFragmentAnchorDescription, kOsAll,
+     FEATURE_VALUE_TYPE(blink::features::kCssSelectorFragmentAnchor)},
+
     {"enable-resampling-input-events",
      flag_descriptions::kEnableResamplingInputEventsName,
      flag_descriptions::kEnableResamplingInputEventsDescription, kOsAll,
@@ -6560,15 +6478,6 @@
      FEATURE_VALUE_TYPE(features::kNearbySharingBackgroundScanning)},
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-    {"align-font-display-auto-lcp",
-     flag_descriptions::kAlignFontDisplayAutoTimeoutWithLCPGoalName,
-     flag_descriptions::kAlignFontDisplayAutoTimeoutWithLCPGoalDescription,
-     kOsAll,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(
-         blink::features::kAlignFontDisplayAutoTimeoutWithLCPGoal,
-         kAlignFontDisplayAutoTimeoutWithLCPGoalVariations,
-         "AlignFontDisplayAutoTimeoutWithLCPGoal")},
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     {"enable-palm-suppression", flag_descriptions::kEnablePalmSuppressionName,
      flag_descriptions::kEnablePalmSuppressionDescription, kOsCrOS,
@@ -7088,9 +6997,6 @@
      flag_descriptions::kPersonalizationHubName,
      flag_descriptions::kPersonalizationHubDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kPersonalizationHub)},
-    {kWallpaperWebUIInternalName, flag_descriptions::kWallpaperWebUIName,
-     flag_descriptions::kWallpaperWebUIDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kWallpaperWebUI)},
     {kWallpaperFullScreenPreviewInternalName,
      flag_descriptions::kWallpaperFullScreenPreviewName,
      flag_descriptions::kWallpaperFullScreenPreviewDescription, kOsCrOS,
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index d05f8ff..8166739 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -54,6 +54,7 @@
 DECLARE_RESOURCE_ID(IDR_ANDORID_MESSAGE_PERMISSION_CAMERA,
                     R.drawable.ic_photo_camera_black)
 DECLARE_RESOURCE_ID(IDR_ANDROID_MESSAGE_SETTINGS, R.drawable.settings_cog)
+DECLARE_RESOURCE_ID(IDR_ANDROID_MESSAGE_SAFETY_CHECK, R.drawable.safety_check)
 
 // Autofill popup and keyboard accessory images.
 // We use Android's |VectorDrawableCompat| for the following images that are
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 6739b25..e3fbf38 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -85,6 +85,7 @@
 #include "chrome/browser/ui/profile_picker.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_shortcut_mac.h"
@@ -2062,10 +2063,11 @@
   // best to bottleneck the openings through that for uniform handling.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   chrome::startup::IsFirstRun first_run =
-      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                    : chrome::startup::IS_NOT_FIRST_RUN;
+      first_run::IsChromeFirstRun() ? chrome::startup::IsFirstRun::kYes
+                                    : chrome::startup::IsFirstRun::kNo;
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run);
-  launch.OpenURLsInBrowser(browser, false, urls);
+  launch.OpenURLsInBrowser(browser, chrome::startup::IsProcessStartup::kNo,
+                           urls);
 
   // This NTP check should be replaced once https://crbug.com/624410 is fixed.
   if (startupIndex != TabStripModel::kNoTab &&
diff --git a/chrome/browser/apps/app_service/instance_registry_updater.cc b/chrome/browser/apps/app_service/instance_registry_updater.cc
index cac403d..c4a37a0 100644
--- a/chrome/browser/apps/app_service/instance_registry_updater.cc
+++ b/chrome/browser/apps/app_service/instance_registry_updater.cc
@@ -107,10 +107,7 @@
     InstanceState state) {
   auto instance = std::make_unique<apps::Instance>(app_id, instance_id, window);
   instance->UpdateState(state, base::Time::Now());
-
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
-  deltas.push_back(std::move(instance));
-  instance_registry_.OnInstances(std::move(deltas));
+  instance_registry_.OnInstance(std::move(instance));
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
index 36bd99be..daff0cc 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
@@ -371,27 +371,21 @@
         app_id, apps::Instance::InstanceKey::ForWindowBasedApp(window));
     instance->UpdateState(state, base::Time::Now());
 
-    std::vector<std::unique_ptr<apps::Instance>> deltas;
-    deltas.push_back(std::move(instance));
-
     apps::AppServiceProxyFactory::GetForProfile(testing_profile_.get())
         ->InstanceRegistry()
-        .OnInstances(std::move(deltas));
+        .OnInstance(std::move(instance));
   }
 
   void ModifyWebAppInstance(const std::string& app_id,
                             aura::Window* window,
                             apps::InstanceState state) {
     std::unique_ptr<apps::Instance> instance = std::make_unique<apps::Instance>(
-        app_id, apps::Instance::InstanceKey::ForWebBasedApp(window));
+        app_id, apps::Instance::InstanceKey(window));
     instance->UpdateState(state, base::Time::Now());
 
-    std::vector<std::unique_ptr<apps::Instance>> deltas;
-    deltas.push_back(std::move(instance));
-
     apps::AppServiceProxyFactory::GetForProfile(testing_profile_.get())
         ->InstanceRegistry()
-        .OnInstances(std::move(deltas));
+        .OnInstance(std::move(instance));
   }
 
   std::unique_ptr<Browser> CreateBrowserWithAuraWindow1() {
diff --git a/chrome/browser/apps/app_service/notifications_browsertest.cc b/chrome/browser/apps/app_service/notifications_browsertest.cc
index 19562e4..6d38e56b 100644
--- a/chrome/browser/apps/app_service/notifications_browsertest.cc
+++ b/chrome/browser/apps/app_service/notifications_browsertest.cc
@@ -4,6 +4,9 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
@@ -39,9 +42,6 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc
index d08b8cb..039a76b 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -10,6 +10,8 @@
 #include "ash/components/arc/arc_util.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/app_menu_constants.h"
 #include "base/bind.h"
@@ -49,8 +51,6 @@
 #include "components/arc/mojom/compatibility_mode.mojom.h"
 #include "components/arc/mojom/file_system.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
index ed6e9fa..7436f16 100644
--- a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
+++ b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/app_list/app_list_metrics.h"
 #include "ash/public/cpp/app_menu_constants.h"
@@ -59,7 +60,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/full_restore_utils.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/services/app_service/public/cpp/instance.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
@@ -815,15 +815,13 @@
     DCHECK(base::Contains(app_window_to_aura_window_, app_window));
     window = app_window_to_aura_window_[app_window];
   }
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
   auto instance = std::make_unique<apps::Instance>(
       app_window->extension_id(),
       apps::Instance::InstanceKey::ForWindowBasedApp(window));
   instance->SetLaunchId(GetLaunchId(app_window));
   instance->UpdateState(new_state, base::Time::Now());
   instance->SetBrowserContext(app_window->browser_context());
-  deltas.push_back(std::move(instance));
-  instance_registry_->OnInstances(std::move(deltas));
+  instance_registry_->OnInstance(std::move(instance));
 }
 
 content::WebContents* ExtensionAppsChromeOs::LaunchImpl(
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc b/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
index 6172a69..dc8e05b0 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
@@ -6,6 +6,8 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -14,8 +16,6 @@
 #include "chrome/browser/apps/app_service/webapk/webapk_install_task.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/arc/mojom/webapk.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace apps {
 
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_queue.h b/chrome/browser/apps/app_service/webapk/webapk_install_queue.h
index 77d7eb5..d49e28a 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_queue.h
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_queue.h
@@ -8,10 +8,10 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/containers/circular_deque.h"
 #include "base/memory/weak_ptr.h"
 #include "components/arc/mojom/webapk.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 
 class Profile;
 
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_task.cc b/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
index 55b5bf3..45836a1 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
@@ -7,6 +7,8 @@
 #include <algorithm>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/location.h"
@@ -25,8 +27,6 @@
 #include "chrome/browser/web_applications/web_application_info.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/arc/mojom/webapk.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/services/app_service/public/cpp/share_target.h"
 #include "components/version_info/version_info.h"
 #include "components/webapk/webapk.pb.h"
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc b/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc
index a2c7f9f..f4018be0 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc
@@ -6,6 +6,8 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_webapk_instance.h"
 #include "ash/constants/ash_features.h"
 #include "base/bind.h"
@@ -23,8 +25,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/mojom/webapk.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/webapk/webapk.pb.h"
 #include "content/public/test/browser_task_environment.h"
 #include "net/test/embedded_test_server/default_handlers.h"
diff --git a/chrome/browser/apps/app_service/webapk/webapk_manager.cc b/chrome/browser/apps/app_service/webapk/webapk_manager.cc
index 30ffef5..2266af9 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_manager.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_manager.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/apps/app_service/webapk/webapk_manager.h"
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/bind.h"
 #include "base/check.h"
 #include "base/containers/flat_set.h"
@@ -20,7 +21,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
diff --git a/chrome/browser/apps/app_service/webapk/webapk_policy_browsertest.cc b/chrome/browser/apps/app_service/webapk/webapk_policy_browsertest.cc
index 8e1af00a..2a9eb43 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_policy_browsertest.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_policy_browsertest.cc
@@ -5,6 +5,8 @@
 #include <memory>
 
 #include "ash/components/arc/arc_features_parser.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_webapk_instance.h"
 #include "ash/constants/ash_features.h"
@@ -19,8 +21,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/apps/intent_helper/metrics/intent_handling_metrics_unittest.cc b/chrome/browser/apps/intent_helper/metrics/intent_handling_metrics_unittest.cc
index cc618282..be691661 100644
--- a/chrome/browser/apps/intent_helper/metrics/intent_handling_metrics_unittest.cc
+++ b/chrome/browser/apps/intent_helper/metrics/intent_handling_metrics_unittest.cc
@@ -16,9 +16,9 @@
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
 #include "ash/components/arc/metrics/stability_metrics_manager.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_service_manager.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 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 0525bc5..415eba0 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
@@ -4,6 +4,8 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
@@ -16,8 +18,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_test.h"
 #include "extensions/common/switches.h"
 #include "extensions/test/extension_test_message_listener.h"
diff --git a/chrome/browser/ash/android_sms/android_sms_service.cc b/chrome/browser/ash/android_sms/android_sms_service.cc
index a62cf1f..692c9871 100644
--- a/chrome/browser/ash/android_sms/android_sms_service.cc
+++ b/chrome/browser/ash/android_sms/android_sms_service.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/ash/android_sms/android_sms_urls.h"
 #include "chrome/browser/ash/android_sms/connection_manager.h"
 #include "chrome/browser/ash/android_sms/fcm_connection_establisher.h"
-#include "chrome/browser/ash/android_sms/pairing_lost_notifier.h"
 #include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -42,12 +41,7 @@
       android_sms_pairing_state_tracker_(
           std::make_unique<AndroidSmsPairingStateTrackerImpl>(
               profile_,
-              android_sms_app_manager_.get())),
-      pairing_lost_notifier_(std::make_unique<PairingLostNotifier>(
-          profile,
-          multidevice_setup_client,
-          profile_->GetPrefs(),
-          android_sms_app_manager_.get())) {
+              android_sms_app_manager_.get())) {
   session_manager::SessionManager::Get()->AddObserver(this);
 }
 
@@ -55,9 +49,6 @@
 
 void AndroidSmsService::Shutdown() {
   connection_manager_.reset();
-  // Note: |pairing_lost_notifier_| holds a reference to
-  // |android_sms_app_manager_|, so it should be deleted first.
-  pairing_lost_notifier_.reset();
   android_sms_pairing_state_tracker_.reset();
   android_sms_app_manager_.reset();
   session_manager::SessionManager::Get()->RemoveObserver(this);
diff --git a/chrome/browser/ash/android_sms/android_sms_service.h b/chrome/browser/ash/android_sms/android_sms_service.h
index 56bbda33..67a116e 100644
--- a/chrome/browser/ash/android_sms/android_sms_service.h
+++ b/chrome/browser/ash/android_sms/android_sms_service.h
@@ -32,7 +32,6 @@
 class AndroidSmsAppManager;
 class AndroidSmsAppSetupController;
 class ConnectionManager;
-class PairingLostNotifier;
 
 // KeyedService which manages Android Messages integration. This service
 // has four main responsibilities:
@@ -79,7 +78,6 @@
   std::unique_ptr<AndroidSmsAppManager> android_sms_app_manager_;
   std::unique_ptr<AndroidSmsPairingStateTrackerImpl>
       android_sms_pairing_state_tracker_;
-  std::unique_ptr<PairingLostNotifier> pairing_lost_notifier_;
   std::unique_ptr<ConnectionManager> connection_manager_;
 };
 
diff --git a/chrome/browser/ash/android_sms/android_sms_service_factory.cc b/chrome/browser/ash/android_sms/android_sms_service_factory.cc
index 07de512f8..d486369a 100644
--- a/chrome/browser/ash/android_sms/android_sms_service_factory.cc
+++ b/chrome/browser/ash/android_sms/android_sms_service_factory.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ash/android_sms/android_sms_service_factory.h"
 
-#include "chrome/browser/ash/android_sms/pairing_lost_notifier.h"
 #include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -100,7 +99,6 @@
 
 void AndroidSmsServiceFactory::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-  PairingLostNotifier::RegisterProfilePrefs(registry);
   AndroidSmsAppManagerImpl::RegisterProfilePrefs(registry);
 }
 
diff --git a/chrome/browser/ash/android_sms/pairing_lost_notifier.cc b/chrome/browser/ash/android_sms/pairing_lost_notifier.cc
deleted file mode 100644
index a3af450c..0000000
--- a/chrome/browser/ash/android_sms/pairing_lost_notifier.cc
+++ /dev/null
@@ -1,173 +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 "chrome/browser/ash/android_sms/pairing_lost_notifier.h"
-
-#include "ash/public/cpp/notification_utils.h"
-#include "base/bind.h"
-#include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/notifications/notification_display_service.h"
-#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
-#include "chrome/grit/generated_resources.h"
-#include "chromeos/components/multidevice/logging/logging.h"
-#include "chromeos/services/multidevice_setup/public/cpp/android_sms_app_helper_delegate.h"
-#include "components/account_id/account_id.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/message_center/public/cpp/notification_types.h"
-
-namespace ash {
-
-// TODO(https://crbug.com/1164001): remove when chromeos/multidevice_setup is
-// migrated.
-namespace multidevice_setup {
-namespace mojom = ::chromeos::multidevice_setup::mojom;
-}
-
-namespace android_sms {
-
-namespace {
-
-const char kWasPreviouslySetUpPrefName[] = "android_sms.was_previously_set_up";
-
-const char kAndroidSmsNotifierId[] = "ash.android_sms";
-const char kPairingLostNotificationId[] = "android_sms.pairing_lost";
-
-}  // namespace
-
-// static
-void PairingLostNotifier::RegisterProfilePrefs(PrefRegistrySimple* registry) {
-  registry->RegisterBooleanPref(kWasPreviouslySetUpPrefName, false);
-}
-
-PairingLostNotifier::PairingLostNotifier(
-    Profile* profile,
-    multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client,
-    PrefService* pref_service,
-    multidevice_setup::AndroidSmsAppHelperDelegate*
-        android_sms_app_helper_delegate)
-    : profile_(profile),
-      multidevice_setup_client_(multidevice_setup_client),
-      pref_service_(pref_service),
-      android_sms_app_helper_delegate_(android_sms_app_helper_delegate) {
-  multidevice_setup_client_->AddObserver(this);
-
-  // Wait until the app registry is loaded before querying for installed PWA
-  // info.
-  android_sms_app_helper_delegate_->ExecuteOnAppRegistryReady(
-      base::BindOnce(&PairingLostNotifier::HandleMessagesFeatureState,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-PairingLostNotifier::~PairingLostNotifier() {
-  multidevice_setup_client_->RemoveObserver(this);
-}
-
-void PairingLostNotifier::OnFeatureStatesChanged(
-    const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
-        feature_states_map) {
-  HandleMessagesFeatureState();
-}
-
-void PairingLostNotifier::HandleMessagesFeatureState() {
-  if (!android_sms_app_helper_delegate_->IsAppRegistryReady()) {
-    return;
-  }
-
-  multidevice_setup::mojom::FeatureState state =
-      multidevice_setup_client_->GetFeatureStates()
-          .find(multidevice_setup::mojom::Feature::kMessages)
-          ->second;
-
-  // If the feature is disabled we should never show any notifications or
-  // track the pairing state.  To avoid showing the notification immediately
-  // if the feature is ever enabled in the future, the pref should also be
-  // cleared.
-  if (state == multidevice_setup::mojom::FeatureState::kDisabledByUser) {
-    pref_service_->SetBoolean(kWasPreviouslySetUpPrefName, false);
-    ClosePairingLostNotificationIfVisible();
-    return;
-  }
-
-  // If Messages is enabled, the user has completed the setup process.
-  if (state == multidevice_setup::mojom::FeatureState::kEnabledByUser) {
-    HandleSetUpFeatureState();
-    return;
-  }
-
-  // If further setup is not required, there is no need to show a notification.
-  if (state != multidevice_setup::mojom::FeatureState::kFurtherSetupRequired)
-    return;
-
-  // The Messages was not previously set up, the notification should not be
-  // shown.
-  if (!pref_service_->GetBoolean(kWasPreviouslySetUpPrefName))
-    return;
-
-  // Set the preference to false to indicate that the app was not previously set
-  // up, then show the notification.
-  pref_service_->SetBoolean(kWasPreviouslySetUpPrefName, false);
-  ShowPairingLostNotification();
-}
-
-void PairingLostNotifier::HandleSetUpFeatureState() {
-  // Store a preference indicating that the feature has been set up. This
-  // preference will be checked in the future in the case that the phone has
-  // become unpaired.
-  pref_service_->SetBoolean(kWasPreviouslySetUpPrefName, true);
-
-  // If the "pairing lost" notification is currently visible, close it.
-  // Otherwise, the user could be confused that a notification is alerting the
-  // user to complete a task that has already been completed.
-  ClosePairingLostNotificationIfVisible();
-}
-
-void PairingLostNotifier::ShowPairingLostNotification() {
-  PA_LOG(INFO) << "PairingLostNotifier::ShowPairingLostNotification(): "
-               << "Pairing has been lost; displaying notification.";
-
-  NotificationDisplayService::GetForProfile(profile_)->Display(
-      NotificationHandler::Type::TRANSIENT,
-      *CreateSystemNotification(
-          message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE,
-          kPairingLostNotificationId,
-          l10n_util::GetStringUTF16(
-              IDS_ANDROID_MESSAGES_PAIRING_LOST_NOTIFICATION_TITLE),
-          l10n_util::GetStringUTF16(
-              IDS_ANDROID_MESSAGES_PAIRING_LOST_NOTIFICATION_MESSAGE),
-          std::u16string() /* display_source */, GURL() /* origin_url */,
-          message_center::NotifierId(
-              message_center::NotifierType::SYSTEM_COMPONENT,
-              kAndroidSmsNotifierId),
-          {} /* rich_notification_data */,
-          base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
-              base::BindRepeating(
-                  &PairingLostNotifier::OnPairingLostNotificationClick,
-                  weak_ptr_factory_.GetWeakPtr())),
-          kNotificationMessagesIcon,
-          message_center::SystemNotificationWarningLevel::NORMAL),
-      /*metadata=*/nullptr);
-}
-
-void PairingLostNotifier::ClosePairingLostNotificationIfVisible() {
-  PA_LOG(INFO) << "PairingLostNotifier::"
-               << "ClosePairingLostNotificationIfVisible(): "
-               << "Closing pairing lost notification if visible.";
-
-  NotificationDisplayService::GetForProfile(profile_)->Close(
-      NotificationHandler::Type::TRANSIENT, kPairingLostNotificationId);
-}
-
-void PairingLostNotifier::OnPairingLostNotificationClick(
-    absl::optional<int> button_index) {
-  PA_LOG(INFO) << "PairingLostNotifier::OnPairingLostNotificationClick(): "
-               << "Pairing notification clicked; opening PWA.";
-
-  ClosePairingLostNotificationIfVisible();
-  android_sms_app_helper_delegate_->SetUpAndLaunchAndroidSmsApp();
-}
-
-}  // namespace android_sms
-}  // namespace ash
diff --git a/chrome/browser/ash/android_sms/pairing_lost_notifier.h b/chrome/browser/ash/android_sms/pairing_lost_notifier.h
deleted file mode 100644
index bf4329e7..0000000
--- a/chrome/browser/ash/android_sms/pairing_lost_notifier.h
+++ /dev/null
@@ -1,64 +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 CHROME_BROWSER_ASH_ANDROID_SMS_PAIRING_LOST_NOTIFIER_H_
-#define CHROME_BROWSER_ASH_ANDROID_SMS_PAIRING_LOST_NOTIFIER_H_
-
-#include "base/memory/weak_ptr.h"
-// TODO(https://crbug.com/1164001): move to forward declaration.
-#include "chromeos/services/multidevice_setup/public/cpp/android_sms_app_helper_delegate.h"
-#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
-
-class PrefRegistrySimple;
-class PrefService;
-class Profile;
-
-namespace ash {
-namespace android_sms {
-
-// Displays a notification when a user loses pairing between their phone and
-// Chromebook.
-class PairingLostNotifier
-    : public multidevice_setup::MultiDeviceSetupClient::Observer {
- public:
-  PairingLostNotifier(
-      Profile* profile,
-      multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client,
-      PrefService* pref_service,
-      multidevice_setup::AndroidSmsAppHelperDelegate*
-          android_sms_app_helper_delegate);
-
-  PairingLostNotifier(const PairingLostNotifier&) = delete;
-  PairingLostNotifier& operator=(const PairingLostNotifier&) = delete;
-
-  ~PairingLostNotifier() override;
-
-  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
- private:
-  // multidevice_setup::MultiDeviceSetupClient::Observer:
-  void OnFeatureStatesChanged(
-      const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
-          feature_states_map) override;
-
-  void HandleMessagesFeatureState();
-  void HandleSetUpFeatureState();
-
-  void ShowPairingLostNotification();
-  void ClosePairingLostNotificationIfVisible();
-  void OnPairingLostNotificationClick(absl::optional<int> button_index);
-
-  Profile* profile_;
-  multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_;
-  PrefService* pref_service_;
-  multidevice_setup::AndroidSmsAppHelperDelegate*
-      android_sms_app_helper_delegate_;
-
-  base::WeakPtrFactory<PairingLostNotifier> weak_ptr_factory_{this};
-};
-
-}  // namespace android_sms
-}  // namespace ash
-
-#endif  // CHROME_BROWSER_ASH_ANDROID_SMS_PAIRING_LOST_NOTIFIER_H_
diff --git a/chrome/browser/ash/android_sms/pairing_lost_notifier_unittest.cc b/chrome/browser/ash/android_sms/pairing_lost_notifier_unittest.cc
deleted file mode 100644
index 3387323..0000000
--- a/chrome/browser/ash/android_sms/pairing_lost_notifier_unittest.cc
+++ /dev/null
@@ -1,153 +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 "chrome/browser/ash/android_sms/pairing_lost_notifier.h"
-
-#include "chrome/browser/notifications/notification_display_service_tester.h"
-#include "chrome/test/base/browser_with_test_window_test.h"
-#include "chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h"
-#include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace ash {
-
-// TODO(https://crbug.com/1164001): remove when chromeos/multidevice_setup is
-// migrated.
-namespace multidevice_setup {
-namespace mojom = ::chromeos::multidevice_setup::mojom;
-}
-
-namespace android_sms {
-
-namespace {
-
-const char kWasPreviouslySetUpPrefName[] = "android_sms.was_previously_set_up";
-const char kPairingLostNotificationId[] = "android_sms.pairing_lost";
-
-}  // namespace
-
-class PairingLostNotifierTest : public BrowserWithTestWindowTest {
- public:
-  PairingLostNotifierTest(const PairingLostNotifierTest&) = delete;
-  PairingLostNotifierTest& operator=(const PairingLostNotifierTest&) = delete;
-
- protected:
-  PairingLostNotifierTest() = default;
-  ~PairingLostNotifierTest() override = default;
-
-  void SetUp() override {
-    BrowserWithTestWindowTest::SetUp();
-
-    display_service_tester_ =
-        std::make_unique<NotificationDisplayServiceTester>(profile());
-    fake_multidevice_setup_client_ =
-        std::make_unique<multidevice_setup::FakeMultiDeviceSetupClient>();
-    test_pref_service_ =
-        std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
-    PairingLostNotifier::RegisterProfilePrefs(test_pref_service_->registry());
-    fake_android_sms_app_helper_delegate_ =
-        std::make_unique<multidevice_setup::FakeAndroidSmsAppHelperDelegate>();
-    fake_android_sms_app_helper_delegate_->set_is_app_registry_ready(true);
-
-    pairing_lost_notifier_ = std::make_unique<PairingLostNotifier>(
-        profile(), fake_multidevice_setup_client_.get(),
-        test_pref_service_.get(), fake_android_sms_app_helper_delegate_.get());
-  }
-
-  bool IsNotificationVisible() {
-    return display_service_tester_->GetNotification(kPairingLostNotificationId)
-        .has_value();
-  }
-
-  void ClickVisibleNotification() {
-    ASSERT_TRUE(IsNotificationVisible());
-    display_service_tester_->SimulateClick(
-        NotificationHandler::Type::TRANSIENT, kPairingLostNotificationId,
-        absl::nullopt /* action_index */, absl::nullopt /* reply */);
-  }
-
-  void SetWasPreviouslySetUpPreference(bool was_previously_set_up) {
-    test_pref_service_->SetBoolean(kWasPreviouslySetUpPrefName,
-                                   was_previously_set_up);
-  }
-
-  bool GetWasPreviouslySetUpPreference() {
-    return test_pref_service_->GetBoolean(kWasPreviouslySetUpPrefName);
-  }
-
-  bool WasAppLaunched() {
-    return fake_android_sms_app_helper_delegate_->has_launched_app();
-  }
-
-  void SetFeatureState(multidevice_setup::mojom::FeatureState feature_state) {
-    fake_multidevice_setup_client_->SetFeatureState(
-        multidevice_setup::mojom::Feature::kMessages, feature_state);
-  }
-
- private:
-  std::unique_ptr<NotificationDisplayServiceTester> display_service_tester_;
-  std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient>
-      fake_multidevice_setup_client_;
-  std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
-      test_pref_service_;
-  std::unique_ptr<multidevice_setup::FakeAndroidSmsAppHelperDelegate>
-      fake_android_sms_app_helper_delegate_;
-
-  std::unique_ptr<PairingLostNotifier> pairing_lost_notifier_;
-};
-
-TEST_F(PairingLostNotifierTest, WasNotPreviouslySetUp) {
-  // Simulate the initial installation of the app. No notification should be
-  // displayed.
-  SetFeatureState(
-      multidevice_setup::mojom::FeatureState::kFurtherSetupRequired);
-  EXPECT_FALSE(IsNotificationVisible());
-
-  // Simulate initial setup. No notification should be displayed, but the
-  // preference should have been set to true.
-  SetFeatureState(multidevice_setup::mojom::FeatureState::kEnabledByUser);
-  EXPECT_FALSE(IsNotificationVisible());
-  EXPECT_TRUE(GetWasPreviouslySetUpPreference());
-}
-
-TEST_F(PairingLostNotifierTest, WasPreviouslySetUp_ClickNotification) {
-  // Simulate the app having been previously set up.
-  SetWasPreviouslySetUpPreference(true /* was_previously_set_up */);
-
-  // Transition back to the "setup required" state. This should trigger a
-  // notification, and the preference should have transitioned back to false to
-  // ensure that a duplicate notification is not shown.
-  SetFeatureState(
-      multidevice_setup::mojom::FeatureState::kFurtherSetupRequired);
-  EXPECT_TRUE(IsNotificationVisible());
-  EXPECT_FALSE(GetWasPreviouslySetUpPreference());
-
-  // Clicking the notification should launch the PWA.
-  ClickVisibleNotification();
-  EXPECT_TRUE(WasAppLaunched());
-}
-
-TEST_F(PairingLostNotifierTest,
-       WasPreviouslySetUp_CompleteSetupWithoutClickingNotification) {
-  // Simulate the app having been previously set up.
-  SetWasPreviouslySetUpPreference(true /* was_previously_set_up */);
-
-  // Transition back to the "setup required" state. This should trigger a
-  // notification, and the preference should have transitioned back to false to
-  // ensure that a duplicate notification is not shown.
-  SetFeatureState(
-      multidevice_setup::mojom::FeatureState::kFurtherSetupRequired);
-  EXPECT_TRUE(IsNotificationVisible());
-  EXPECT_FALSE(GetWasPreviouslySetUpPreference());
-
-  // Transition to the "enabled" state; this should cause the notification to be
-  // closed since it is no longer applicable.
-  SetFeatureState(multidevice_setup::mojom::FeatureState::kEnabledByUser);
-  EXPECT_FALSE(IsNotificationVisible());
-  EXPECT_TRUE(GetWasPreviouslySetUpPreference());
-}
-
-}  // namespace android_sms
-}  // namespace ash
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
index 6bd9ecb0..38068a2 100644
--- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
+++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/test/ash_test_helper.h"
@@ -21,8 +23,6 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_stop_reason.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/wm_helper.h"
 #include "components/exo/wm_helper_chromeos.h"
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
index d7bbbd0..df23fe0 100644
--- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
@@ -8,6 +8,8 @@
 #include <map>
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "ash/public/cpp/autotest_desks_api.h"
@@ -58,8 +60,6 @@
 #include "components/app_restore/window_info.h"
 #include "components/app_restore/window_properties.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/buffer.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
diff --git a/chrome/browser/ash/apps/apk_web_app_service.cc b/chrome/browser/ash/apps/apk_web_app_service.cc
index 517f18fe..f52ea2d 100644
--- a/chrome/browser/ash/apps/apk_web_app_service.cc
+++ b/chrome/browser/ash/apps/apk_web_app_service.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/feature_list.h"
@@ -22,7 +23,6 @@
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/chrome_features.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
diff --git a/chrome/browser/ash/arc/accessibility/accessibility_helper_instance_remote_proxy.cc b/chrome/browser/ash/arc/accessibility/accessibility_helper_instance_remote_proxy.cc
index c7705b83..77d159b4 100644
--- a/chrome/browser/ash/arc/accessibility/accessibility_helper_instance_remote_proxy.cc
+++ b/chrome/browser/ash/arc/accessibility/accessibility_helper_instance_remote_proxy.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_holder.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_holder.h"
 
 namespace arc {
 
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
index 2775525..e18eca52 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -7,6 +7,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_surface.h"
 #include "ash/public/cpp/window_properties.h"
 #include "base/bind.h"
@@ -20,8 +22,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/common/extensions/api/accessibility_private.h"
 #include "chrome/common/pref_names.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
 #include "components/exo/wm_helper.h"
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h
index 060bc8a3..095b1b7 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <tuple>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_surface_manager.h"
 #include "base/callback_list.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
@@ -18,7 +19,6 @@
 #include "chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h"
 #include "chrome/browser/ash/arc/accessibility/ax_tree_source_arc.h"
 #include "components/arc/mojom/accessibility_helper.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 class PrefService;
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
index f816594..502fb12 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
@@ -9,6 +9,8 @@
 
 #include "ash/accessibility/ui/accessibility_focus_ring_controller_impl.h"
 #include "ash/accessibility/ui/accessibility_focus_ring_layer.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_accessibility_helper_instance.h"
@@ -21,8 +23,6 @@
 #include "chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/buffer.h"
 #include "components/exo/client_controlled_accelerators.h"
 #include "components/exo/shell_surface.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 e1ed9e8..ea2a9f3 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
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/constants/app_types.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_content_view.h"
@@ -31,7 +32,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "components/arc/mojom/accessibility_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/live_caption/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
index e6a28650..ab720077 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
@@ -7,6 +7,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_surface.h"
 #include "ash/public/cpp/external_arc/message_center/arc_notification_surface_manager.h"
@@ -22,8 +24,6 @@
 #include "chrome/browser/ash/arc/accessibility/ax_tree_source_arc.h"
 #include "chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service.h"
 #include "chrome/common/extensions/api/accessibility_private.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/exo/input_method_surface.h"
 #include "components/exo/shell_surface.h"
 #include "components/exo/shell_surface_util.h"
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc
index ef784223..aecb418 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h"
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/constants/app_types.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "chrome/browser/ash/arc/accessibility/accessibility_helper_instance_remote_proxy.h"
@@ -13,7 +14,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "components/arc/mojom/accessibility_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/exo/shell_surface_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/client/aura_constants.h"
diff --git a/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.cc b/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.cc
index 0f7c482..05d9ce21 100644
--- a/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.cc
+++ b/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.cc
@@ -11,6 +11,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/files/file_util.h"
@@ -22,7 +23,6 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
 #include "chromeos/system/statistics_provider.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.h b/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.h
index 1eb34b6..17c5d8b 100644
--- a/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.h
+++ b/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.h
@@ -5,11 +5,11 @@
 #ifndef CHROME_BROWSER_ASH_ARC_ADBD_ARC_ADBD_MONITOR_BRIDGE_H_
 #define CHROME_BROWSER_ASH_ARC_ADBD_ARC_ADBD_MONITOR_BRIDGE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "components/arc/mojom/adbd.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge_unittest.cc b/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge_unittest.cc
index 93e49415..a5e8eb8 100644
--- a/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_adbd_monitor_instance.h"
 #include "ash/components/arc/test/fake_arc_session.h"
@@ -14,8 +16,6 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "chromeos/dbus/upstart/fake_upstart_client.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc
index 79c85ad..7ed838a 100644
--- a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc
+++ b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc
@@ -7,6 +7,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
@@ -15,8 +17,6 @@
 #include "chrome/browser/apps/app_service/menu_item_constants.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
 #include "chrome/browser/ash/arc/icon_decode_request.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace arc {
 
diff --git a/chrome/browser/ash/arc/arc_demo_mode_delegate_impl.h b/chrome/browser/ash/arc/arc_demo_mode_delegate_impl.h
index a88194b..ef8f9c8 100644
--- a/chrome/browser/ash/arc/arc_demo_mode_delegate_impl.h
+++ b/chrome/browser/ash/arc/arc_demo_mode_delegate_impl.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_ASH_ARC_ARC_DEMO_MODE_DELEGATE_IMPL_H_
 #define CHROME_BROWSER_ASH_ARC_ARC_DEMO_MODE_DELEGATE_IMPL_H_
 
+#include "ash/components/arc/session/arc_client_adapter.h"
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
-#include "components/arc/session/arc_client_adapter.h"
 
 namespace arc {
 
diff --git a/chrome/browser/ash/arc/arc_ui_availability_reporter.cc b/chrome/browser/ash/arc/arc_ui_availability_reporter.cc
index 07abab847..c9dd758 100644
--- a/chrome/browser/ash/arc/arc_ui_availability_reporter.cc
+++ b/chrome/browser/ash/arc/arc_ui_availability_reporter.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/ash/arc/arc_ui_availability_reporter.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/logging.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace arc {
 
diff --git a/chrome/browser/ash/arc/arc_ui_availability_reporter_unittest.cc b/chrome/browser/ash/arc/arc_ui_availability_reporter_unittest.cc
index 9163f2e..9dc32875 100644
--- a/chrome/browser/ash/arc/arc_ui_availability_reporter_unittest.cc
+++ b/chrome/browser/ash/arc/arc_ui_availability_reporter_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ash/arc/arc_ui_availability_reporter.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "base/command_line.h"
@@ -13,8 +15,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/arc_util.h b/chrome/browser/ash/arc/arc_util.h
index 52e1c61..2707e5b 100644
--- a/chrome/browser/ash/arc/arc_util.h
+++ b/chrome/browser/ash/arc/arc_util.h
@@ -8,9 +8,9 @@
 #include <stdint.h>
 #include <memory>
 
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "base/callback_forward.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
-#include "components/arc/session/arc_management_transition.h"
 #include "storage/browser/file_system/file_system_url.h"
 
 // Most utility should be put in components/arc/arc_util.{h,cc}, rather than
diff --git a/chrome/browser/ash/arc/auth/arc_auth_service.cc b/chrome/browser/ash/arc/auth/arc_auth_service.cc
index eedd7617..e1edb01 100644
--- a/chrome/browser/ash/arc/auth/arc_auth_service.cc
+++ b/chrome/browser/ash/arc/auth/arc_auth_service.cc
@@ -11,6 +11,10 @@
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_management_transition.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/singleton.h"
@@ -37,10 +41,6 @@
 #include "chrome/common/webui_url_constants.h"
 #include "components/account_manager_core/account_manager_facade.h"
 #include "components/account_manager_core/chromeos/account_manager_facade_factory.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_management_transition.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ash/arc/auth/arc_auth_service.h b/chrome/browser/ash/arc/auth/arc_auth_service.h
index 30217af2..335ee5b 100644
--- a/chrome/browser/ash/arc/auth/arc_auth_service.h
+++ b/chrome/browser/ash/arc/auth/arc_auth_service.h
@@ -9,13 +9,13 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/arc/auth/arc_active_directory_enrollment_token_fetcher.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
 #include "components/arc/mojom/auth.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 
diff --git a/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc
index ca8d356..357a8828 100644
--- a/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc
+++ b/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc
@@ -8,6 +8,10 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_data_remover.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_arc_session.h"
@@ -49,10 +53,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_data_remover.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/policy/core/common/policy_switches.h"
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc
index 05f4266f..b245265 100644
--- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -17,6 +17,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/bluetooth/bluetooth_type_converters.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/constants/ash_pref_names.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -35,7 +36,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/device_event_log/device_event_log.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h
index 1ccbfe3..2111c91 100644
--- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h
+++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h
@@ -15,6 +15,7 @@
 #include <unordered_set>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/files/file.h"
@@ -24,7 +25,6 @@
 #include "chrome/browser/ash/arc/bluetooth/arc_bluetooth_task_queue.h"
 #include "components/arc/mojom/bluetooth.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
index 3e349c9..e37b571 100644
--- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "ash/components/arc/bluetooth/bluetooth_type_converters.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_bluetooth_instance.h"
 #include "base/bind.h"
@@ -18,7 +19,6 @@
 #include "base/test/scoped_chromeos_version_info.h"
 #include "base/test/task_environment.h"
 #include "components/arc/mojom/bluetooth.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
 #include "device/bluetooth/dbus/fake_bluetooth_device_client.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 8176d8aa..72b1de9f 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
@@ -8,6 +8,7 @@
 
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
@@ -20,7 +21,6 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 namespace {
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 20d8cff..d986a7948 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
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/bind.h"
@@ -20,7 +21,6 @@
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc
index 3f0d2ee..983e6e01 100644
--- a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc
+++ b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.cc
@@ -7,6 +7,8 @@
 #include <string>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/memory/singleton.h"
@@ -14,8 +16,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "components/arc/mojom/cast_receiver.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 
diff --git a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h
index 63760f1..6cb48414 100644
--- a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h
+++ b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "components/arc/mojom/cast_receiver.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc
index 51c1629..e3fe5d0 100644
--- a/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc
+++ b/chrome/browser/ash/arc/cast_receiver/arc_cast_receiver_service_unittest.cc
@@ -6,14 +6,14 @@
 
 #include <string>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_cast_receiver_instance.h"
 #include "ash/components/settings/cros_settings_names.h"
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate.h b/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate.h
index f1f3b11..67cec66 100644
--- a/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate.h
+++ b/chrome/browser/ash/arc/enterprise/arc_data_snapshotd_delegate.h
@@ -5,13 +5,13 @@
 #ifndef CHROME_BROWSER_ASH_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_DELEGATE_H_
 #define CHROME_BROWSER_ASH_ARC_ENTERPRISE_ARC_DATA_SNAPSHOTD_DELEGATE_H_
 
+#include "ash/components/arc/enterprise/arc_apps_tracker.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/enterprise/arc_snapshot_reboot_notification.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
-#include "components/arc/enterprise/arc_apps_tracker.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
-#include "components/arc/enterprise/arc_snapshot_reboot_notification.h"
-#include "components/arc/session/arc_stop_reason.h"
 
 class PrefService;
 
diff --git a/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service.cc b/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service.cc
index 45cbbfbf..780d93b8 100644
--- a/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service.cc
+++ b/chrome/browser/ash/arc/enterprise/arc_enterprise_reporting_service.cc
@@ -7,12 +7,12 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace arc {
 namespace {
diff --git a/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker.h b/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker.h
index c4b4497..9bd25234 100644
--- a/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker.h
+++ b/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
+#include "ash/components/arc/enterprise/arc_apps_tracker.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "components/arc/enterprise/arc_apps_tracker.h"
 
 class ArcAppListPrefs;
 
diff --git a/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker_unittest.cc b/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker_unittest.cc
index f58c1b4..16fab4c3 100644
--- a/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker_unittest.cc
+++ b/chrome/browser/ash/arc/enterprise/arc_force_installed_apps_tracker_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/barrier_closure.h"
 #include "base/callback_helpers.h"
 #include "base/run_loop.h"
@@ -14,7 +15,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/policy/core/common/mock_policy_service.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_service.h"
diff --git a/chrome/browser/ash/arc/enterprise/arc_snapshot_reboot_notification_impl.h b/chrome/browser/ash/arc/enterprise/arc_snapshot_reboot_notification_impl.h
index d5acf7a..ecdccde 100644
--- a/chrome/browser/ash/arc/enterprise/arc_snapshot_reboot_notification_impl.h
+++ b/chrome/browser/ash/arc/enterprise/arc_snapshot_reboot_notification_impl.h
@@ -5,9 +5,9 @@
 #ifndef CHROME_BROWSER_ASH_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_IMPL_H_
 #define CHROME_BROWSER_ASH_ARC_ENTERPRISE_ARC_SNAPSHOT_REBOOT_NOTIFICATION_IMPL_H_
 
+#include "ash/components/arc/enterprise/arc_snapshot_reboot_notification.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "components/arc/enterprise/arc_snapshot_reboot_notification.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer_unittest.cc b/chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer_unittest.cc
index 0d6a2d6..a6dd707 100644
--- a/chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer_unittest.cc
+++ b/chrome/browser/ash/arc/enterprise/cert_store/arc_cert_installer_unittest.cc
@@ -7,6 +7,8 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_policy_instance.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
@@ -15,8 +17,6 @@
 #include "chrome/browser/ash/arc/policy/arc_policy_bridge.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/mojom/policy.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/core/common/remote_commands/remote_commands_queue.h"
 #include "content/public/test/browser_task_environment.h"
 #include "crypto/rsa_private_key.h"
diff --git a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc
index ab6847d..86548b78 100644
--- a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc
+++ b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/constants/ash_switches.h"
 #include "base/base64.h"
@@ -36,7 +37,6 @@
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/network/network_cert_loader.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.cc b/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.cc
index a972469..071159c 100644
--- a/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.cc
+++ b/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/files/file_enumerator.h"
@@ -29,7 +30,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
 #include "components/arc/mojom/file_system.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.h b/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.h
index d842a5c..ddb5e4c 100644
--- a/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.h
+++ b/chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_service.h
@@ -10,12 +10,12 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/components/arc/volume_mounter/arc_volume_mounter_bridge.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "components/arc/mojom/file_system.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace base {
diff --git a/chrome/browser/ash/arc/file_system_watcher/file_system_scanner.cc b/chrome/browser/ash/arc/file_system_watcher/file_system_scanner.cc
index 9c89eca..6522bd12 100644
--- a/chrome/browser/ash/arc/file_system_watcher/file_system_scanner.cc
+++ b/chrome/browser/ash/arc/file_system_watcher/file_system_scanner.cc
@@ -7,13 +7,13 @@
 #include <fts.h>
 #include <sys/stat.h>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/files/file_enumerator.h"
 #include "base/task/post_task.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "chrome/browser/ash/arc/file_system_watcher/arc_file_system_watcher_util.h"
 #include "components/arc/mojom/file_system.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/ash/arc/file_system_watcher/file_system_scanner_unittest.cc b/chrome/browser/ash/arc/file_system_watcher/file_system_scanner_unittest.cc
index 508c253..a144159 100644
--- a/chrome/browser/ash/arc/file_system_watcher/file_system_scanner_unittest.cc
+++ b/chrome/browser/ash/arc/file_system_watcher/file_system_scanner_unittest.cc
@@ -9,6 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/files/file_enumerator.h"
@@ -20,8 +22,6 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
index 1ad9e638..5b6e28d 100644
--- a/chrome/browser/ash/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
@@ -9,6 +9,8 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -19,8 +21,6 @@
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/test/browser_task_environment.h"
 #include "storage/browser/file_system/file_system_url.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
index 62235d4..50b9f90 100644
--- a/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
@@ -10,6 +10,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -18,8 +20,6 @@
 #include "chrome/browser/ash/arc/fileapi/arc_content_file_system_size_util.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/test/browser_task_environment.h"
 #include "net/base/io_buffer.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc
index e2042e6b..d539fdf 100644
--- a/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc
@@ -8,14 +8,14 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
 #include "net/base/io_buffer.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.cc b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.cc
index 8def199..e2c01772 100644
--- a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root.h"
 #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.h"
 #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_thread.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc
index fff21a2..84ef810 100644
--- a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map_factory.h"
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_root_map.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_unittest.cc
index b8b39e4..a5b0807 100644
--- a/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_documents_provider_root_unittest.cc
@@ -11,6 +11,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -21,8 +23,6 @@
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/mojom/file_system.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/test/browser_task_environment.h"
 #include "storage/browser/file_system/file_system_operation.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.cc b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.cc
index 5f13efd..07e5008 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
@@ -32,7 +33,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/virtual_file_provider/virtual_file_provider_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h
index 1ea3703..20124f6 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h
@@ -12,13 +12,13 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "chrome/browser/ash/arc/fileapi/arc_select_files_handler.h"
 #include "chrome/browser/ash/arc/fileapi/file_stream_forwarder.h"
 #include "components/arc/mojom/file_system.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "storage/browser/file_system/file_system_operation.h"
 #include "storage/browser/file_system/watcher_manager.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc
index 8af5212b..4fd55a6 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_bridge_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -27,7 +28,6 @@
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/virtual_file_provider/fake_virtual_file_provider_client.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
 #include "storage/browser/file_system/external_mount_points.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.cc b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.cc
index c198f50..a3b4b5e 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
@@ -16,7 +17,6 @@
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h
index 621cc5fe..5c0e69c6 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h
@@ -12,13 +12,13 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
 #include "components/arc/mojom/file_system.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "storage/browser/file_system/watcher_manager.h"
 
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_unittest.cc
index a0cbbdc4..390d3ba 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_unittest.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -14,8 +16,6 @@
 #include "base/run_loop.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/mojom/file_system.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_util.cc b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_util.cc
index 57b092bd..bb90ec0 100644
--- a/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_util.cc
+++ b/chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner_util.cc
@@ -7,8 +7,8 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.cc b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.cc
index f097ecc..eb61487e 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.cc
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.h b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.h
index 491293c..b86a3d36 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.h
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge_impl.h
@@ -8,8 +8,8 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_bridge.h"
-#include "components/arc/session/connection_observer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
index d8a0448..fbec018 100644
--- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
+++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/test_browser_context.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/public/cpp/keyboard/arc/arc_input_method_bounds_tracker.h"
@@ -25,7 +26,6 @@
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/crx_file/id_util.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc
index 6c5b5cb..aebffcab 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/command_line.h"
@@ -18,8 +20,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
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 e9a2b6c9..d4465eb0 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.cc
@@ -6,6 +6,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
@@ -22,7 +23,6 @@
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/arc/mojom/power.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace arc {
 
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.h b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.h
index 91b7b25..0fab28a 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.h
+++ b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle.h
@@ -10,9 +10,9 @@
 #include <utility>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "chrome/browser/ash/throttle_observer.h"
 #include "chrome/browser/ash/throttle_service.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace base {
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc
index 1c2ab31..c322e3df 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_instance_throttle_unittest.cc
@@ -11,6 +11,8 @@
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/power/arc_power_bridge.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_arc_session.h"
@@ -26,8 +28,6 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/mojom/power.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/test/browser_task_environment.h"
 #include "services/device/public/cpp/test/test_wake_lock_provider.h"
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer.cc b/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer.cc
index 3e7e463..709de30 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer.cc
@@ -8,7 +8,10 @@
 
 namespace {
 
-constexpr base::TimeDelta kHandleAnrTime = base::Seconds(10);
+// Time to recover ANR by default.
+constexpr base::TimeDelta kHandleDefaultAnrTime = base::Seconds(10);
+// Time to recover ANR in services.
+constexpr base::TimeDelta kHandleServiceAnrTime = base::Seconds(20);
 
 }  // namespace
 
@@ -40,21 +43,35 @@
 }
 
 void ArcPowerThrottleObserver::OnPreAnr(mojom::AnrType type) {
-  VLOG(1) << "Handle pre-ANR state";
+  VLOG(1) << "Handle pre-ANR state in " << type;
   // Android system server detects the situation that ANR crash may happen
   // soon. This might be caused by ARC throttling when Android does not have
   // enough CPU power to flash pending requests. Disable throttling in this
   // case for kHandleAnrTime| period in order to let the system server to flash
   // requests.
   SetActive(true);
-  // Automatically inactivate this lock in |kHandleAnrTime|. Note, if we
-  // would receive another pre-ANR event, timer would be re-activated and
-  // this lock would be extended.
+
+  base::TimeDelta delta;
+  switch (type) {
+    case mojom::AnrType::FOREGROUND_SERVICE:
+    case mojom::AnrType::BACKGROUND_SERVICE:
+      delta = kHandleServiceAnrTime;
+      break;
+    default:
+      delta = kHandleDefaultAnrTime;
+  }
+
+  // Automatically inactivate this lock in |delta| time. Note, if we
+  // would receive another pre-ANR event, timer might be re-activated and
+  // this lock might be extended.
   // base::Unretained(this) is safe here due to |timer_| is owned by this
-  // class and timer is automatically canceled on DTOR.
-  timer_.Start(FROM_HERE, kHandleAnrTime,
-               base::BindOnce(&ArcPowerThrottleObserver::SetActive,
-                              base::Unretained(this), false));
+  // class and timer is autoatically canceled on DTOR.
+  const base::TimeTicks new_expected = base::TimeTicks::Now() + delta;
+  if (timer_.desired_run_time() < new_expected) {
+    timer_.Start(FROM_HERE, delta,
+                 base::BindOnce(&ArcPowerThrottleObserver::SetActive,
+                                base::Unretained(this), false));
+  }
 }
 
 }  // namespace arc
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc
index f171ac8..43f1900 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ash/arc/instance_throttle/arc_power_throttle_observer.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/bind.h"
@@ -15,8 +17,6 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "components/arc/mojom/anr.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -55,6 +55,8 @@
     testing_profile_.reset();
     session_manager_.reset();
     service_manager_.reset();
+    chromeos::DBusThreadManager::Shutdown();
+    chromeos::PowerManagerClient::Shutdown();
   }
 
  protected:
@@ -81,7 +83,7 @@
   EXPECT_EQ(0, call_count);
   EXPECT_FALSE(observer.active());
 
-  observer.OnPreAnr(mojom::AnrType::SERVICE);
+  observer.OnPreAnr(mojom::AnrType::CONTENT_PROVIDER);
   EXPECT_EQ(1, call_count);
   EXPECT_TRUE(observer.active());
 
@@ -107,7 +109,7 @@
   EXPECT_FALSE(observer.active());
 
   // Timer is not fired after stopping observing.
-  observer.OnPreAnr(mojom::AnrType::SERVICE);
+  observer.OnPreAnr(mojom::AnrType::CONTENT_PROVIDER);
   EXPECT_EQ(3, call_count);
   EXPECT_TRUE(observer.active());
 
@@ -117,4 +119,69 @@
   EXPECT_TRUE(observer.active());
 }
 
+// Test verifies that new preANR extends active time of the lock in the case
+// new preANR type requires more time for handling.
+TEST_F(ArcPowerThrottleObserverTest, ActiveTimeExtended) {
+  ArcPowerThrottleObserver observer;
+  int call_count = 0;
+  observer.StartObserving(
+      profile(),
+      base::BindRepeating([](int* counter) { (*counter)++; }, &call_count));
+
+  observer.OnPreAnr(mojom::AnrType::PROCESS);
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(observer.active());
+
+  task_environment().FastForwardBy(base::Milliseconds(5000));
+  // Timer not yet fired
+  EXPECT_TRUE(observer.active());
+
+  observer.OnPreAnr(mojom::AnrType::FOREGROUND_SERVICE);
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(observer.active());
+
+  task_environment().FastForwardBy(base::Milliseconds(19000));
+  // Without FOREGROUND_SERVICE preANR timer would be already fired.
+  // So it is still active now.
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(observer.active());
+
+  task_environment().FastForwardBy(base::Milliseconds(1000));
+  EXPECT_EQ(2, call_count);
+  EXPECT_FALSE(observer.active());
+}
+
+// Test verifies that new preANR does not change active time of the lock in
+// the case new preANR type requires less time that currently remained from the
+// previous preANR handling.
+TEST_F(ArcPowerThrottleObserverTest, ActiveTimePreserved) {
+  ArcPowerThrottleObserver observer;
+  int call_count = 0;
+  observer.StartObserving(
+      profile(),
+      base::BindRepeating([](int* counter) { (*counter)++; }, &call_count));
+
+  observer.OnPreAnr(mojom::AnrType::FOREGROUND_SERVICE);
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(observer.active());
+
+  task_environment().FastForwardBy(base::Milliseconds(9000));
+  // Timer not yet fired
+  EXPECT_TRUE(observer.active());
+
+  // Process has shorter active time. It should not change the previous timeout.
+  observer.OnPreAnr(mojom::AnrType::PROCESS);
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(observer.active());
+
+  task_environment().FastForwardBy(base::Milliseconds(10000));
+  EXPECT_EQ(1, call_count);
+  EXPECT_TRUE(observer.active());
+
+  // Only now the lock becomes inactive.
+  task_environment().FastForwardBy(base::Milliseconds(1000));
+  EXPECT_EQ(2, call_count);
+  EXPECT_FALSE(observer.active());
+}
+
 }  // namespace arc
diff --git a/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc b/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc
index 34ef5ea..5dd7933 100644
--- a/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc
+++ b/chrome/browser/ash/arc/instance_throttle/arc_provisioning_throttle_observer_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/command_line.h"
@@ -17,8 +19,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "components/arc/mojom/auth.mojom.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog.cc b/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog.cc
index 9e3f28f..cc709be 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog.cc
+++ b/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog.cc
@@ -6,6 +6,8 @@
 
 #include <map>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram_functions.h"
@@ -22,8 +24,6 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/intent_picker_tab_helper.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/sync/protocol/sync_enums.pb.h"
 #include "components/sync_device_info/device_info.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog_unittest.cc b/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog_unittest.cc
index 7f6156c..8d705f3 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog_unittest.cc
+++ b/chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog_unittest.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/ash/arc/intent_helper/arc_external_protocol_dialog.h"
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/arc/arc_web_contents_data.h"
@@ -18,8 +20,6 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service.cc
index fb7cefb..55bc0ab8 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_settings_service.cc
+++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service.cc
@@ -10,6 +10,7 @@
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/settings/timezone_settings.h"
 #include "ash/constants/ash_pref_names.h"
 #include "base/bind.h"
@@ -41,7 +42,6 @@
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/backup_settings.mojom.h"
 #include "components/arc/mojom/pip.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/onc/onc_pref_names.h"
 #include "components/prefs/pref_change_registrar.h"
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service.h b/chrome/browser/ash/arc/intent_helper/arc_settings_service.h
index 069f448..7a273f7 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_settings_service.h
+++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service.h
@@ -7,9 +7,9 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
 #include "components/arc/mojom/intent_helper.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 class Profile;
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc
index 220d56b..5a594a8 100644
--- a/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc
+++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -10,6 +10,8 @@
 #include <vector>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_backup_settings_instance.h"
@@ -33,8 +35,6 @@
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/proxy/proxy_config_handler.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.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/arc/intent_helper/arc_settings_service_unittest.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service_unittest.cc
index ea44e19..3fafcb3 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
@@ -7,6 +7,8 @@
 #include <memory>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_arc_session.h"
@@ -28,8 +30,6 @@
 #include "chromeos/network/network_handler_test_helper.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_store.h"
diff --git a/chrome/browser/ash/arc/intent_helper/start_smart_selection_action_menu.cc b/chrome/browser/ash/arc/intent_helper/start_smart_selection_action_menu.cc
index 9604233c..5bc7cb70 100644
--- a/chrome/browser/ash/arc/intent_helper/start_smart_selection_action_menu.cc
+++ b/chrome/browser/ash/arc/intent_helper/start_smart_selection_action_menu.cc
@@ -9,6 +9,8 @@
 #include <utility>
 
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/string_util.h"
@@ -25,8 +27,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/renderer_context_menu/render_view_context_menu_proxy.h"
 #include "content/public/browser/context_menu_params.h"
 #include "ui/base/models/image_model.h"
diff --git a/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc b/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc
index 00cc613..4f7f83f8 100644
--- a/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc
+++ b/chrome/browser/ash/arc/keymaster/arc_keymaster_bridge.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
@@ -14,7 +15,6 @@
 #include "chrome/services/keymaster/public/mojom/cert_store.mojom.h"
 #include "chromeos/dbus/arc/arc_keymaster_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/system/invitation.h"
diff --git a/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge.cc b/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge.cc
index 58847301..e6d1a91 100644
--- a/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge.cc
+++ b/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge.cc
@@ -7,11 +7,11 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_service.h"
 #include "chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_factory.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/user_manager/user_manager.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge_unittest.cc b/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge_unittest.cc
index dff3fc68..a5f17ad 100644
--- a/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/kiosk/arc_kiosk_bridge_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge.cc b/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge.cc
index 354d3d7..5227cbb 100644
--- a/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge.cc
+++ b/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge.cc
@@ -8,6 +8,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "base/files/file_util.h"
 #include "base/memory/singleton.h"
@@ -19,7 +20,6 @@
 #include "chrome/browser/ui/browser.h"
 #include "components/arc/intent_helper/custom_tab.h"
 #include "components/arc/mojom/nearby_share.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge_unittest.cc b/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge_unittest.cc
index e7678f0..e7fc7284 100644
--- a/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/ash/arc/nearby_share/arc_nearby_share_bridge.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_nearby_share_instance.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/notification/arc_management_transition_notification_unittest.cc b/chrome/browser/ash/arc/notification/arc_management_transition_notification_unittest.cc
index 2cbd59d..6eec61dc 100644
--- a/chrome/browser/ash/arc/notification/arc_management_transition_notification_unittest.cc
+++ b/chrome/browser/ash/arc/notification/arc_management_transition_notification_unittest.cc
@@ -10,6 +10,7 @@
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
@@ -20,7 +21,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
-#include "components/arc/session/arc_management_transition.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc b/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
index 4c0d5887..5dd9dd7 100644
--- a/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
+++ b/chrome/browser/ash/arc/notification/arc_provision_notification_service_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/bind.h"
@@ -25,7 +26,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
diff --git a/chrome/browser/ash/arc/oemcrypto/arc_oemcrypto_bridge.cc b/chrome/browser/ash/arc/oemcrypto/arc_oemcrypto_bridge.cc
index a24a0fa..9f562bb 100644
--- a/chrome/browser/ash/arc/oemcrypto/arc_oemcrypto_bridge.cc
+++ b/chrome/browser/ash/arc/oemcrypto/arc_oemcrypto_bridge.cc
@@ -7,12 +7,12 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/ash/settings/cros_settings.h"
 #include "chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy_ash.h"
 #include "components/arc/mojom/protected_buffer_manager.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/gpu_service_registry.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
diff --git a/chrome/browser/ash/arc/pip/arc_pip_bridge.cc b/chrome/browser/ash/arc/pip/arc_pip_bridge.cc
index e34f570..eb7b8cd 100644
--- a/chrome/browser/ash/arc/pip/arc_pip_bridge.cc
+++ b/chrome/browser/ash/arc/pip/arc_pip_bridge.cc
@@ -8,13 +8,13 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/ash/arc/pip/arc_picture_in_picture_window_controller_impl.h"
 #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/picture_in_picture_window_controller.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/pip/arc_pip_bridge.h b/chrome/browser/ash/arc/pip/arc_pip_bridge.h
index f01fbf5..7e9162d1c 100644
--- a/chrome/browser/ash/arc/pip/arc_pip_bridge.h
+++ b/chrome/browser/ash/arc/pip/arc_pip_bridge.h
@@ -7,8 +7,8 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "components/arc/mojom/pip.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content {
diff --git a/chrome/browser/ash/arc/pip/arc_pip_bridge_unittest.cc b/chrome/browser/ash/arc/pip/arc_pip_bridge_unittest.cc
index 503fb4e..13609a6 100644
--- a/chrome/browser/ash/arc/pip/arc_pip_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/pip/arc_pip_bridge_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/ash/arc/pip/arc_picture_in_picture_window_controller_impl.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_pip_instance.h"
 #include "chrome/browser/ash/arc/pip/arc_pip_bridge.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge.cc b/chrome/browser/ash/arc/policy/arc_policy_bridge.cc
index 6aafd52c..db69d9c 100644
--- a/chrome/browser/ash/arc/policy/arc_policy_bridge.cc
+++ b/chrome/browser/ash/arc/policy/arc_policy_bridge.cc
@@ -8,6 +8,8 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/guid.h"
@@ -29,8 +31,6 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/network/onc/onc_utils.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/onc/onc_constants.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_namespace.h"
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge.h b/chrome/browser/ash/arc/policy/arc_policy_bridge.h
index ced3634f..0e99a1ec 100644
--- a/chrome/browser/ash/arc/policy/arc_policy_bridge.h
+++ b/chrome/browser/ash/arc/policy/arc_policy_bridge.h
@@ -12,12 +12,12 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
 #include "components/arc/mojom/policy.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/policy/core/common/policy_namespace.h"
 #include "components/policy/core/common/policy_service.h"
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
index f623859c..1e5da4e 100644
--- a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
@@ -10,6 +10,9 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/components/arc/test/fake_policy_instance.h"
@@ -34,9 +37,6 @@
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/upstart/fake_upstart_client.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/policy/core/common/mock_policy_service.h"
diff --git a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc
index b156b9e2..9b93819 100644
--- a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc
+++ b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -18,7 +19,6 @@
 #include "chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.h"
 #include "chrome/browser/ash/arc/print_spooler/print_session_impl.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/filename_util.h"
diff --git a/chrome/browser/ash/arc/process/arc_process_service.cc b/chrome/browser/ash/arc/process/arc_process_service.cc
index 9210c26..79bee4c8 100644
--- a/chrome/browser/ash/arc/process/arc_process_service.cc
+++ b/chrome/browser/ash/arc/process/arc_process_service.cc
@@ -18,6 +18,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/containers/cxx20_erase.h"
 #include "base/containers/flat_set.h"
@@ -35,7 +36,6 @@
 #include "base/trace_event/trace_event.h"
 #include "chrome/browser/ash/process_snapshot_server.h"
 #include "components/arc/mojom/process.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/process/arc_process_service.h b/chrome/browser/ash/arc/process/arc_process_service.h
index 181618c..b5a5393 100644
--- a/chrome/browser/ash/arc/process/arc_process_service.h
+++ b/chrome/browser/ash/arc/process/arc_process_service.h
@@ -10,6 +10,7 @@
 #include <queue>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
@@ -18,7 +19,6 @@
 #include "chrome/browser/ash/arc/process/arc_process.h"
 #include "chrome/browser/ash/process_snapshot_server.h"
 #include "components/arc/mojom/process.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
diff --git a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc
index 3108b13..62efcc73 100644
--- a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc
+++ b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -16,7 +17,6 @@
 #include "base/system/sys_info.h"
 #include "chrome/browser/ash/arc/screen_capture/arc_screen_capture_session.h"
 #include "chrome/browser/media/webrtc/desktop_media_list_ash.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace {
diff --git a/chrome/browser/ash/arc/session/adb_sideloading_availability_delegate_impl.h b/chrome/browser/ash/arc/session/adb_sideloading_availability_delegate_impl.h
index ede4b7e..2b98a90 100644
--- a/chrome/browser/ash/arc/session/adb_sideloading_availability_delegate_impl.h
+++ b/chrome/browser/ash/arc/session/adb_sideloading_availability_delegate_impl.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_IMPL_H_
 #define CHROME_BROWSER_ASH_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_IMPL_H_
 
-#include "components/arc/session/adb_sideloading_availability_delegate.h"
+#include "ash/components/arc/session/adb_sideloading_availability_delegate.h"
 
 #include "chrome/browser/profiles/profile.h"
 
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 a5cba5f..98cedf72 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
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/bind.h"
@@ -30,7 +31,6 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/consent_auditor/fake_consent_auditor.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
diff --git a/chrome/browser/ash/arc/session/arc_provisioning_result.h b/chrome/browser/ash/arc/session/arc_provisioning_result.h
index 0203cfc..86a5fd0 100644
--- a/chrome/browser/ash/arc/session/arc_provisioning_result.h
+++ b/chrome/browser/ash/arc/session/arc_provisioning_result.h
@@ -7,8 +7,8 @@
 
 #include <ostream>
 
+#include "ash/components/arc/session/arc_stop_reason.h"
 #include "components/arc/mojom/auth.mojom.h"
-#include "components/arc/session/arc_stop_reason.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
 
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc
index 4a67dda..e0b925e 100644
--- a/chrome/browser/ash/arc/session/arc_service_launcher.cc
+++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -20,6 +20,7 @@
 #include "ash/components/arc/ime/arc_ime_service.h"
 #include "ash/components/arc/keyboard_shortcut/arc_keyboard_shortcut_bridge.h"
 #include "ash/components/arc/lock_screen/arc_lock_screen_bridge.h"
+#include "ash/components/arc/media_session/arc_media_session_bridge.h"
 #include "ash/components/arc/memory_pressure/arc_memory_pressure_bridge.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
 #include "ash/components/arc/midis/arc_midis_bridge.h"
@@ -32,6 +33,9 @@
 #include "ash/components/arc/rotation_lock/arc_rotation_lock_bridge.h"
 #include "ash/components/arc/sensor/arc_iio_sensor_bridge.h"
 #include "ash/components/arc/sensor/arc_sensor_bridge.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/storage_manager/arc_storage_manager.h"
 #include "ash/components/arc/timer/arc_timer_bridge.h"
 #include "ash/components/arc/usb/usb_host_bridge.h"
@@ -92,10 +96,6 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/common/channel_info.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/media_session/arc_media_session_bridge.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/prefs/pref_member.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.cc b/chrome/browser/ash/arc/session/arc_session_manager.cc
index b882e9b01..a207f47 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager.cc
@@ -13,6 +13,12 @@
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
 #include "ash/components/arc/metrics/stability_metrics_manager.h"
+#include "ash/components/arc/session/arc_data_remover.h"
+#include "ash/components/arc/session/arc_dlc_installer.h"
+#include "ash/components/arc/session/arc_instance_mode.h"
+#include "ash/components/arc/session/arc_management_transition.h"
+#include "ash/components/arc/session/arc_session.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -60,12 +66,6 @@
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_data_remover.h"
-#include "components/arc/session/arc_dlc_installer.h"
-#include "components/arc/session/arc_instance_mode.h"
-#include "components/arc/session/arc_management_transition.h"
-#include "components/arc/session/arc_session.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/exo/wm_helper_chromeos.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
diff --git a/chrome/browser/ash/arc/session/arc_session_manager.h b/chrome/browser/ash/arc/session/arc_session_manager.h
index 4d2b4d6b..979cb1c0 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager.h
+++ b/chrome/browser/ash/arc/session/arc_session_manager.h
@@ -10,6 +10,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_session_runner.h"
+#include "ash/components/arc/session/arc_stop_reason.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
@@ -20,8 +22,6 @@
 #include "chrome/browser/ash/policy/arc/android_management_client.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "components/arc/session/arc_session_runner.h"
-#include "components/arc/session/arc_stop_reason.h"
 #include "components/policy/core/common/policy_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
diff --git a/chrome/browser/ash/arc/session/arc_session_manager_browsertest.cc b/chrome/browser/ash/arc/session/arc_session_manager_browsertest.cc
index 9389fcb..be8d7ca 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager_browsertest.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager_browsertest.cc
@@ -8,6 +8,8 @@
 #include <string>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/auto_reset.h"
@@ -39,8 +41,6 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
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 e5d828ab..f398122 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
@@ -12,6 +12,8 @@
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/constants/ash_switches.h"
@@ -58,8 +60,6 @@
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc
index b93f8e92..1648a49 100644
--- a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc
+++ b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.cc
@@ -5,11 +5,11 @@
 #include "chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h"
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc
index 87da5aa..1d6a720b 100644
--- a/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/ash/arc/sharesheet/arc_sharesheet_bridge.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_sharesheet_instance.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/survey/arc_survey_service_unittest.cc b/chrome/browser/ash/arc/survey/arc_survey_service_unittest.cc
index 09532fa1..1754368 100644
--- a/chrome/browser/ash/arc/survey/arc_survey_service_unittest.cc
+++ b/chrome/browser/ash/arc/survey/arc_survey_service_unittest.cc
@@ -7,10 +7,10 @@
 #include <cstdint>
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/time/time.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/tracing/arc_app_performance_tracing.cc b/chrome/browser/ash/arc/tracing/arc_app_performance_tracing.cc
index 5304496..f6d4b56e 100644
--- a/chrome/browser/ash/arc/tracing/arc_app_performance_tracing.cc
+++ b/chrome/browser/ash/arc/tracing/arc_app_performance_tracing.cc
@@ -7,6 +7,8 @@
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
@@ -21,8 +23,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
 #include "components/exo/wm_helper.h"
diff --git a/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc b/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc
index 2f1323b..4d92eb6 100644
--- a/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc
+++ b/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc
@@ -7,6 +7,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/files/file.h"
@@ -19,8 +21,6 @@
 #include "base/trace_event/trace_config.h"
 #include "base/trace_event/trace_event.h"
 #include "components/arc/mojom/tracing.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/system/platform_handle.h"
diff --git a/chrome/browser/ash/arc/tracing/arc_tracing_bridge.h b/chrome/browser/ash/arc/tracing/arc_tracing_bridge.h
index b097bce..af2f4fb 100644
--- a/chrome/browser/ash/arc/tracing/arc_tracing_bridge.h
+++ b/chrome/browser/ash/arc/tracing/arc_tracing_bridge.h
@@ -10,12 +10,12 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "components/arc/mojom/tracing.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "services/tracing/public/cpp/base_agent.h"
 
diff --git a/chrome/browser/ash/arc/tracing/arc_tracing_bridge_unittest.cc b/chrome/browser/ash/arc/tracing/arc_tracing_bridge_unittest.cc
index 61126e03..aac58a50 100644
--- a/chrome/browser/ash/arc/tracing/arc_tracing_bridge_unittest.cc
+++ b/chrome/browser/ash/arc/tracing/arc_tracing_bridge_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_tracing_instance.h"
 #include "base/bind.h"
@@ -11,7 +12,6 @@
 #include "chrome/browser/ash/arc/tracing/arc_tracing_bridge.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ash/arc/tts/arc_tts_service.cc b/chrome/browser/ash/arc/tts/arc_tts_service.cc
index 0e12c2d..3ac94e8 100644
--- a/chrome/browser/ash/arc/tts/arc_tts_service.cc
+++ b/chrome/browser/ash/arc/tts/arc_tts_service.cc
@@ -7,12 +7,12 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/speech/tts_chromeos.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/tts_controller.h"
 #include "third_party/icu/source/common/unicode/uloc.h"
 
diff --git a/chrome/browser/ash/arc/tts/arc_tts_service_unittest.cc b/chrome/browser/ash/arc/tts/arc_tts_service_unittest.cc
index 184b38e7..396f490 100644
--- a/chrome/browser/ash/arc/tts/arc_tts_service_unittest.cc
+++ b/chrome/browser/ash/arc/tts/arc_tts_service_unittest.cc
@@ -6,12 +6,12 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/threading/platform_thread.h"
 #include "chrome/browser/speech/tts_chromeos.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/browser/tts_controller.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service.cc b/chrome/browser/ash/arc/user_session/arc_user_session_service.cc
index d553e2b..3dd9386b 100644
--- a/chrome/browser/ash/arc/user_session/arc_user_session_service.cc
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service.cc
@@ -5,9 +5,9 @@
 #include "chrome/browser/ash/arc/user_session/arc_user_session_service.h"
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/memory/singleton.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/session_manager/core/session_manager.h"
 
 namespace arc {
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service.h b/chrome/browser/ash/arc/user_session/arc_user_session_service.h
index 96e6407e..7b9251e8 100644
--- a/chrome/browser/ash/arc/user_session/arc_user_session_service.h
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service.h
@@ -5,8 +5,8 @@
 #ifndef CHROME_BROWSER_ASH_ARC_USER_SESSION_ARC_USER_SESSION_SERVICE_H_
 #define CHROME_BROWSER_ASH_ARC_USER_SESSION_ARC_USER_SESSION_SERVICE_H_
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "components/arc/mojom/intent_helper.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/session_manager/core/session_manager_observer.h"
 
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service_browsertest.cc b/chrome/browser/ash/arc/user_session/arc_user_session_service_browsertest.cc
index 23f79c01..62732a14 100644
--- a/chrome/browser/ash/arc/user_session/arc_user_session_service_browsertest.cc
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service_browsertest.cc
@@ -6,14 +6,14 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "base/run_loop.h"
 #include "base/task/current_thread.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_prefs.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc b/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc
index 75f5619..e7897d0 100644
--- a/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc
+++ b/chrome/browser/ash/arc/user_session/arc_user_session_service_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "chrome/browser/ash/arc/user_session/arc_user_session_service.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/video/OWNERS b/chrome/browser/ash/arc/video/OWNERS
index 5d140d09..e6eb205 100644
--- a/chrome/browser/ash/arc/video/OWNERS
+++ b/chrome/browser/ash/arc/video/OWNERS
@@ -1 +1 @@
-file://components/arc/video_accelerator/OWNERS
+file://ash/components/arc/video_accelerator/OWNERS
diff --git a/chrome/browser/ash/arc/video/gpu_arc_video_service_host.cc b/chrome/browser/ash/arc/video/gpu_arc_video_service_host.cc
index 2f83cd6a..06ff90c2 100644
--- a/chrome/browser/ash/arc/video/gpu_arc_video_service_host.cc
+++ b/chrome/browser/ash/arc/video/gpu_arc_video_service_host.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/check_op.h"
 #include "base/location.h"
@@ -18,7 +19,6 @@
 #include "components/arc/mojom/video_decode_accelerator.mojom.h"
 #include "components/arc/mojom/video_encode_accelerator.mojom.h"
 #include "components/arc/mojom/video_protected_buffer_allocator.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/gpu_service_registry.h"
diff --git a/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc b/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc
index e6430f5..876ecbe 100644
--- a/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc
+++ b/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
@@ -17,7 +18,6 @@
 #include "base/task/thread_pool.h"
 #include "chrome/browser/ui/ash/wallpaper_controller_client_impl.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service_unittest.cc b/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service_unittest.cc
index 7d9e710a..b5ecf72a 100644
--- a/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service_unittest.cc
+++ b/chrome/browser/ash/arc/wallpaper/arc_wallpaper_service_unittest.cc
@@ -9,6 +9,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_wallpaper_instance.h"
 #include "ash/constants/ash_pref_names.h"
@@ -22,8 +24,6 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/user_manager/scoped_user_manager.h"
diff --git a/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
index 64f491a..ec87c8b 100644
--- a/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_app_metrics_unittest.cc
@@ -194,16 +194,15 @@
     cache.OnApps(std::move(deltas), apps::mojom::AppType::kUnknown,
                  false /* should_notify_initialized */);
 
-    apps::InstanceRegistry::Instances instances;
     apps::InstanceRegistry& instance_registry =
         apps::AppServiceProxyFactory::GetForProfile(profile())
             ->InstanceRegistry();
     window_ = std::make_unique<aura::Window>(nullptr);
     window_->Init(ui::LAYER_NOT_DRAWN);
-    instances.push_back(std::make_unique<apps::Instance>(
+    auto instance = std::make_unique<apps::Instance>(
         /*app_id=*/"a",
-        apps::Instance::InstanceKey::ForWindowBasedApp(window_.get())));
-    instance_registry.OnInstances(std::move(instances));
+        apps::Instance::InstanceKey::ForWindowBasedApp(window_.get()));
+    instance_registry.OnInstance(std::move(instance));
   }
 
   SupervisedUserService* supervised_user_service() {
diff --git a/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
index d617a40..97a0946 100644
--- a/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
+++ b/chrome/browser/ash/child_accounts/family_user_chrome_activity_metrics_unittest.cc
@@ -137,12 +137,9 @@
         apps::Instance::InstanceKey::ForWindowBasedApp(window));
     instance->UpdateState(state, base::Time::Now());
 
-    std::vector<std::unique_ptr<apps::Instance>> deltas;
-    deltas.push_back(std::move(instance));
-
     apps::AppServiceProxyFactory::GetForProfile(profile())
         ->InstanceRegistry()
-        .OnInstances(std::move(deltas));
+        .OnInstance(std::move(instance));
   }
 
   std::unique_ptr<Browser> CreateBrowserWithAuraWindow() {
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
index 7721389..ba79dcb 100644
--- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc
+++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "ash/components/audio/audio_devices_pref_handler_impl.h"
 #include "ash/components/audio/cras_audio_handler.h"
 #include "ash/components/device_activity/device_activity_controller.h"
@@ -157,11 +158,13 @@
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/metrics/chrome_feature_list_creator.h"
 #include "chrome/browser/metrics/structured/chrome_structured_metrics_recorder.h"
 #include "chrome/browser/net/chrome_network_delegate.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/startup_data.h"
 #include "chrome/browser/task_manager/task_manager_interface.h"
 #include "chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.h"
 #include "chrome/browser/ui/ash/assistant/assistant_state_client.h"
@@ -205,7 +208,6 @@
 #include "chromeos/tpm/install_attributes.h"
 #include "chromeos/tpm/tpm_token_loader.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "components/device_event_log/device_event_log.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/metrics/metrics_service.h"
@@ -292,7 +294,9 @@
 // Wrapper class for initializing D-Bus services and shutting them down.
 class DBusServices {
  public:
-  explicit DBusServices(const content::MainFunctionParams& parameters) {
+  explicit DBusServices(
+      const content::MainFunctionParams& parameters,
+      std::unique_ptr<base::FeatureList::Accessor> feature_list_accessor) {
     PowerPolicyController::Initialize(PowerManagerClient::Get());
 
     dbus::Bus* system_bus = DBusThreadManager::Get()->IsUsingFakes()
@@ -351,7 +355,8 @@
         system_bus, chromeos::kChromeFeaturesServiceName,
         dbus::ObjectPath(chromeos::kChromeFeaturesServicePath),
         CrosDBusService::CreateServiceProviderList(
-            std::make_unique<ChromeFeaturesServiceProvider>()));
+            std::make_unique<ChromeFeaturesServiceProvider>(
+                std::move(feature_list_accessor))));
 
     printers_service_ = CrosDBusService::Create(
         system_bus, chromeos::kPrintersServiceName,
@@ -538,7 +543,11 @@
 ChromeBrowserMainPartsAsh::ChromeBrowserMainPartsAsh(
     content::MainFunctionParams parameters,
     StartupData* startup_data)
-    : ChromeBrowserMainPartsLinux(std::move(parameters), startup_data) {}
+    : ChromeBrowserMainPartsLinux(std::move(parameters), startup_data),
+      feature_list_accessor_(
+          startup_data->chrome_feature_list_creator()
+              ->GetAndClearFeatureListAccessor(
+                  base::PassKey<ChromeBrowserMainPartsAsh>())) {}
 
 ChromeBrowserMainPartsAsh::~ChromeBrowserMainPartsAsh() {
   // To be precise, logout (browser shutdown) is not yet done, but the
@@ -620,7 +629,8 @@
   // (ComponentUpdaterServiceProvider).
   g_browser_process->platform_part()->InitializeCrosComponentManager();
 
-  dbus_services_ = std::make_unique<internal::DBusServices>(parameters());
+  dbus_services_ = std::make_unique<internal::DBusServices>(
+      parameters(), std::move(feature_list_accessor_));
 
   // Need to be done after LoginState has been initialized in DBusServices().
   ::memory::MemoryKillsMonitor::Initialize();
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.h b/chrome/browser/ash/chrome_browser_main_parts_ash.h
index 8e13e77..83dfaef0 100644
--- a/chrome/browser/ash/chrome_browser_main_parts_ash.h
+++ b/chrome/browser/ash/chrome_browser_main_parts_ash.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/feature_list.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "chrome/browser/ash/external_metrics.h"
 // TODO(https://crbug.com/1164001): remove and use forward declaration.
@@ -253,6 +254,11 @@
 
   std::unique_ptr<quick_pair::QuickPairBrowserDelegateImpl>
       quick_pair_delegate_;
+
+  // Only temporarily owned, will be null after PostCreateMainMessageLoop().
+  // The Accessor is constructed before initialization of FeatureList and should
+  // only be used by ChromeFeaturesServiceProvider.
+  std::unique_ptr<base::FeatureList::Accessor> feature_list_accessor_;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.cc b/chrome/browser/ash/crosapi/test_controller_ash.cc
index 80b4f486..ef281f8 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.cc
+++ b/chrome/browser/ash/crosapi/test_controller_ash.cc
@@ -17,6 +17,9 @@
 #include "base/task/post_task.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ash/crosapi/window_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -272,6 +275,20 @@
   std::move(callback).Run(std::move(items));
 }
 
+void TestControllerAsh::GetOpenAshBrowserWindows(
+    GetOpenAshBrowserWindowsCallback callback) {
+  std::move(callback).Run(BrowserList::GetInstance()->size());
+}
+
+void TestControllerAsh::CloseAllBrowserWindows(
+    CloseAllBrowserWindowsCallback callback) {
+  for (auto* browser : *BrowserList::GetInstance()) {
+    browser->window()->Close();
+  }
+
+  std::move(callback).Run(/*success*/ true);
+}
+
 // This class waits for overview mode to either enter or exit and fires a
 // callback. This class will fire the callback at most once.
 class TestControllerAsh::OverviewWaiter : public ash::OverviewObserver {
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.h b/chrome/browser/ash/crosapi/test_controller_ash.h
index a758701..719e2d0 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.h
+++ b/chrome/browser/ash/crosapi/test_controller_ash.h
@@ -57,6 +57,9 @@
                       uint8_t pointer_id,
                       const gfx::PointF& location_in_window,
                       SendTouchEventCallback cb) override;
+  void GetOpenAshBrowserWindows(
+      GetOpenAshBrowserWindowsCallback callback) override;
+  void CloseAllBrowserWindows(CloseAllBrowserWindowsCallback callback) override;
 
  private:
   class OverviewWaiter;
diff --git a/chrome/browser/ash/dbus/chrome_features_service_provider.cc b/chrome/browser/ash/dbus/chrome_features_service_provider.cc
index fbb0b52..173d20b1 100644
--- a/chrome/browser/ash/dbus/chrome_features_service_provider.cc
+++ b/chrome/browser/ash/dbus/chrome_features_service_provider.cc
@@ -80,7 +80,9 @@
 
 namespace ash {
 
-ChromeFeaturesServiceProvider::ChromeFeaturesServiceProvider() {}
+ChromeFeaturesServiceProvider::ChromeFeaturesServiceProvider(
+    std::unique_ptr<base::FeatureList::Accessor> feature_list_accessor)
+    : feature_list_accessor_(std::move(feature_list_accessor)) {}
 
 ChromeFeaturesServiceProvider::~ChromeFeaturesServiceProvider() = default;
 
@@ -201,8 +203,6 @@
     return;
   }
   // Not on our list. Potentially look up by name instead.
-  base::FeatureList* features = base::FeatureList::GetInstance();
-  base::FieldTrial* trial = nullptr;
   // Only search for arbitrary trial names that begin with the appropriate
   // prefix, since looking up a feature by name will not be able to get the
   // default value associated with any `base::Feature` defined in the code
@@ -210,20 +210,20 @@
   // Separately, a presubmit will enforce that no `base::Feature` definition
   // has a name starting with this prefix.
   // TODO(https://crbug.com/1263068): Add the aforementioned presubmit.
+  base::FeatureList::OverrideState state =
+      base::FeatureList::OVERRIDE_USE_DEFAULT;
   if (feature_name.find(kCrOSLateBootFeaturePrefix) == 0) {
-    trial = features->GetAssociatedFieldTrialByFeatureName(feature_name);
+    state = feature_list_accessor_->GetOverrideStateByFeatureName(feature_name);
   }
-  if (!trial) {
+  if (state == base::FeatureList::OVERRIDE_USE_DEFAULT) {
     LOG(ERROR) << "Unexpected feature name '" << feature_name << "'";
     std::move(response_sender)
         .Run(dbus::ErrorResponse::FromMethodCall(
             method_call, DBUS_ERROR_INVALID_ARGS, "Unexpected feature name."));
     return;
   }
-  bool enabled = features->GetEnabledFieldTrialByFeatureName(feature_name);
-  // Call group() so that the field trial will be reported as active.
-  trial->group();
-  SendResponse(method_call, std::move(response_sender), enabled);
+  SendResponse(method_call, std::move(response_sender),
+               state == base::FeatureList::OVERRIDE_ENABLE_FEATURE);
 }
 
 void ChromeFeaturesServiceProvider::IsCrostiniEnabled(
diff --git a/chrome/browser/ash/dbus/chrome_features_service_provider.h b/chrome/browser/ash/dbus/chrome_features_service_provider.h
index 9023a48..a0daf5b 100644
--- a/chrome/browser/ash/dbus/chrome_features_service_provider.h
+++ b/chrome/browser/ash/dbus/chrome_features_service_provider.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_ASH_DBUS_CHROME_FEATURES_SERVICE_PROVIDER_H_
 #define CHROME_BROWSER_ASH_DBUS_CHROME_FEATURES_SERVICE_PROVIDER_H_
 
+#include "base/feature_list.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/dbus/services/cros_dbus_service.h"
@@ -45,7 +46,8 @@
 class ChromeFeaturesServiceProvider
     : public CrosDBusService::ServiceProviderInterface {
  public:
-  ChromeFeaturesServiceProvider();
+  explicit ChromeFeaturesServiceProvider(
+      std::unique_ptr<base::FeatureList::Accessor> feature_list_accessor);
 
   ChromeFeaturesServiceProvider(const ChromeFeaturesServiceProvider&) = delete;
   ChromeFeaturesServiceProvider& operator=(
@@ -88,6 +90,9 @@
   void IsDnsProxyEnabled(dbus::MethodCall* method_call,
                          dbus::ExportedObject::ResponseSender response_sender);
 
+  // Provides a way to look up features by _name_ rather than by base::Feature.
+  std::unique_ptr<base::FeatureList::Accessor> feature_list_accessor_;
+
   // Keep this last so that all weak pointers will be invalidated at the
   // beginning of destruction.
   base::WeakPtrFactory<ChromeFeaturesServiceProvider> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/file_manager/arc_file_tasks.cc b/chrome/browser/ash/file_manager/arc_file_tasks.cc
index e14a12d3..60be9d59 100644
--- a/chrome/browser/ash/file_manager/arc_file_tasks.cc
+++ b/chrome/browser/ash/file_manager/arc_file_tasks.cc
@@ -11,6 +11,8 @@
 
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/files/file_path.h"
@@ -32,8 +34,6 @@
 #include "components/arc/intent_helper/intent_constants.h"
 #include "components/arc/mojom/file_system.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/entry_info.h"
 #include "storage/browser/file_system/file_system_context.h"
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task.cc
index d142f5de..02958a2 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task.cc
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task.cc
@@ -168,8 +168,14 @@
   base::FilePath my_files_path =
       file_manager::util::GetMyFilesFolderForProfile(profile_);
   base::FilePath downloads_path = my_files_path.Append("Downloads");
-  return downloads_path.IsParent(source_url.path()) !=
-         downloads_path.IsParent(destination_url.path());
+
+  bool source_in_downloads = downloads_path.IsParent(source_url.path());
+  // The destination_url can be the destination folder, so Downloads is a valid
+  // destination.
+  bool destination_in_downloads =
+      downloads_path == destination_url.path() ||
+      downloads_path.IsParent(destination_url.path());
+  return source_in_downloads != destination_in_downloads;
 }
 
 void CopyOrMoveIOTask::Execute(IOTask::ProgressCallback progress_callback,
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc
index f0d7a8a..c5bcbecf 100644
--- a/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc
+++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_unittest.cc
@@ -455,7 +455,7 @@
   ASSERT_TRUE(IsCrossFileSystem(source_path, destination_path));
 
   source_path = downloads_volume_path_.Append("a.txt");
-  destination_path = test_volume_path_.Append("a.txt");
+  destination_path = test_volume_path_;
   ASSERT_TRUE(IsCrossFileSystem(source_path, destination_path));
 }
 
@@ -465,7 +465,7 @@
   ASSERT_FALSE(IsCrossFileSystem(source_path, destination_path));
 
   source_path = test_volume_path_.Append("a/b.txt");
-  destination_path = test_volume_path_.Append("b.txt");
+  destination_path = test_volume_path_;
   ASSERT_FALSE(IsCrossFileSystem(source_path, destination_path));
 }
 
@@ -478,7 +478,7 @@
   ASSERT_FALSE(IsCrossFileSystem(source_path, destination_path));
 
   source_path = downloads_volume_path_.Append("a.txt");
-  destination_path = downloads_volume_path_.Append("Downloadss/a.txt");
+  destination_path = downloads_volume_path_.Append("Downloadss");
   ASSERT_FALSE(IsCrossFileSystem(source_path, destination_path));
 }
 
@@ -489,7 +489,7 @@
   ASSERT_TRUE(IsCrossFileSystem(source_path, destination_path));
 
   source_path = downloads_volume_path_.Append("a/b.txt");
-  destination_path = downloads_volume_path_.Append("Downloads/b.txt");
+  destination_path = downloads_volume_path_.Append("Downloads");
   ASSERT_TRUE(IsCrossFileSystem(source_path, destination_path));
 }
 
@@ -499,18 +499,18 @@
   ASSERT_TRUE(IsCrossFileSystem(source_path, destination_path));
 
   source_path = downloads_volume_path_.Append("Downloads/a/b.txt");
-  destination_path = downloads_volume_path_.Append("b.txt");
+  destination_path = downloads_volume_path_;
   ASSERT_TRUE(IsCrossFileSystem(source_path, destination_path));
 }
 
 TEST_F(CopyOrMoveIsCrossFileSystemTest, DownloadsToDownloads) {
   base::FilePath source_path = downloads_volume_path_.Append("Downloads/a.txt");
   base::FilePath destination_path =
-      downloads_volume_path_.Append("Downloads/b/a.txt");
+      downloads_volume_path_.Append("Downloads/b/a (1).txt");
   ASSERT_FALSE(IsCrossFileSystem(source_path, destination_path));
 
   source_path = downloads_volume_path_.Append("Downloads/a.txt");
-  destination_path = downloads_volume_path_.Append("Downloads/a (1).txt");
+  destination_path = downloads_volume_path_.Append("Downloads");
   ASSERT_FALSE(IsCrossFileSystem(source_path, destination_path));
 }
 
diff --git a/chrome/browser/ash/file_manager/documents_provider_root_manager_unittest.cc b/chrome/browser/ash/file_manager/documents_provider_root_manager_unittest.cc
index 4b812843..da370fb46 100644
--- a/chrome/browser/ash/file_manager/documents_provider_root_manager_unittest.cc
+++ b/chrome/browser/ash/file_manager/documents_provider_root_manager_unittest.cc
@@ -7,13 +7,13 @@
 #include <vector>
 
 #include "ash/components/arc/arc_features.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/browser/ash/file_manager/documents_provider_root_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
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 bbe8ed4..35dab969 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -12,6 +12,8 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
@@ -94,8 +96,6 @@
 #include "chromeos/dbus/cros_disks/fake_cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/disks/mount_point.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/drive/drive_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ash/file_manager/filesystem_api_util.cc b/chrome/browser/ash/file_manager/filesystem_api_util.cc
index aa7903a..3c03465 100644
--- a/chrome/browser/ash/file_manager/filesystem_api_util.cc
+++ b/chrome/browser/ash/file_manager/filesystem_api_util.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file.h"
@@ -22,7 +23,6 @@
 #include "chrome/browser/ash/file_system_provider/provided_file_system_interface.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/drive/file_errors.h"
 #include "components/drive/file_system_core_util.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/ash/file_manager/path_util_unittest.cc b/chrome/browser/ash/file_manager/path_util_unittest.cc
index 3364673..4fd27b5 100644
--- a/chrome/browser/ash/file_manager/path_util_unittest.cc
+++ b/chrome/browser/ash/file_manager/path_util_unittest.cc
@@ -8,6 +8,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -36,8 +38,6 @@
 #include "chromeos/dbus/seneschal/seneschal_client.h"
 #include "chromeos/disks/disk.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/drive/drive_pref_names.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/first_run/first_run.cc b/chrome/browser/ash/first_run/first_run.cc
index ea6de9a..0e09347 100644
--- a/chrome/browser/ash/first_run/first_run.cc
+++ b/chrome/browser/ash/first_run/first_run.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ash/first_run/first_run.h"
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/tablet_mode.h"
 #include "base/command_line.h"
@@ -25,7 +26,6 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/login/login_state/login_state.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
index edfa59b4..02378f2 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ash/guest_os/guest_os_share_path.h"
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/bind.h"
 #include "base/files/file_path.h"
@@ -39,7 +40,6 @@
 #include "chromeos/dbus/seneschal/seneschal_service.pb.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/drive/drive_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
diff --git a/chrome/browser/ash/input_method/ui/colors.cc b/chrome/browser/ash/input_method/ui/colors.cc
new file mode 100644
index 0000000..2ad384cc
--- /dev/null
+++ b/chrome/browser/ash/input_method/ui/colors.cc
@@ -0,0 +1,26 @@
+// 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/input_method/ui/colors.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/public/cpp/style/color_provider.h"
+
+namespace ui {
+namespace ime {
+
+bool IsDarkModeEnabled() {
+  auto* provider = ash::ColorProvider::Get();
+  if (!provider)
+    return false;
+  return (ash::features::IsDarkLightModeEnabled() &&
+          provider->IsDarkModeEnabled());
+}
+
+SkColor ResolveSemanticColor(const cros_styles::ColorName& color_name) {
+  return cros_styles::ResolveColor(color_name, IsDarkModeEnabled(), false);
+}
+
+}  // namespace ime
+}  // namespace ui
diff --git a/chrome/browser/ash/input_method/ui/colors.h b/chrome/browser/ash/input_method/ui/colors.h
new file mode 100644
index 0000000..a981069
--- /dev/null
+++ b/chrome/browser/ash/input_method/ui/colors.h
@@ -0,0 +1,18 @@
+// 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_INPUT_METHOD_UI_COLORS_H_
+#define CHROME_BROWSER_ASH_INPUT_METHOD_UI_COLORS_H_
+
+#include "ui/chromeos/styles/cros_styles.h"
+
+namespace ui {
+namespace ime {
+
+SkColor ResolveSemanticColor(const cros_styles::ColorName& color_name);
+
+}  // namespace ime
+}  // namespace ui
+
+#endif  // CHROME_BROWSER_ASH_INPUT_METHOD_UI_COLORS_H_
diff --git a/chrome/browser/ash/input_method/ui/grammar_suggestion_window.cc b/chrome/browser/ash/input_method/ui/grammar_suggestion_window.cc
index e6e0502e..aecb0e1 100644
--- a/chrome/browser/ash/input_method/ui/grammar_suggestion_window.cc
+++ b/chrome/browser/ash/input_method/ui/grammar_suggestion_window.cc
@@ -5,8 +5,10 @@
 #include "chrome/browser/ash/input_method/ui/grammar_suggestion_window.h"
 
 #include "chrome/browser/ash/input_method/ui/border_factory.h"
+#include "chrome/browser/ash/input_method/ui/colors.h"
 #include "chrome/browser/ash/input_method/ui/suggestion_details.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/chromeos/styles/cros_styles.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_border.h"
@@ -21,7 +23,6 @@
 
 namespace {
 
-constexpr SkColor kGrammarColor = gfx::kGoogleGrey700;
 constexpr int kGrammarPaddingSize = 4;
 constexpr float kSuggestionBorderRadius = 2;
 // Large enough to make the background a circle.
@@ -81,10 +82,10 @@
 
   // Highlights buttons when they are hovered or pressed.
   const auto update_button_highlight = [](views::Button* button) {
-    button->SetBackground(
-        ShouldHighlight(*button)
-            ? views::CreateSolidBackground(kButtonHighlightColor)
-            : nullptr);
+    button->SetBackground(ShouldHighlight(*button)
+                              ? views::CreateSolidBackground(
+                                    ResolveSemanticColor(kButtonHighlightColor))
+                              : nullptr);
   };
   subscriptions_.insert(
       {suggestion_button_,
@@ -105,7 +106,9 @@
 
   ignore_button_->SetImage(
       views::Button::ButtonState::STATE_NORMAL,
-      gfx::CreateVectorIcon(views::kCloseIcon, kGrammarColor));
+      gfx::CreateVectorIcon(
+          views::kCloseIcon,
+          ResolveSemanticColor(cros_styles::ColorName::kTextColorPrimary)));
 
   BubbleDialogDelegateView::OnThemeChanged();
 }
@@ -131,10 +134,7 @@
 }
 
 void GrammarSuggestionWindow::SetSuggestion(const std::u16string& suggestion) {
-  suggestion_button_->SetView(SuggestionDetails{
-      .text = suggestion,
-      .text_color = kGrammarColor,
-  });
+  suggestion_button_->SetView(SuggestionDetails{.text = suggestion});
 }
 
 void GrammarSuggestionWindow::SetButtonHighlighted(
@@ -151,11 +151,12 @@
     switch (button.id) {
       case ButtonId::kSuggestion:
         suggestion_button_->SetBackground(views::CreateRoundedRectBackground(
-            kButtonHighlightColor, kSuggestionBorderRadius));
+            ResolveSemanticColor(kButtonHighlightColor),
+            kSuggestionBorderRadius));
         break;
       case ButtonId::kIgnoreSuggestion:
         ignore_button_->SetBackground(views::CreateRoundedRectBackground(
-            kButtonHighlightColor, kIconBorderRadius));
+            ResolveSemanticColor(kButtonHighlightColor), kIconBorderRadius));
         break;
       default:
         break;
diff --git a/chrome/browser/ash/input_method/ui/suggestion_details.h b/chrome/browser/ash/input_method/ui/suggestion_details.h
index 71c9e05..214915b 100644
--- a/chrome/browser/ash/input_method/ui/suggestion_details.h
+++ b/chrome/browser/ash/input_method/ui/suggestion_details.h
@@ -7,28 +7,21 @@
 
 #include <string>
 
-#include "ui/gfx/color_palette.h"
-
 namespace ui {
 namespace ime {
 
-constexpr SkColor kDefaultSuggestionTextColor =
-    SkColorSetA(gfx::kGoogleGrey700, 0xB3);  // 70% opacity
-
 struct SuggestionDetails {
   std::u16string text;
   size_t confirmed_length = 0;
   bool show_accept_annotation = false;
   bool show_quick_accept_annotation = false;
   bool show_setting_link = false;
-  SkColor text_color = kDefaultSuggestionTextColor;
 
   bool operator==(const SuggestionDetails& other) const {
     return text == other.text && confirmed_length == other.confirmed_length &&
            show_accept_annotation == other.show_accept_annotation &&
            show_quick_accept_annotation == other.show_quick_accept_annotation &&
-           show_setting_link == other.show_setting_link &&
-           text_color == other.text_color;
+           show_setting_link == other.show_setting_link;
   }
 };
 
diff --git a/chrome/browser/ash/input_method/ui/suggestion_view.cc b/chrome/browser/ash/input_method/ui/suggestion_view.cc
index 471e8700..95255cf9 100644
--- a/chrome/browser/ash/input_method/ui/suggestion_view.cc
+++ b/chrome/browser/ash/input_method/ui/suggestion_view.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ash/input_method/ui/colors.h"
 #include "chrome/browser/ash/input_method/ui/suggestion_details.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/accessibility/ax_enums.mojom.h"
@@ -40,7 +41,8 @@
   index_label->SetFontList(gfx::FontList({kFontStyle}, gfx::Font::NORMAL,
                                          kIndexFontSize,
                                          gfx::Font::Weight::MEDIUM));
-  index_label->SetEnabledColor(kSuggestionColor);
+  index_label->SetEnabledColor(
+      ResolveSemanticColor(cros_styles::ColorName::kTextColorSecondary));
   index_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
   index_label->SetBorder(
       views::CreateEmptyBorder(gfx::Insets(kPadding / 2, 0)));
@@ -71,7 +73,8 @@
 
 std::unique_ptr<views::Label> CreateEnterLabel() {
   auto label = std::make_unique<views::Label>();
-  label->SetEnabledColor(kSuggestionColor);
+  label->SetEnabledColor(
+      ResolveSemanticColor(cros_styles::ColorName::kTextColorSecondary));
   label->SetText(l10n_util::GetStringUTF16(IDS_SUGGESTION_ENTER_KEY));
   label->SetFontList(gfx::FontList({kFontStyle}, gfx::Font::NORMAL,
                                    kAnnotationFontSize,
@@ -83,7 +86,8 @@
 
 std::unique_ptr<views::Label> CreateTabLabel() {
   auto label = std::make_unique<views::Label>();
-  label->SetEnabledColor(kSuggestionColor);
+  label->SetEnabledColor(
+      ResolveSemanticColor(cros_styles::ColorName::kTextColorPrimary));
   label->SetText(l10n_util::GetStringUTF16(IDS_SUGGESTION_TAB_KEY));
   label->SetFontList(gfx::FontList({kFontStyle}, gfx::Font::NORMAL,
                                    kAnnotationFontSize,
@@ -170,7 +174,7 @@
 }
 
 void SuggestionView::SetView(const SuggestionDetails& details) {
-  SetSuggestionText(details.text, details.confirmed_length, details.text_color);
+  SetSuggestionText(details.text, details.confirmed_length);
   suggestion_width_ = suggestion_label_->GetPreferredSize().width();
   down_and_enter_annotation_label_->SetVisible(details.show_accept_annotation);
   tab_annotation_label_->SetVisible(details.show_quick_accept_annotation);
@@ -188,8 +192,7 @@
 }
 
 void SuggestionView::SetSuggestionText(const std::u16string& text,
-                                       const size_t confirmed_length,
-                                       SkColor text_color) {
+                                       const size_t confirmed_length) {
   // SetText clears the existing style only if the text to set is different from
   // the previous one.
   suggestion_label_->SetText(base::EmptyString16());
@@ -200,14 +203,16 @@
   if (confirmed_length != 0) {
     views::StyledLabel::RangeStyleInfo confirmed_style;
     confirmed_style.custom_font = kSuggestionFont;
-    confirmed_style.override_color = kConfirmedTextColor;
+    confirmed_style.override_color =
+        ResolveSemanticColor(cros_styles::ColorName::kTextColorPrimary);
     suggestion_label_->AddStyleRange(gfx::Range(0, confirmed_length),
                                      confirmed_style);
   }
 
   views::StyledLabel::RangeStyleInfo suggestion_style;
   suggestion_style.custom_font = kSuggestionFont;
-  suggestion_style.override_color = text_color;
+  suggestion_style.override_color =
+      ResolveSemanticColor(cros_styles::ColorName::kTextColorDisabled);
   suggestion_label_->AddStyleRange(gfx::Range(confirmed_length, text.length()),
                                    suggestion_style);
 
@@ -225,7 +230,8 @@
   if (highlighted) {
     NotifyAccessibilityEvent(ax::mojom::Event::kSelection, false);
     // TODO(crbug/1099044): Use System Color for button highlight.
-    SetBackground(views::CreateSolidBackground(kButtonHighlightColor));
+    SetBackground(views::CreateSolidBackground(
+        ResolveSemanticColor(kButtonHighlightColor)));
   } else {
     SetBackground(nullptr);
   }
diff --git a/chrome/browser/ash/input_method/ui/suggestion_view.h b/chrome/browser/ash/input_method/ui/suggestion_view.h
index 787f17c4..64f26d1 100644
--- a/chrome/browser/ash/input_method/ui/suggestion_view.h
+++ b/chrome/browser/ash/input_method/ui/suggestion_view.h
@@ -7,6 +7,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/chromeos/styles/cros_styles.h"
 #include "ui/chromeos/ui_chromeos_export.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/label.h"
@@ -37,11 +38,8 @@
 constexpr int kAnnotationPaddingBottom = 16;
 constexpr int kAnnotationPaddingTop = 6;
 constexpr char kTabKey[] = "tab";
-constexpr SkColor kConfirmedTextColor = gfx::kGoogleGrey900;
-constexpr SkColor kSuggestionColor =
-    SkColorSetA(gfx::kGoogleGrey700, 0xB3);  // 70% opacity
-constexpr SkColor kButtonHighlightColor =
-    SkColorSetA(SK_ColorBLACK, 0x0F);  // 6% Black.
+constexpr cros_styles::ColorName kButtonHighlightColor =
+    cros_styles::ColorName::kRippleColor;
 
 // SuggestionView renders a suggestion.
 class UI_CHROMEOS_EXPORT SuggestionView : public views::Button {
@@ -78,8 +76,7 @@
   // child views will be deleted when |this| is deleted.
 
   void SetSuggestionText(const std::u16string& text,
-                         const size_t confirmed_length,
-                         SkColor text_color);
+                         const size_t confirmed_length);
 
   views::Label* index_label_ = nullptr;
   // The suggestion label renders suggestions.
diff --git a/chrome/browser/ash/input_method/ui/suggestion_window_view.cc b/chrome/browser/ash/input_method/ui/suggestion_window_view.cc
index e4fc659..59f9a5a 100644
--- a/chrome/browser/ash/input_method/ui/suggestion_window_view.cc
+++ b/chrome/browser/ash/input_method/ui/suggestion_window_view.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ash/input_method/assistive_window_properties.h"
 #include "chrome/browser/ash/input_method/ui/assistive_delegate.h"
 #include "chrome/browser/ash/input_method/ui/border_factory.h"
+#include "chrome/browser/ash/input_method/ui/colors.h"
 #include "chrome/browser/ash/input_method/ui/suggestion_details.h"
 #include "chrome/browser/ash/input_method/ui/suggestion_view.h"
 #include "chrome/grit/generated_resources.h"
@@ -56,7 +57,8 @@
 void SetHighlighted(views::View& view, bool highlighted) {
   if (!!view.background() != highlighted) {
     view.SetBackground(highlighted
-                           ? views::CreateSolidBackground(kButtonHighlightColor)
+                           ? views::CreateSolidBackground(
+                                 ResolveSemanticColor(kButtonHighlightColor))
                            : nullptr);
   }
 }
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 d6ce734..7304ce7 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
@@ -9,6 +9,8 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/files/file_path.h"
@@ -33,8 +35,6 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/browser/disable_reason.h"
 #include "extensions/browser/extension_file_task_runner.h"
diff --git a/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc b/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
index f5ebc1b..16def46 100644
--- a/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
@@ -8,6 +8,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/command_line.h"
@@ -33,8 +35,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session.h"
 #include "components/crx_file/id_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
diff --git a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
index b3d5e382..13d8fe2b 100644
--- a/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
+++ b/chrome/browser/ash/lock_screen_apps/state_controller_unittest.cc
@@ -9,6 +9,8 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/mojom/tray_action.mojom.h"
 #include "ash/session/test_session_controller_client.h"
@@ -41,8 +43,6 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ash/login/existing_user_controller.cc b/chrome/browser/ash/login/existing_user_controller.cc
index a348aa5..3ea1e4b3 100644
--- a/chrome/browser/ash/login/existing_user_controller.cc
+++ b/chrome/browser/ash/login/existing_user_controller.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "ash/components/settings/cros_settings_names.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/constants/ash_switches.h"
@@ -97,7 +98,6 @@
 #include "chromeos/login/session/session_termination_manager.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "components/google/core/common/google_util.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/login/existing_user_controller_browsertest.cc b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
index 57a9712..3118517d 100644
--- a/chrome/browser/ash/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
@@ -5,6 +5,7 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/settings/cros_settings_names.h"
 #include "ash/components/settings/cros_settings_provider.h"
@@ -72,7 +73,6 @@
 #include "chromeos/network/network_state_test_helper.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
diff --git a/chrome/browser/ash/login/oobe_interactive_ui_test.cc b/chrome/browser/ash/login/oobe_interactive_ui_test.cc
index 7160e26..8df0e467 100644
--- a/chrome/browser/ash/login/oobe_interactive_ui_test.cc
+++ b/chrome/browser/ash/login/oobe_interactive_ui_test.cc
@@ -4,6 +4,8 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/components/attestation/attestation_flow_utils.h"
@@ -59,8 +61,6 @@
 #include "chromeos/assistant/buildflags.h"
 #include "chromeos/dbus/update_engine/update_engine_client.h"
 #include "chromeos/system/fake_statistics_provider.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/ash/login/screens/management_transition_screen_browsertest.cc b/chrome/browser/ash/login/screens/management_transition_screen_browsertest.cc
index 3ed954c..e63276ca 100644
--- a/chrome/browser/ash/login/screens/management_transition_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/management_transition_screen_browsertest.cc
@@ -7,6 +7,8 @@
 
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_management_transition.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/login_screen_test_api.h"
@@ -25,8 +27,6 @@
 #include "chrome/browser/ui/webui/chromeos/login/management_transition_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "components/arc/session/arc_management_transition.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_type.h"
diff --git a/chrome/browser/ash/login/session/user_session_manager.cc b/chrome/browser/ash/login/session/user_session_manager.cc
index f73f81b..0a2d6c68 100644
--- a/chrome/browser/ash/login/session/user_session_manager.cc
+++ b/chrome/browser/ash/login/session/user_session_manager.cc
@@ -2305,13 +2305,13 @@
 void UserSessionManager::LaunchBrowser(Profile* profile) {
   StartupBrowserCreator browser_creator;
   chrome::startup::IsFirstRun first_run =
-      ::first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                      : chrome::startup::IS_NOT_FIRST_RUN;
+      ::first_run::IsChromeFirstRun() ? chrome::startup::IsFirstRun::kYes
+                                      : chrome::startup::IsFirstRun::kNo;
 
-  browser_creator.LaunchBrowser(*base::CommandLine::ForCurrentProcess(),
-                                profile, base::FilePath(),
-                                chrome::startup::IS_PROCESS_STARTUP, first_run,
-                                std::make_unique<LaunchModeRecorder>());
+  browser_creator.LaunchBrowser(
+      *base::CommandLine::ForCurrentProcess(), profile, base::FilePath(),
+      chrome::startup::IsProcessStartup::kYes, first_run,
+      std::make_unique<LaunchModeRecorder>());
 }
 
 // static
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index 67319ff..f551fa5 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -16,6 +16,7 @@
 
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/components/audio/cras_audio_handler.h"
 #include "ash/components/geolocation/simple_geolocation_provider.h"
 #include "ash/components/settings/cros_settings_names.h"
@@ -184,7 +185,6 @@
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
 #include "chromeos/services/rollback_network_config/public/mojom/rollback_network_config.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "components/crash/core/app/breakpad_linux.h"
 #include "components/crash/core/app/crashpad.h"
 #include "components/metrics/structured/neutrino_logging.h"
diff --git a/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.cc b/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.cc
index 4412003c..61f79af 100644
--- a/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.cc
+++ b/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.cc
@@ -5,10 +5,10 @@
 #include <algorithm>
 #include <utility>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics_util.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "net/dns/public/dns_protocol.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.h b/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.h
index 78dd48d..3bd0b49 100644
--- a/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.h
+++ b/chrome/browser/ash/net/network_diagnostics/arc_dns_resolution_routine.h
@@ -8,10 +8,10 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics_routine.h"
 #include "components/arc/mojom/net.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace chromeos {
 namespace network_diagnostics {
diff --git a/chrome/browser/ash/net/network_diagnostics/arc_http_routine.cc b/chrome/browser/ash/net/network_diagnostics/arc_http_routine.cc
index fd74c49..5db5b9c 100644
--- a/chrome/browser/ash/net/network_diagnostics/arc_http_routine.cc
+++ b/chrome/browser/ash/net/network_diagnostics/arc_http_routine.cc
@@ -5,10 +5,10 @@
 #include <algorithm>
 #include <utility>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/net/network_diagnostics/arc_http_routine.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics_util.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "net/http/http_status_code.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/ash/net/network_diagnostics/arc_http_routine.h b/chrome/browser/ash/net/network_diagnostics/arc_http_routine.h
index 224561c..cd5098e 100644
--- a/chrome/browser/ash/net/network_diagnostics/arc_http_routine.h
+++ b/chrome/browser/ash/net/network_diagnostics/arc_http_routine.h
@@ -7,10 +7,10 @@
 
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics_routine.h"
 #include "components/arc/mojom/net.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 
 namespace chromeos {
 namespace network_diagnostics {
diff --git a/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.cc b/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.cc
index 7acc115..abc2a6b1 100644
--- a/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.cc
+++ b/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.cc
@@ -6,12 +6,12 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/net/network_diagnostics/arc_ping_routine.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics_util.h"
 #include "chromeos/services/network_config/in_process_instance.h"
 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace chromeos {
 namespace network_diagnostics {
diff --git a/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.h b/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.h
index 983b6ec..8df3da7c 100644
--- a/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.h
+++ b/chrome/browser/ash/net/network_diagnostics/arc_ping_routine.h
@@ -8,11 +8,11 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/net/network_diagnostics/network_diagnostics_routine.h"
 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
 #include "components/arc/mojom/net.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ash/note_taking_helper.cc b/chrome/browser/ash/note_taking_helper.cc
index 14b2cc9..f9446ce 100644
--- a/chrome/browser/ash/note_taking_helper.cc
+++ b/chrome/browser/ash/note_taking_helper.cc
@@ -10,6 +10,9 @@
 #include "apps/launcher.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/stylus_utils.h"
 #include "base/bind.h"
@@ -39,9 +42,6 @@
 #include "components/arc/mojom/file_system.mojom.h"
 #include "components/arc/mojom/intent_common.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_update.h"
diff --git a/chrome/browser/ash/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking_helper_unittest.cc
index b198ace..6861ad5a 100644
--- a/chrome/browser/ash/note_taking_helper_unittest.cc
+++ b/chrome/browser/ash/note_taking_helper_unittest.cc
@@ -8,6 +8,9 @@
 #include <utility>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "ash/constants/ash_switches.h"
@@ -52,9 +55,6 @@
 #include "components/arc/mojom/file_system.mojom.h"
 #include "components/arc/mojom/intent_common.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/crx_file/id_util.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager.cc b/chrome/browser/ash/policy/dlp/dlp_content_manager.cc
index 592a730..c91e2a6 100644
--- a/chrome/browser/ash/policy/dlp/dlp_content_manager.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_content_manager.cc
@@ -144,28 +144,6 @@
   CheckScreenCaptureRestriction(info, std::move(callback));
 }
 
-bool DlpContentManager::IsVideoCaptureRestricted(const ScreenshotArea& area) {
-  const ConfidentialContentsInfo info = GetAreaConfidentialContentsInfo(
-      area, DlpContentRestriction::kVideoCapture);
-  MaybeReportEvent(info.restriction_info,
-                   DlpRulesManager::Restriction::kScreenshot);
-  DlpBooleanHistogram(dlp::kVideoCaptureBlockedUMA,
-                      IsBlocked(info.restriction_info));
-  return IsBlocked(info.restriction_info);
-}
-
-void DlpContentManager::CheckVideoCaptureRestriction(
-    const ScreenshotArea& area,
-    ash::OnCaptureModeDlpRestrictionChecked callback) {
-  const ConfidentialContentsInfo info = GetAreaConfidentialContentsInfo(
-      area, DlpContentRestriction::kVideoCapture);
-  MaybeReportEvent(info.restriction_info,
-                   DlpRulesManager::Restriction::kScreenshot);
-  DlpBooleanHistogram(dlp::kVideoCaptureBlockedUMA,
-                      IsBlocked(info.restriction_info));
-  CheckScreenCaptureRestriction(info, std::move(callback));
-}
-
 void DlpContentManager::CheckPrintingRestriction(
     content::WebContents* web_contents,
     OnDlpRestrictionCheckedCallback callback) {
@@ -246,7 +224,7 @@
 }
 
 void DlpContentManager::OnVideoCaptureStarted(const ScreenshotArea& area) {
-  if (IsVideoCaptureRestricted(area)) {
+  if (IsScreenshotRestricted(area)) {
     InterruptVideoRecording();
     return;
   }
@@ -272,16 +250,9 @@
 }
 
 bool DlpContentManager::IsCaptureModeInitRestricted() {
-  const RestrictionLevelAndUrl screenshot_restriction_info =
+  const RestrictionLevelAndUrl restriction_info =
       GetOnScreenPresentRestrictions().GetRestrictionLevelAndUrl(
           DlpContentRestriction::kScreenshot);
-  const RestrictionLevelAndUrl videocapture_restriction_info =
-      GetOnScreenPresentRestrictions().GetRestrictionLevelAndUrl(
-          DlpContentRestriction::kVideoCapture);
-  const RestrictionLevelAndUrl restriction_info =
-      screenshot_restriction_info.level >= videocapture_restriction_info.level
-          ? screenshot_restriction_info
-          : videocapture_restriction_info;
   MaybeReportEvent(restriction_info, DlpRulesManager::Restriction::kScreenshot);
   DlpBooleanHistogram(dlp::kCaptureModeInitBlockedUMA,
                       IsBlocked(restriction_info));
@@ -290,25 +261,8 @@
 
 void DlpContentManager::CheckCaptureModeInitRestriction(
     ash::OnCaptureModeDlpRestrictionChecked callback) {
-  const ConfidentialContentsInfo screenshot_info =
+  const ConfidentialContentsInfo info =
       GetConfidentialContentsOnScreen(DlpContentRestriction::kScreenshot);
-  const ConfidentialContentsInfo videocapture_info =
-      GetConfidentialContentsOnScreen(DlpContentRestriction::kVideoCapture);
-  ConfidentialContentsInfo info;
-
-  if (screenshot_info.restriction_info.level >
-      videocapture_info.restriction_info.level) {
-    info = screenshot_info;
-  } else if (screenshot_info.restriction_info.level <
-             videocapture_info.restriction_info.level) {
-    info = videocapture_info;
-  } else {
-    // Both screenshot and video capture have the same restriction level, so a
-    // union is needed.
-    info = screenshot_info;
-    info.confidential_contents.UnionWith(
-        videocapture_info.confidential_contents);
-  }
 
   MaybeReportEvent(info.restriction_info,
                    DlpRulesManager::Restriction::kScreenshot);
@@ -718,7 +672,7 @@
   if (!running_video_capture_info_.has_value())
     return;
   ConfidentialContentsInfo info = GetAreaConfidentialContentsInfo(
-      running_video_capture_info_->area, DlpContentRestriction::kVideoCapture);
+      running_video_capture_info_->area, DlpContentRestriction::kScreenshot);
   MaybeReportEvent(info.restriction_info,
                    DlpRulesManager::Restriction::kScreenshot);
   if (IsBlocked(info.restriction_info)) {
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager.h b/chrome/browser/ash/policy/dlp/dlp_content_manager.h
index ca46125..aed94235 100644
--- a/chrome/browser/ash/policy/dlp/dlp_content_manager.h
+++ b/chrome/browser/ash/policy/dlp/dlp_content_manager.h
@@ -81,17 +81,6 @@
       const ScreenshotArea& area,
       ash::OnCaptureModeDlpRestrictionChecked callback);
 
-  // Returns whether video capture should be restricted.
-  // TODO(crbug.com/1257493): Remove when it won't be used anymore.
-  bool IsVideoCaptureRestricted(const ScreenshotArea& area);
-
-  // Checks whether video capture of |area| is restricted or not advised.
-  // Depending on the result, calls |callback| and passes an indicator whether
-  // to proceed or not.
-  void CheckVideoCaptureRestriction(
-      const ScreenshotArea& area,
-      ash::OnCaptureModeDlpRestrictionChecked callback);
-
   // Checks whether printing of |web_contents| is restricted or not advised.
   // Depending on the result, calls |callback| and passes an indicator whether
   // to proceed or not.
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager_browsertest.cc b/chrome/browser/ash/policy/dlp/dlp_content_manager_browsertest.cc
index e763cb3..7c58367 100644
--- a/chrome/browser/ash/policy/dlp/dlp_content_manager_browsertest.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_browsertest.cc
@@ -63,12 +63,6 @@
                                                 DlpRulesManager::Level::kBlock);
 const DlpContentRestrictionSet kPrintReported(DlpContentRestriction::kPrint,
                                               DlpRulesManager::Level::kReport);
-const DlpContentRestrictionSet kVideoCaptureRestricted(
-    DlpContentRestriction::kVideoCapture,
-    DlpRulesManager::Level::kBlock);
-const DlpContentRestrictionSet kVideoCaptureReported(
-    DlpContentRestriction::kVideoCapture,
-    DlpRulesManager::Level::kReport);
 const DlpContentRestrictionSet kScreenShareRestricted(
     DlpContentRestriction::kScreenShare,
     DlpRulesManager::Level::kBlock);
@@ -363,7 +357,7 @@
   browser2->window()->SetBounds(gfx::Rect(0, 0, 700, 700));
 
   // Make first window content as confidential.
-  helper_.ChangeConfidentiality(web_contents1, kVideoCaptureRestricted);
+  helper_.ChangeConfidentiality(web_contents1, kScreenshotRestricted);
 
   // Start capture of the whole screen.
   base::RunLoop run_loop;
@@ -411,7 +405,7 @@
   browser2->window()->SetBounds(gfx::Rect(0, 0, 700, 700));
 
   // Make first window content as confidential.
-  helper_.ChangeConfidentiality(web_contents1, kVideoCaptureReported);
+  helper_.ChangeConfidentiality(web_contents1, kScreenshotReported);
 
   // Start capture of the whole screen.
   base::RunLoop run_loop;
@@ -460,7 +454,7 @@
   browser2->window()->SetBounds(gfx::Rect(0, 0, 700, 700));
 
   // Make first window content as confidential.
-  helper_.ChangeConfidentiality(web_contents1, kVideoCaptureRestricted);
+  helper_.ChangeConfidentiality(web_contents1, kScreenshotRestricted);
 
   // Start capture of the whole screen.
   base::RunLoop run_loop;
@@ -509,7 +503,7 @@
   browser2->window()->SetBounds(gfx::Rect(0, 0, 700, 700));
 
   // Make first window content as confidential.
-  helper_.ChangeConfidentiality(web_contents1, kVideoCaptureRestricted);
+  helper_.ChangeConfidentiality(web_contents1, kScreenshotRestricted);
 
   // Start capture of the whole screen.
   base::RunLoop run_loop;
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_content_manager_unittest.cc
index 4acb28c..d147ff5 100644
--- a/chrome/browser/ash/policy/dlp/dlp_content_manager_unittest.cc
+++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_unittest.cc
@@ -54,9 +54,6 @@
 const DlpContentRestrictionSet kScreenshotRestricted(
     DlpContentRestriction::kScreenshot,
     DlpRulesManager::Level::kBlock);
-const DlpContentRestrictionSet kVideoCaptureRestricted(
-    DlpContentRestriction::kVideoCapture,
-    DlpRulesManager::Level::kBlock);
 const DlpContentRestrictionSet kPrivacyScreenEnforced(
     DlpContentRestriction::kPrivacyScreen,
     DlpRulesManager::Level::kBlock);
@@ -72,9 +69,6 @@
 const DlpContentRestrictionSet kScreenshotWarned(
     DlpContentRestriction::kScreenshot,
     DlpRulesManager::Level::kWarn);
-const DlpContentRestrictionSet kVideoCaptureWarned(
-    DlpContentRestriction::kVideoCapture,
-    DlpRulesManager::Level::kWarn);
 const DlpContentRestrictionSet kScreenShareWarned(
     DlpContentRestriction::kScreenShare,
     DlpRulesManager::Level::kWarn);
@@ -996,178 +990,4 @@
   VerifyAndResetActionAllowed(true /*expected*/);
 }
 
-TEST_F(DlpContentManagerCheckRestrictionTest, VideoCaptureRestricted) {
-  // Needs to be set because CheckScreencaptureRestriction() will show the
-  // blocked notification.
-  NotificationDisplayServiceTester display_service_tester(profile());
-
-  EXPECT_CALL(*mock_rules_manager_, GetSourceUrlPattern(_, _, _))
-      .Times(1)
-      .WillOnce(::testing::Return(kSrcPattern));
-
-  ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
-
-  // No restrictions are enforced: allow.
-  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-  histogram_tester_.ExpectBucketCount(
-      GetDlpHistogramPrefix() + dlp::kVideoCaptureBlockedUMA, true, 0);
-  histogram_tester_.ExpectBucketCount(
-      GetDlpHistogramPrefix() + dlp::kVideoCaptureBlockedUMA, false, 1);
-
-  // Block restriction is enforced for web_contents: block.
-  helper_.ChangeConfidentiality(web_contents.get(), kVideoCaptureRestricted);
-
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kVideoCaptureRestricted);
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(false /*expected*/);
-  histogram_tester_.ExpectBucketCount(
-      GetDlpHistogramPrefix() + dlp::kVideoCaptureBlockedUMA, true, 1);
-  histogram_tester_.ExpectBucketCount(
-      GetDlpHistogramPrefix() + dlp::kVideoCaptureBlockedUMA, false, 1);
-
-  EXPECT_EQ(events_.size(), 1u);
-  EXPECT_THAT(events_[0],
-              IsDlpPolicyEvent(CreateDlpPolicyEvent(
-                  kSrcPattern, DlpRulesManager::Restriction::kScreenshot,
-                  DlpRulesManager::Level::kBlock)));
-
-  // Web contents are destroyed: allow.
-  helper_.DestroyWebContents(web_contents.get());
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kEmptyRestrictionSet);
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-  histogram_tester_.ExpectBucketCount(
-      GetDlpHistogramPrefix() + dlp::kVideoCaptureBlockedUMA, true, 1);
-  histogram_tester_.ExpectBucketCount(
-      GetDlpHistogramPrefix() + dlp::kVideoCaptureBlockedUMA, false, 2);
-}
-
-TEST_F(DlpContentManagerCheckRestrictionTest, VideoCaptureWarnedContinued) {
-  // Set the notifier to "Proceed" on the warning.
-  MockDlpWarnNotifier* mock_dlp_warn_notifier =
-      CreateAndSetDlpWarnNotifier(true /*should_proceed*/);
-  // The warning should be shown only once.
-  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog(_, _)).Times(1);
-
-  ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
-
-  // No restrictions are enforced: allow.
-  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kEmptyRestrictionSet);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .IsEmpty());
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .IsEmpty());
-
-  // Warn restriction is enforced: allow and remember that the user proceeded.
-  helper_.ChangeConfidentiality(web_contents.get(), kVideoCaptureWarned);
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kVideoCaptureWarned);
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .Contains(web_contents.get()));
-
-  // Check again: allow based on cached user's response - no dialog is shown.
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .Contains(web_contents.get()));
-
-  // Web contents are destroyed: allow, no dialog is shown.
-  helper_.DestroyWebContents(web_contents.get());
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kEmptyRestrictionSet);
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-}
-
-TEST_F(DlpContentManagerCheckRestrictionTest, VideoCaptureWarnedCancelled) {
-  // Set the notifier to "Proceed" on the warning.
-  MockDlpWarnNotifier* mock_dlp_warn_notifier =
-      CreateAndSetDlpWarnNotifier(false /*should_proceed*/);
-  // If the user cancels, the warning can be shown again for the same contents.
-  EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpWarningDialog(_, _)).Times(2);
-
-  ScreenshotArea area = ScreenshotArea::CreateForAllRootWindows();
-
-  // No restrictions are enforced: allow.
-  std::unique_ptr<content::WebContents> web_contents = CreateWebContents();
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kEmptyRestrictionSet);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .IsEmpty());
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .IsEmpty());
-
-  // Warn restriction is enforced: reject since the user canceled.
-  helper_.ChangeConfidentiality(web_contents.get(), kVideoCaptureWarned);
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kVideoCaptureWarned);
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(false /*expected*/);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .IsEmpty());
-
-  // Check again: since the user previously cancelled, dialog is shown again.
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(false /*expected*/);
-  EXPECT_TRUE(helper_
-                  .GetUserAllowedContentsForRestriction(
-                      DlpRulesManager::Restriction::kScreenshot)
-                  .IsEmpty());
-
-  // Web contents are destroyed: allow, no dialog is shown.
-  helper_.DestroyWebContents(web_contents.get());
-  EXPECT_EQ(GetManager()->GetConfidentialRestrictions(web_contents.get()),
-            kEmptyRestrictionSet);
-  GetManager()->CheckVideoCaptureRestriction(
-      area,
-      base::BindOnce(on_dlp_restriction_checked_callback, &is_action_allowed_));
-  VerifyAndResetActionAllowed(true /*expected*/);
-}
-
 }  // namespace policy
diff --git a/chrome/browser/ash/policy/external_data/handlers/preconfigured_desk_templates_external_data_handler.cc b/chrome/browser/ash/policy/external_data/handlers/preconfigured_desk_templates_external_data_handler.cc
index 156659f..50a890d 100644
--- a/chrome/browser/ash/policy/external_data/handlers/preconfigured_desk_templates_external_data_handler.cc
+++ b/chrome/browser/ash/policy/external_data/handlers/preconfigured_desk_templates_external_data_handler.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "chrome/browser/ash/settings/cros_settings.h"
-#include "chrome/browser/ui/ash/desks_client.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_client.h"
 #include "components/policy/policy_constants.h"
 
 namespace policy {
@@ -29,7 +29,7 @@
 void PreconfiguredDeskTemplatesExternalDataHandler::OnExternalDataCleared(
     const std::string& policy,
     const std::string& user_id) {
-  DesksClient* dc = DesksClient::Get();
+  DesksTemplatesClient* dc = DesksTemplatesClient::Get();
   if (dc) {
     dc->RemovePolicyPreconfiguredTemplate(
         CloudExternalDataPolicyHandler::GetAccountId(user_id));
@@ -41,7 +41,7 @@
     const std::string& user_id,
     std::unique_ptr<std::string> data,
     const base::FilePath& file_path) {
-  DesksClient* dc = DesksClient::Get();
+  DesksTemplatesClient* dc = DesksTemplatesClient::Get();
   if (dc) {
     dc->SetPolicyPreconfiguredTemplate(
         CloudExternalDataPolicyHandler::GetAccountId(user_id), std::move(data));
@@ -50,7 +50,7 @@
 
 void PreconfiguredDeskTemplatesExternalDataHandler::RemoveForAccountId(
     const AccountId& account_id) {
-  DesksClient* dc = DesksClient::Get();
+  DesksTemplatesClient* dc = DesksTemplatesClient::Get();
   if (dc)
     dc->RemovePolicyPreconfiguredTemplate(account_id);
 }
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 6365d3b..14a2aa3 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
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/components/settings/cros_settings_names.h"
@@ -24,7 +25,6 @@
 #include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h"
 #include "chromeos/login/session/session_termination_manager.h"
 #include "components/account_id/account_id.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "components/user_manager/scoped_user_manager.h"
 
diff --git a/chrome/browser/ash/policy/remote_commands/user_command_arc_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/user_command_arc_job_unittest.cc
index 2ad079eb..d5e9c9b8 100644
--- a/chrome/browser/ash/policy/remote_commands/user_command_arc_job_unittest.cc
+++ b/chrome/browser/ash/policy/remote_commands/user_command_arc_job_unittest.cc
@@ -7,6 +7,9 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/fake_policy_instance.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -14,9 +17,6 @@
 #include "base/time/time.h"
 #include "chrome/browser/ash/arc/policy/arc_policy_bridge.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/policy/core/common/remote_commands/remote_command_job.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/policy/status_collector/app_info_generator_unittest.cc b/chrome/browser/ash/policy/status_collector/app_info_generator_unittest.cc
index 74c7413..99769f7 100644
--- a/chrome/browser/ash/policy/status_collector/app_info_generator_unittest.cc
+++ b/chrome/browser/ash/policy/status_collector/app_info_generator_unittest.cc
@@ -176,9 +176,7 @@
     auto clone = instance.instance()->Clone();
     clone->UpdateState(state, time);
 
-    std::vector<std::unique_ptr<apps::Instance>> deltas;
-    deltas.push_back(std::move(clone));
-    GetInstanceRegistry().OnInstances(std::move(deltas));
+    GetInstanceRegistry().OnInstance(std::move(clone));
   }
 
   std::unique_ptr<TestingProfile> CreateProfile(const AccountId& account_id,
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector.cc b/chrome/browser/ash/policy/status_collector/child_status_collector.cc
index d1db059cf..8d3f7ed 100644
--- a/chrome/browser/ash/policy/status_collector/child_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/child_status_collector.cc
@@ -14,6 +14,8 @@
 #include <sstream>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/settings/cros_settings_names.h"
 #include "ash/components/settings/timezone_settings.h"
 #include "base/base64.h"
@@ -41,8 +43,6 @@
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/arc/mojom/enterprise_reporting.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/proto/device_management_backend.pb.h"
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 f26aae0..affc664 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -17,6 +17,8 @@
 #include <sstream>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/audio/cras_audio_handler.h"
 #include "ash/components/settings/cros_settings_names.h"
 #include "ash/components/settings/timezone_settings.h"
@@ -86,8 +88,6 @@
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/arc/mojom/enterprise_reporting.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/core/browser/browser_policy_connector.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/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
index 3229090a5..847c64e 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
@@ -3824,9 +3824,7 @@
   auto instance = std::make_unique<apps::Instance>(
       "id", apps::Instance::InstanceKey::ForWindowBasedApp(window.get()));
   instance->UpdateState(apps::InstanceState::kStarted, start_time);
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
-  deltas.push_back(std::move(instance));
-  app_proxy->InstanceRegistry().OnInstances(std::move(deltas));
+  app_proxy->InstanceRegistry().OnInstance(std::move(instance));
 
   base::Time report_time;
   EXPECT_TRUE(base::Time::FromString("30-MAR-2020 2:30pm", &report_time));
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 bf208ccf..441c87f 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
@@ -17,6 +17,8 @@
 #include <sstream>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/audio/cras_audio_handler.h"
 #include "ash/components/settings/cros_settings_names.h"
 #include "ash/components/settings/timezone_settings.h"
@@ -83,8 +85,6 @@
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/arc/mojom/enterprise_reporting.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/proto/device_management_backend.pb.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 312d567..0cf9750c 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
@@ -3771,9 +3771,7 @@
   auto instance = std::make_unique<apps::Instance>(
       "id", apps::Instance::InstanceKey::ForWindowBasedApp(window.get()));
   instance->UpdateState(apps::InstanceState::kStarted, start_time);
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
-  deltas.push_back(std::move(instance));
-  app_proxy->InstanceRegistry().OnInstances(std::move(deltas));
+  app_proxy->InstanceRegistry().OnInstance(std::move(instance));
 
   base::Time report_time;
   EXPECT_TRUE(base::Time::FromString("30-MAR-2020 2:30pm", &report_time));
diff --git a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
index 7e3cd86..46f60bb 100644
--- a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
@@ -20,8 +20,6 @@
 
 namespace {
 
-const char kOsUrlPrefix[] = "os://";
-
 SkColor GetBgColor(bool use_dark_mode) {
   return cros_styles::ResolveColor(
       cros_styles::ColorName::kBgColor, use_dark_mode,
@@ -106,6 +104,7 @@
   // been replaced by the chrome:// scheme. As the user cannot enter in ash
   // chrome:// scheme urls anymore, we should be safely able to assume that they
   // might have been os:// schemed URLs when being called from Lacros.
-  target_url = GURL(kOsUrlPrefix + target_url.host());
+  target_url =
+      crosapi::gurl_os_handler_utils::GetSystemUrlFromChromeUrl(target_url);
   return ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(target_url);
 }
diff --git a/chrome/browser/bluetooth/web_bluetooth_browsertest.cc b/chrome/browser/bluetooth/web_bluetooth_browsertest.cc
index 4226e545..de67f3e 100644
--- a/chrome/browser/bluetooth/web_bluetooth_browsertest.cc
+++ b/chrome/browser/bluetooth/web_bluetooth_browsertest.cc
@@ -35,6 +35,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/prerender_test_util.h"
 #include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
 #include "content/public/test/url_loader_interceptor.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -1239,11 +1240,17 @@
   EXPECT_EQ(observer.num_is_connected_to_bluetooth_device_changed(), 1);
   EXPECT_FALSE(observer.last_is_connected_to_bluetooth_device().has_value());
 
+  content::RenderFrameDeletedObserver rfh_observer(
+      GetWebContents()->GetMainFrame());
+
   // Navigates the primary page to the URL.
   prerender_helper()->NavigatePrimaryPage(prerender_url);
   // The page should be activated from the prerendering.
   EXPECT_TRUE(host_observer.was_activated());
 
+  // Wait until the previous RFH to be disposed of.
+  rfh_observer.WaitUntilDeleted();
+
   // During prerendering activation, the connection from the previous
   // RenderFrameHost to Web Bluetooth is closed, while the connection attempt
   // from the prerendering RenderFrameHost was refused.
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc
index 206bfcb1..03d32db 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.cc
+++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -8,6 +8,8 @@
 #include <utility>
 
 #include "ash/components/account_manager/account_manager_factory.h"
+#include "ash/components/arc/enterprise/arc_data_snapshotd_manager.h"
+#include "ash/components/arc/enterprise/snapshot_hours_policy_service.h"
 #include "ash/components/geolocation/simple_geolocation_provider.h"
 #include "ash/components/timezone/timezone_resolver.h"
 #include "base/bind.h"
@@ -50,8 +52,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/app_restore/features.h"
-#include "components/arc/enterprise/arc_data_snapshotd_manager.h"
-#include "components/arc/enterprise/snapshot_hours_policy_service.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
diff --git a/chrome/browser/cart/cart_service.cc b/chrome/browser/cart/cart_service.cc
index 4b143db..18e003d 100644
--- a/chrome/browser/cart/cart_service.cc
+++ b/chrome/browser/cart/cart_service.cc
@@ -150,6 +150,7 @@
                                       weak_ptr_factory_.GetWeakPtr());
   pref_change_registrar_.Add(prefs::kNtpDisabledModules, callback);
   pref_change_registrar_.Add(prefs::kCartDiscountEnabled, callback);
+  pref_change_registrar_.Add(prefs::kNtpModulesVisible, callback);
 }
 
 CartService::~CartService() = default;
@@ -988,7 +989,8 @@
   if (list && base::Contains(list->GetList(), base::Value(kCartPrefsKey))) {
     return false;
   }
-  return profile_->GetPrefs()->GetBoolean(prefs::kCartDiscountEnabled);
+  return profile_->GetPrefs()->GetBoolean(prefs::kCartDiscountEnabled) &&
+         profile_->GetPrefs()->GetBoolean(prefs::kNtpModulesVisible);
 }
 
 void CartService::SetCartDiscountLinkFetcherForTesting(
diff --git a/chrome/browser/cart/cart_service_unittest.cc b/chrome/browser/cart/cart_service_unittest.cc
index ded5fb20..6bdbb9e8 100644
--- a/chrome/browser/cart/cart_service_unittest.cc
+++ b/chrome/browser/cart/cart_service_unittest.cc
@@ -1906,3 +1906,14 @@
   ListPrefUpdate(profile_->GetPrefs(), prefs::kNtpDisabledModules)
       ->EraseListValue(base::Value("chrome_cart"));
 }
+
+TEST_F(CartServiceCouponTest, TestModuleFeatureStatusUpdate) {
+  // prefs::kNtpModulesVisible is true by default.
+  profile_->GetPrefs()->SetBoolean(prefs::kCartDiscountEnabled, true);
+
+  EXPECT_CALL(coupon_service_, MaybeFeatureStatusChanged(false)).Times(1);
+  profile_->GetPrefs()->SetBoolean(prefs::kNtpModulesVisible, false);
+
+  EXPECT_CALL(coupon_service_, MaybeFeatureStatusChanged(true)).Times(1);
+  profile_->GetPrefs()->SetBoolean(prefs::kNtpModulesVisible, true);
+}
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 0008476..2c80d1789 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -80,7 +80,9 @@
     "//apps",
     "//ash",
     "//ash/components/account_manager",
+    "//ash/components/arc/enterprise",
     "//ash/components/arc/input_overlay/resources:resources_grit",
+    "//ash/components/arc/media_session",
     "//ash/components/attestation",
     "//ash/components/audio",
     "//ash/components/device_activity",
@@ -326,8 +328,6 @@
     "//chromeos/utils",
     "//components/app_restore",
     "//components/arc",
-    "//components/arc/enterprise",
-    "//components/arc/media_session",
     "//components/arc/mojom:mojom_traits",
     "//components/autofill/core/browser",
     "//components/browser_sync",
@@ -590,8 +590,6 @@
     "../ash/android_sms/connection_manager.h",
     "../ash/android_sms/fcm_connection_establisher.cc",
     "../ash/android_sms/fcm_connection_establisher.h",
-    "../ash/android_sms/pairing_lost_notifier.cc",
-    "../ash/android_sms/pairing_lost_notifier.h",
     "../ash/app_mode/app_launch_utils.cc",
     "../ash/app_mode/app_launch_utils.h",
     "../ash/app_mode/app_session_ash.cc",
@@ -1675,6 +1673,8 @@
     "../ash/input_method/ui/candidate_window_constants.h",
     "../ash/input_method/ui/candidate_window_view.cc",
     "../ash/input_method/ui/candidate_window_view.h",
+    "../ash/input_method/ui/colors.cc",
+    "../ash/input_method/ui/colors.h",
     "../ash/input_method/ui/grammar_suggestion_window.cc",
     "../ash/input_method/ui/grammar_suggestion_window.h",
     "../ash/input_method/ui/infolist_window.cc",
@@ -3837,7 +3837,6 @@
     "../ash/android_sms/android_sms_app_setup_controller_impl_unittest.cc",
     "../ash/android_sms/connection_manager_unittest.cc",
     "../ash/android_sms/fcm_connection_establisher_unittest.cc",
-    "../ash/android_sms/pairing_lost_notifier_unittest.cc",
     "../ash/app_mode/app_launch_utils_unittest.cc",
     "../ash/app_mode/arc/arc_kiosk_app_service_unittest.cc",
     "../ash/app_mode/kiosk_app_launch_error_unittest.cc",
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 d58350d..923479f 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
@@ -29,7 +30,6 @@
 #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/arc/session/connection_holder.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"
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h
index c2dbd036..15320998 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/settings/timezone_settings.h"
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "base/gtest_prod_util.h"
@@ -29,7 +30,6 @@
 #include "chrome/common/extensions/api/file_manager_private.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/arc/intent_helper/arc_intent_helper_observer.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc
index cf88090..50a51ee 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_dialog.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/arc/fileapi/arc_select_files_util.h"
 #include "chrome/browser/ash/file_manager/file_tasks_notifier.h"
@@ -16,8 +18,6 @@
 #include "chrome/common/extensions/api/file_manager_private.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/mime_util.h"
 #include "ui/shell_dialogs/selected_file_info.h"
diff --git a/chrome/browser/chromeos/extensions/speech/speech_recognition_private_apitest.cc b/chrome/browser/chromeos/extensions/speech/speech_recognition_private_apitest.cc
index 61b9974..1b51305f7 100644
--- a/chrome/browser/chromeos/extensions/speech/speech_recognition_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/speech/speech_recognition_private_apitest.cc
@@ -59,7 +59,10 @@
   // This test requires some back and forth communication between C++ and JS.
   // Use message listeners to force the synchronicity of this test.
   ExtensionTestMessageListener start_listener("Started", false);
-  ExtensionTestMessageListener result_listener("Received result", true);
+  ExtensionTestMessageListener first_result_listener("Received first result",
+                                                     false);
+  ExtensionTestMessageListener second_result_listener("Received second result",
+                                                      true);
 
   // Load the extension and wait for speech recognition to start.
   ResultCatcher result_catcher;
@@ -68,13 +71,19 @@
   ASSERT_TRUE(extension);
   ASSERT_TRUE(start_listener.WaitUntilSatisfied());
 
-  // Send a fake speech result and wait for confirmation from the extension.
-  SendFinalFakeSpeechResultAndWait("Testing");
-  ASSERT_TRUE(result_listener.WaitUntilSatisfied());
+  // Send a non-final speech result and wait for confirmation from the
+  // extension.
+  SendFakeSpeechResultAndWait("First result", /*is_final=*/false);
+  ASSERT_TRUE(first_result_listener.WaitUntilSatisfied());
+  ASSERT_FALSE(second_result_listener.was_satisfied());
+
+  // Send a final speech result and wait for confirmation from the extension.
+  SendFakeSpeechResultAndWait("Second result", /*is_final=*/true);
+  ASSERT_TRUE(second_result_listener.WaitUntilSatisfied());
 
   // Replying will trigger the extension to stop speech recogntition. As done
   // above, wait for the extension to confirm that recognition has stopped.
-  result_listener.Reply("Proceed");
+  second_result_listener.Reply("Proceed");
   ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
 }
 
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
index 3d23c0f..0332ab3 100644
--- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
@@ -9,7 +9,7 @@
 #include "ash/public/cpp/desk_template.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/ui/ash/desks_client.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_client.h"
 #include "chrome/common/extensions/api/wm_desks_private.h"
 
 namespace extensions {
@@ -34,7 +34,7 @@
 
 ExtensionFunction::ResponseAction
 WmDesksPrivateCaptureActiveDeskAndSaveTemplateFunction::Run() {
-  DesksClient::Get()->CaptureActiveDeskAndSaveTemplate(
+  DesksTemplatesClient::Get()->CaptureActiveDeskAndSaveTemplate(
       base::BindOnce(&WmDesksPrivateCaptureActiveDeskAndSaveTemplateFunction::
                          OnCaptureActiveDeskAndSaveTemplateCompleted,
                      this));
@@ -68,7 +68,7 @@
       api::wm_desks_private::UpdateDeskTemplate::Params::Create(args()));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  DesksClient::Get()->UpdateDeskTemplate(
+  DesksTemplatesClient::Get()->UpdateDeskTemplate(
       params->desk_template.template_uuid,
       base::UTF8ToUTF16(params->desk_template.template_name),
       base::BindOnce(&WmDesksPrivateUpdateDeskTemplateFunction::
@@ -94,7 +94,7 @@
 
 ExtensionFunction::ResponseAction
 WmDesksPrivateGetSavedDeskTemplatesFunction::Run() {
-  DesksClient::Get()->GetDeskTemplates(base::BindOnce(
+  DesksTemplatesClient::Get()->GetDeskTemplates(base::BindOnce(
       &WmDesksPrivateGetSavedDeskTemplatesFunction::OnGetSavedDeskTemplate,
       this));
   return RespondLater();
@@ -132,7 +132,7 @@
       api::wm_desks_private::DeleteDeskTemplate::Params::Create(args()));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  DesksClient::Get()->DeleteDeskTemplate(
+  DesksTemplatesClient::Get()->DeleteDeskTemplate(
       params->template_uuid,
       base::BindOnce(&WmDesksPrivateDeleteDeskTemplateFunction::
                          OnDeleteDeskTemplateCompleted,
@@ -161,7 +161,7 @@
       api::wm_desks_private::LaunchDeskTemplate::Params::Create(args()));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  DesksClient::Get()->LaunchDeskTemplate(
+  DesksTemplatesClient::Get()->LaunchDeskTemplate(
       params->template_uuid,
       base::BindOnce(
           &WmDesksPrivateLaunchDeskTemplateFunction::OnLaunchDeskTemplate,
diff --git a/chrome/browser/chromeos/fileapi/recent_arc_media_source_unittest.cc b/chrome/browser/chromeos/fileapi/recent_arc_media_source_unittest.cc
index 630502d..7311744 100644
--- a/chrome/browser/chromeos/fileapi/recent_arc_media_source_unittest.cc
+++ b/chrome/browser/chromeos/fileapi/recent_arc_media_source_unittest.cc
@@ -4,6 +4,8 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_file_system_instance.h"
 #include "base/bind.h"
@@ -19,8 +21,6 @@
 #include "chrome/browser/chromeos/fileapi/recent_source.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/mojom/file_system.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.cc
index d0830b2..524b202 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.cc
@@ -111,14 +111,12 @@
   if (!dlp_rules_manager)
     return set;
 
-  const size_t kRestrictionsCount = 5;
+  const size_t kRestrictionsCount = 4;
   static constexpr std::array<
       std::pair<DlpRulesManager::Restriction, DlpContentRestriction>,
       kRestrictionsCount>
       kRestrictionsArray = {{{DlpRulesManager::Restriction::kScreenshot,
                               DlpContentRestriction::kScreenshot},
-                             {DlpRulesManager::Restriction::kScreenshot,
-                              DlpContentRestriction::kVideoCapture},
                              {DlpRulesManager::Restriction::kPrivacyScreen,
                               DlpContentRestriction::kPrivacyScreen},
                              {DlpRulesManager::Restriction::kPrinting,
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h b/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h
index 9a792bbc..28ce59f7 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h
@@ -17,16 +17,14 @@
 // These values are used in bitmask in DlpContentRestrictionSet and should
 // correspond to the type in which the mask is stored.
 enum DlpContentRestriction {
-  // Do not allow any screenshots of the corresponding content.
+  // Do not allow any screenshots or video capture of the corresponding content.
   kScreenshot = 0,
   // Enforce ePrivacy screen when content is visible.
   kPrivacyScreen = 1,
   // Do not allow printing.
   kPrint = 2,
-  // Do not allow video capturing of the content.
-  kVideoCapture = 3,
   // Do not allow screen share.
-  kScreenShare = 4,
+  kScreenShare = 3,
   // Should be equal to the last restriction.
   kMaxValue = kScreenShare,
 };
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set_browsertest.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set_browsertest.cc
index 47c4fef..c593377 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set_browsertest.cc
+++ b/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set_browsertest.cc
@@ -110,11 +110,7 @@
 
   SetDlpRulesPolicy(rules);
 
-  DlpContentRestrictionSet screenshot_and_videocapture(kScreenshotRestricted);
-  screenshot_and_videocapture.SetRestriction(
-      DlpContentRestriction::kVideoCapture, DlpRulesManager::Level::kBlock,
-      GURL());
-  EXPECT_EQ(screenshot_and_videocapture,
+  EXPECT_EQ(kScreenshotRestricted,
             DlpContentRestrictionSet::GetForURL(GURL(kUrl1)));
   EXPECT_EQ(kPrivacyScreenEnforced,
             DlpContentRestrictionSet::GetForURL(GURL(kUrl2)));
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_histogram_helper.h b/chrome/browser/chromeos/policy/dlp/dlp_histogram_helper.h
index 0c59cfe..a0441ea 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_histogram_helper.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_histogram_helper.h
@@ -29,7 +29,6 @@
 constexpr char kScreenSharePausedOrResumedUMA[] = "ScreenSharePausedOrResumed";
 constexpr char kScreenshotBlockedUMA[] = "ScreenshotBlocked";
 constexpr char kVideoCaptureInterruptedUMA[] = "VideoCaptureInterrupted";
-constexpr char kVideoCaptureBlockedUMA[] = "VideoCaptureBlocked";
 constexpr char kReportedBlockLevelRestriction[] =
     "ReportedBlockLevelRestriction";
 constexpr char kReportedReportLevelRestriction[] =
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
index d75bd7f..a29cfb91 100644
--- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
+++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
@@ -29,9 +29,8 @@
     kUnknownRestriction = 0,
     kClipboard = 1,      // Restricts sharing the data via clipboard and
                          // drag-n-drop.
-    kScreenshot = 2,     // Restricts taking screenshots of confidential screen
-                         // content.
-                         // TODO(crbug/1145100): Update to include video capture
+    kScreenshot = 2,     // Restricts taking screenshots and video captures of
+                         // confidential screen content.
     kPrinting = 3,       // Restricts printing confidential screen content.
     kPrivacyScreen = 4,  // Enforces the Eprivacy screen when there's
                          // confidential content on the screen.
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index 84acca5..833114e4 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -268,6 +268,8 @@
         http_server_.GetURL("/accept_ch_with_lifetime.html");
     http_equiv_accept_ch_with_lifetime_http_local_url_ =
         http_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
+    meta_name_accept_ch_with_lifetime_http_local_url_ =
+        http_server_.GetURL("/meta_name_accept_ch_with_lifetime.html");
     EXPECT_TRUE(accept_ch_with_lifetime_http_local_url_.SchemeIsHTTPOrHTTPS());
     EXPECT_FALSE(
         accept_ch_with_lifetime_http_local_url_.SchemeIsCryptographic());
@@ -283,6 +285,8 @@
     EXPECT_TRUE(accept_ch_with_lifetime_url_.SchemeIsCryptographic());
     http_equiv_accept_ch_without_lifetime_url_ =
         https_server_.GetURL("/http_equiv_accept_ch_without_lifetime.html");
+    meta_name_accept_ch_without_lifetime_url_ =
+        https_server_.GetURL("/meta_name_accept_ch_without_lifetime.html");
 
     without_accept_ch_without_lifetime_url_ =
         https_server_.GetURL("/without_accept_ch_without_lifetime.html");
@@ -306,11 +310,17 @@
     http_equiv_accept_ch_without_lifetime_with_iframe_url_ =
         https_server_.GetURL(
             "/http_equiv_accept_ch_without_lifetime_with_iframe.html");
+    meta_name_accept_ch_without_lifetime_with_iframe_url_ =
+        https_server_.GetURL(
+            "/meta_name_accept_ch_without_lifetime_with_iframe.html");
     accept_ch_without_lifetime_with_subresource_url_ = https_server_.GetURL(
         "/accept_ch_without_lifetime_with_subresource.html");
     http_equiv_accept_ch_without_lifetime_with_subresource_url_ =
         https_server_.GetURL(
             "/http_equiv_accept_ch_without_lifetime_with_subresource.html");
+    meta_name_accept_ch_without_lifetime_with_subresource_url_ =
+        https_server_.GetURL(
+            "/meta_name_accept_ch_without_lifetime_with_subresource.html");
     accept_ch_without_lifetime_with_subresource_iframe_url_ =
         https_server_.GetURL(
             "/accept_ch_without_lifetime_with_subresource_iframe.html");
@@ -318,18 +328,28 @@
         https_server_.GetURL(
             "/http_equiv_accept_ch_without_lifetime_with_subresource_iframe."
             "html");
+    meta_name_accept_ch_without_lifetime_with_subresource_iframe_url_ =
+        https_server_.GetURL(
+            "/meta_name_accept_ch_without_lifetime_with_subresource_iframe."
+            "html");
     accept_ch_without_lifetime_img_localhost_ =
         https_server_.GetURL("/accept_ch_without_lifetime_img_localhost.html");
     http_equiv_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
         "/http_equiv_accept_ch_without_lifetime_img_localhost.html");
+    meta_name_accept_ch_without_lifetime_img_localhost_ = https_server_.GetURL(
+        "/meta_name_accept_ch_without_lifetime_img_localhost.html");
     http_equiv_accept_ch_with_lifetime_ =
         https_server_.GetURL("/http_equiv_accept_ch_with_lifetime.html");
+    meta_name_accept_ch_with_lifetime_ =
+        https_server_.GetURL("/meta_name_accept_ch_with_lifetime.html");
 
     redirect_url_ = https_cross_origin_server_.GetURL("/redirect.html");
 
     accept_ch_empty_ = https_server_.GetURL("/accept_ch_empty.html");
     http_equiv_accept_ch_merge_ =
         https_server_.GetURL("/http_equiv_accept_ch_merge.html");
+    meta_name_accept_ch_merge_ =
+        https_server_.GetURL("/meta_name_accept_ch_merge.html");
 
     without_accept_ch_without_lifetime_cross_origin_ =
         https_cross_origin_server_.GetURL(
@@ -346,7 +366,8 @@
     feature_list->InitializeFromCommandLine(
         "UserAgentClientHint,CriticalClientHint,"
         "AcceptCHFrame,PrefersColorSchemeClientHintHeader,"
-        "ViewportHeightClientHintHeader,UserAgentClientHintFullVersionList",
+        "ViewportHeightClientHintHeader,UserAgentClientHintFullVersionList,"
+        "ClientHintsMetaNameAcceptCH",
         "");
     return feature_list;
   }
@@ -418,6 +439,9 @@
   const GURL& http_equiv_accept_ch_with_lifetime_http_local_url() const {
     return http_equiv_accept_ch_with_lifetime_http_local_url_;
   }
+  const GURL& meta_name_accept_ch_with_lifetime_http_local_url() const {
+    return meta_name_accept_ch_with_lifetime_http_local_url_;
+  }
 
   // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
   // headers.
@@ -427,6 +451,9 @@
   const GURL& http_equiv_accept_ch_with_lifetime() {
     return http_equiv_accept_ch_with_lifetime_;
   }
+  const GURL& meta_name_accept_ch_with_lifetime() {
+    return meta_name_accept_ch_with_lifetime_;
+  }
 
   // A URL whose response headers include Accept-CH and Accept-CH-Lifetime
   // headers. The Accept-CH-Lifetime duration is set very short to 1 second.
@@ -441,6 +468,9 @@
   const GURL& http_equiv_accept_ch_without_lifetime_url() const {
     return http_equiv_accept_ch_without_lifetime_url_;
   }
+  const GURL& meta_name_accept_ch_without_lifetime_url() const {
+    return meta_name_accept_ch_without_lifetime_url_;
+  }
 
   // A URL whose response headers do not include either Accept-CH or
   // Accept-CH-Lifetime headers. Navigating to this URL also fetches an image.
@@ -476,6 +506,9 @@
   const GURL& http_equiv_accept_ch_without_lifetime_with_iframe_url() const {
     return http_equiv_accept_ch_without_lifetime_with_iframe_url_;
   }
+  const GURL& meta_name_accept_ch_without_lifetime_with_iframe_url() const {
+    return meta_name_accept_ch_without_lifetime_with_iframe_url_;
+  }
 
   // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
   // headers. The response loads accept_ch_with_lifetime_url() as a subresource
@@ -487,10 +520,15 @@
       const {
     return http_equiv_accept_ch_without_lifetime_with_subresource_url_;
   }
+  const GURL& meta_name_accept_ch_without_lifetime_with_subresource_url()
+      const {
+    return meta_name_accept_ch_without_lifetime_with_subresource_url_;
+  }
 
   // A URL whose response does not include Accept-CH or Accept-CH-Lifetime
   // headers. The response loads accept_ch_with_lifetime_url() or
-  // http_equiv_accept_ch_with_lifetime_url() as a subresource in the iframe.
+  // {http_equiv|meta_name}_accept_ch_with_lifetime_url() as a subresource in
+  // the iframe.
   const GURL& accept_ch_without_lifetime_with_subresource_iframe_url() const {
     return accept_ch_without_lifetime_with_subresource_iframe_url_;
   }
@@ -498,6 +536,10 @@
   http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url() const {
     return http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
   }
+  const GURL& meta_name_accept_ch_without_lifetime_with_subresource_iframe_url()
+      const {
+    return meta_name_accept_ch_without_lifetime_with_subresource_iframe_url_;
+  }
 
   // A URL whose response includes only Accept-CH header. Navigating to
   // this URL also fetches two images: One from the localhost, and one from
@@ -508,6 +550,9 @@
   const GURL& http_equiv_accept_ch_without_lifetime_img_localhost() const {
     return http_equiv_accept_ch_without_lifetime_img_localhost_;
   }
+  const GURL& meta_name_accept_ch_without_lifetime_img_localhost() const {
+    return meta_name_accept_ch_without_lifetime_img_localhost_;
+  }
 
   const GURL& redirect_url() const { return redirect_url_; }
 
@@ -518,6 +563,9 @@
   const GURL& http_equiv_accept_ch_merge() const {
     return http_equiv_accept_ch_merge_;
   }
+  const GURL& meta_name_accept_ch_merge() const {
+    return meta_name_accept_ch_merge_;
+  }
 
   const GURL& without_accept_ch_without_lifetime_cross_origin() {
     return without_accept_ch_without_lifetime_cross_origin_;
@@ -579,6 +627,7 @@
 
   std::string intercept_iframe_resource_;
   bool intercept_to_http_equiv_iframe_ = false;
+  bool intercept_to_meta_name_iframe_ = false;
   mutable base::Lock count_headers_lock_;
 
   Profile* GenerateNewProfile() {
@@ -637,12 +686,17 @@
     }
 
     const std::string iframe_url =
-        intercept_to_http_equiv_iframe_
+        intercept_to_meta_name_iframe_
             ? https_cross_origin_server_
-                  .GetURL("/http_equiv_accept_ch_with_lifetime.html")
+                  .GetURL("/meta_name_accept_ch_with_lifetime.html")
                   .spec()
-            : https_cross_origin_server_.GetURL("/accept_ch_with_lifetime.html")
-                  .spec();
+            : intercept_to_http_equiv_iframe_
+                  ? https_cross_origin_server_
+                        .GetURL("/http_equiv_accept_ch_with_lifetime.html")
+                        .spec()
+                  : https_cross_origin_server_
+                        .GetURL("/accept_ch_with_lifetime.html")
+                        .spec();
 
     std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
         new net::test_server::BasicHttpResponse());
@@ -942,26 +996,34 @@
   net::EmbeddedTestServer http2_server_;
   GURL accept_ch_with_lifetime_http_local_url_;
   GURL http_equiv_accept_ch_with_lifetime_http_local_url_;
+  GURL meta_name_accept_ch_with_lifetime_http_local_url_;
   GURL accept_ch_with_lifetime_url_;
   GURL accept_ch_with_short_lifetime_url_;
   GURL accept_ch_without_lifetime_url_;
   GURL http_equiv_accept_ch_without_lifetime_url_;
+  GURL meta_name_accept_ch_without_lifetime_url_;
   GURL without_accept_ch_without_lifetime_url_;
   GURL without_accept_ch_without_lifetime_local_url_;
   GURL accept_ch_without_lifetime_with_iframe_url_;
   GURL http_equiv_accept_ch_without_lifetime_with_iframe_url_;
+  GURL meta_name_accept_ch_without_lifetime_with_iframe_url_;
   GURL accept_ch_without_lifetime_with_subresource_url_;
   GURL http_equiv_accept_ch_without_lifetime_with_subresource_url_;
+  GURL meta_name_accept_ch_without_lifetime_with_subresource_url_;
   GURL accept_ch_without_lifetime_with_subresource_iframe_url_;
   GURL http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url_;
+  GURL meta_name_accept_ch_without_lifetime_with_subresource_iframe_url_;
   GURL without_accept_ch_without_lifetime_img_foo_com_;
   GURL without_accept_ch_without_lifetime_img_localhost_;
   GURL accept_ch_without_lifetime_img_localhost_;
   GURL http_equiv_accept_ch_without_lifetime_img_localhost_;
+  GURL meta_name_accept_ch_without_lifetime_img_localhost_;
   GURL http_equiv_accept_ch_with_lifetime_;
+  GURL meta_name_accept_ch_with_lifetime_;
   GURL redirect_url_;
   GURL accept_ch_empty_;
   GURL http_equiv_accept_ch_merge_;
+  GURL meta_name_accept_ch_merge_;
   GURL without_accept_ch_without_lifetime_cross_origin_;
 
   std::string main_frame_ua_observed_;
@@ -1008,7 +1070,7 @@
     feature_list->InitializeFromCommandLine(
         "AllowClientHintsToThirdParty,UserAgentClientHint,"
         "PrefersColorSchemeClientHintHeader,ViewportHeightClientHintHeader,"
-        "UserAgentClientHintFullVersionList",
+        "UserAgentClientHintFullVersionList,ClientHintsMetaNameAcceptCH",
         "");
     return feature_list;
   }
@@ -1045,12 +1107,22 @@
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
   histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
 }
+IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MetaNameWorks) {
+  const GURL gurl = meta_name_accept_ch_without_lifetime_img_localhost();
+  base::HistogramTester histogram_tester;
+
+  SetClientHintExpectationsOnMainFrame(false);
+  SetClientHintExpectationsOnSubresources(true);
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
+}
 
 // Loads a webpage that requests persisting of client hints. Verifies that
 // the browser receives the mojo notification from the renderer and persists the
 // client hints to the disk --- unless it's using http-equiv which shouldn't
 // persist.
-IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps) {
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps_HttpEquiv) {
   base::HistogramTester histogram_tester;
   const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
                                : accept_ch_with_lifetime_url();
@@ -1077,6 +1149,33 @@
                                         uma_histogram_max_value, 1);
   }
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, ClientHintsHttps_MetaName) {
+  base::HistogramTester histogram_tester;
+  const GURL gurl = GetParam() ? meta_name_accept_ch_with_lifetime()
+                               : accept_ch_with_lifetime_url();
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+
+  if (GetParam())
+    histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
+  else
+    histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
+
+  content::FetchHistogramsFromChildProcesses();
+  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+
+  if (GetParam()) {
+    histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
+    histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
+  } else {
+    // client_hints_url() sets the expected number of client hints.
+    histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
+                                        expected_client_hints_number, 1);
+    // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
+    // seconds, but a maximum value is registered instead.
+    histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
+                                        uma_histogram_max_value, 1);
+  }
+}
 
 IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsAlps) {
   base::HistogramTester histogram_tester;
@@ -1430,7 +1529,7 @@
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
 }
 
-IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH) {
+IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH_HttpEquiv) {
   // Go to page where some hints are enabled by headers, some by
   // http-equiv. It shouldn't get hints itself (due to first visit),
   // but subresources should get all the client hints.
@@ -1440,6 +1539,16 @@
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
   EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
 }
+IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH_MetaName) {
+  // Go to page where some hints are enabled by headers, some by
+  // http-equiv. It shouldn't get hints itself (due to first visit),
+  // but subresources should get all the client hints.
+  GURL gurl = meta_name_accept_ch_merge();
+  SetClientHintExpectationsOnMainFrame(false);
+  SetClientHintExpectationsOnSubresources(true);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+}
 
 void ClientHintsBrowserTest::TestProfilesIndependent(Browser* browser_a,
                                                      Browser* browser_b) {
@@ -1492,7 +1601,7 @@
 // Test that client hints are attached to third party subresources if
 // AllowClientHintsToThirdParty feature is enabled.
 IN_PROC_BROWSER_TEST_P(ClientHintsAllowThirdPartyBrowserTest,
-                       ClientHintsThirdPartyAllowed) {
+                       ClientHintsThirdPartyAllowed_HttpEquiv) {
   GURL gurl;
   unsigned update_event_count = 0;
   if (GetParam()) {
@@ -1521,11 +1630,41 @@
   // the third-party when feature "AllowClientHintsToThirdParty" is enabled.
   EXPECT_EQ(6u, third_party_client_hints_count_seen());
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsAllowThirdPartyBrowserTest,
+                       ClientHintsThirdPartyAllowed_MetaName) {
+  GURL gurl;
+  unsigned update_event_count = 0;
+  if (GetParam()) {
+    gurl = meta_name_accept_ch_without_lifetime_img_localhost();
+  } else {
+    gurl = accept_ch_without_lifetime_img_localhost();
+    update_event_count = 1;
+  }
+
+  base::HistogramTester histogram_tester;
+
+  SetClientHintExpectationsOnMainFrame(false);
+  SetClientHintExpectationsOnSubresources(true);
+
+  // Add client hints for the embedded test server.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount",
+                                    update_event_count);
+
+  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+
+  // Requests to third party servers should not have client hints attached.
+  EXPECT_EQ(1u, third_party_request_count_seen());
+
+  // Device memory, viewport width, DRP, and UA client hints should be sent to
+  // the third-party when feature "AllowClientHintsToThirdParty" is enabled.
+  EXPECT_EQ(6u, third_party_client_hints_count_seen());
+}
 
 // Test that client hints are not attached to third party subresources if
 // AllowClientHintsToThirdParty feature is not enabled.
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       ClientHintsThirdPartyNotAllowed) {
+                       ClientHintsThirdPartyNotAllowed_HttpEquiv) {
   GURL gurl;
   unsigned update_event_count = 0;
   if (GetParam()) {
@@ -1558,6 +1697,40 @@
   // `Sec-CH-UA` hint, which is sent with every request.
   EXPECT_EQ(3u, third_party_client_hints_count_seen());
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       ClientHintsThirdPartyNotAllowed_MetaName) {
+  GURL gurl;
+  unsigned update_event_count = 0;
+  if (GetParam()) {
+    gurl = meta_name_accept_ch_without_lifetime_img_localhost();
+  } else {
+    gurl = accept_ch_without_lifetime_img_localhost();
+    update_event_count = 1;
+  }
+
+  base::HistogramTester histogram_tester;
+
+  SetClientHintExpectationsOnMainFrame(false);
+  SetClientHintExpectationsOnSubresources(true);
+
+  // Add client hints for the embedded test server.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount",
+                                    update_event_count);
+
+  EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
+  EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
+  EXPECT_EQ(2u, count_ua_platform_client_hints_headers_seen());
+  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+
+  // Requests to third party servers should not have client hints attached.
+  EXPECT_EQ(1u, third_party_request_count_seen());
+
+  // Client hints should not be sent to the third-party when feature
+  // "AllowClientHintsToThirdParty" is not enabled, with the exception of the
+  // `Sec-CH-UA` hint, which is sent with every request.
+  EXPECT_EQ(3u, third_party_client_hints_count_seen());
+}
 
 // Loads a HTTPS webpage that does not request persisting of client hints.
 // A same-origin iframe loaded by the webpage requests persistence of client
@@ -1593,7 +1766,7 @@
 // Verify that the request from the cross origin iframe is not honored, and
 // client hints preference is not persisted.
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       DisregardPersistenceRequestIframe_CrossOrigin) {
+                       DisregardPersistenceRequestIframe_HttpEquivCrossOrigin) {
   const GURL gurl =
       GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
                  : accept_ch_without_lifetime_with_iframe_url();
@@ -1622,13 +1795,43 @@
   histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
   histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       DisregardPersistenceRequestIframe_MetaNameCrossOrigin) {
+  const GURL gurl = GetParam()
+                        ? meta_name_accept_ch_without_lifetime_with_iframe_url()
+                        : accept_ch_without_lifetime_with_iframe_url();
+
+  intercept_iframe_resource_ = gurl.path();
+  intercept_to_meta_name_iframe_ = GetParam();
+
+  base::HistogramTester histogram_tester;
+  ContentSettingsForOneType host_settings;
+
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
+
+  content::FetchHistogramsFromChildProcesses();
+  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+
+  // accept_ch_without_lifetime_with_iframe_url() loads
+  // accept_ch_with_lifetime() in a cross origin iframe. The request to persist
+  // client hints from accept_ch_with_lifetime() should be disregarded.
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
+  histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
+}
 
 // Loads a HTTPS webpage that does not request persisting of client hints.
 // A subresource loaded by the webpage requests persistence of client hints.
 // Verify that the request from the subresource is not honored, and client hints
 // preference is not persisted.
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       DisregardPersistenceRequestSubresource) {
+                       DisregardPersistenceRequestSubresource_HttpEquiv) {
   const GURL gurl =
       GetParam() ? http_equiv_accept_ch_without_lifetime_with_subresource_url()
                  : accept_ch_without_lifetime_with_subresource_url();
@@ -1654,13 +1857,40 @@
   histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
   histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       DisregardPersistenceRequestSubresource_MetaName) {
+  const GURL gurl =
+      GetParam() ? meta_name_accept_ch_without_lifetime_with_subresource_url()
+                 : accept_ch_without_lifetime_with_subresource_url();
+
+  base::HistogramTester histogram_tester;
+  ContentSettingsForOneType host_settings;
+
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
+
+  content::FetchHistogramsFromChildProcesses();
+  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+
+  // accept_ch_without_lifetime_with_subresource_url() loads
+  // accept_ch_with_lifetime() as a subresource. The request to persist client
+  // hints from accept_ch_with_lifetime() should be disregarded.
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
+  histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
+}
 
 // Loads a HTTPS webpage that does not request persisting of client hints.
 // A subresource loaded by the webpage in an iframe requests persistence of
 // client hints. Verify that the request from the subresource in the iframe
 // is not honored, and client hints preference is not persisted.
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       DisregardPersistenceRequestSubresourceIframe) {
+                       DisregardPersistenceRequestSubresourceIframe_HttpEquiv) {
   const GURL gurl =
       GetParam()
           ? http_equiv_accept_ch_without_lifetime_with_subresource_iframe_url()
@@ -1688,6 +1918,35 @@
   histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
   histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       DisregardPersistenceRequestSubresourceIframe_MetaName) {
+  const GURL gurl =
+      GetParam()
+          ? meta_name_accept_ch_without_lifetime_with_subresource_iframe_url()
+          : accept_ch_without_lifetime_with_subresource_iframe_url();
+
+  base::HistogramTester histogram_tester;
+  ContentSettingsForOneType host_settings;
+
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
+
+  content::FetchHistogramsFromChildProcesses();
+  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+
+  // |gurl| loads accept_ch_with_lifetime() or
+  // meta_name_accept_ch_with_lifetime() as a subresource in an iframe. The
+  // request to persist client hints from accept_ch_with_lifetime() or
+  // meta_name_accept_ch_with_lifetime() should be disregarded.
+  histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
+  histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
+}
 
 // Loads a HTTP local webpage (which qualifies as a secure context) that
 // requests persisting of client hints. Verifies that the browser receives the
@@ -1760,7 +2019,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       ClientHintsLifetimeFollowedByNoClientHint) {
+                       ClientHintsLifetimeFollowedByNoClientHint_HttpEquiv) {
   const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
                                : accept_ch_with_lifetime_url();
 
@@ -1818,6 +2077,65 @@
   EXPECT_EQ(GetParam() ? 0 : expected_client_hints_number * 2,
             count_client_hints_headers_seen());
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       ClientHintsLifetimeFollowedByNoClientHint_MetaName) {
+  const GURL gurl = GetParam() ? meta_name_accept_ch_with_lifetime()
+                               : accept_ch_with_lifetime_url();
+
+  base::HistogramTester histogram_tester;
+  ContentSettingsForOneType host_settings;
+
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+
+  // Fetching |gurl| should persist the request for client hints iff using
+  // headers and not http-equiv.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+
+  if (GetParam())
+    histogram_tester.ExpectTotalCount("ClientHints.UpdateEventCount", 0);
+  else
+    histogram_tester.ExpectUniqueSample("ClientHints.UpdateEventCount", 1, 1);
+
+  content::FetchHistogramsFromChildProcesses();
+  metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+  base::RunLoop().RunUntilIdle();
+
+  if (GetParam()) {
+    histogram_tester.ExpectTotalCount("ClientHints.UpdateSize", 0);
+    histogram_tester.ExpectTotalCount("ClientHints.PersistDuration", 0);
+  } else {
+    histogram_tester.ExpectUniqueSample("ClientHints.UpdateSize",
+                                        expected_client_hints_number, 1);
+    // accept_ch_with_lifetime_url() sets client hints persist duration to 3600
+    // seconds, but a maximum value is registered instead.
+    histogram_tester.ExpectUniqueSample("ClientHints.PersistDuration",
+                                        uma_histogram_max_value, 1);
+
+    // Clients hints preferences for one origin should be persisted.
+    HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+        ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                                &host_settings);
+    EXPECT_EQ(1u, host_settings.size());
+  }
+
+  SetClientHintExpectationsOnMainFrame(!GetParam());
+  SetClientHintExpectationsOnSubresources(!GetParam());
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), without_accept_ch_without_lifetime_url()));
+
+  // The user agent hint is attached to all three requests:
+  EXPECT_EQ(3u, count_user_agent_hint_headers_seen());
+  EXPECT_EQ(3u, count_ua_mobile_client_hints_headers_seen());
+  EXPECT_EQ(3u, count_ua_platform_client_hints_headers_seen());
+
+  // Expected number of hints attached to the image request, and the same number
+  // to the main frame request.
+  EXPECT_EQ(GetParam() ? 0 : expected_client_hints_number * 2,
+            count_client_hints_headers_seen());
+}
 
 // The test first fetches a page that sets Accept-CH-Lifetime. Next, it fetches
 // a URL from a different origin. However, that URL response redirects to the
@@ -1959,10 +2277,11 @@
       ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
 }
 
-// Ensure that when the JavaScript is blocked, client hint preferences are not
+// Ensure that when JavaScript is blocked, client hint preferences are not
 // persisted.
-IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       ClientHintsLifetimeNotPersistedJavaScriptBlocked) {
+IN_PROC_BROWSER_TEST_P(
+    ClientHintsBrowserTest,
+    ClientHintsLifetimeNotPersistedJavaScriptBlocked_HttpEquiv) {
   ContentSettingsForOneType host_settings;
 
   // Start a navigation. This navigation makes it possible to block JavaScript
@@ -1974,7 +2293,7 @@
       GetParam() ? http_equiv_accept_ch_without_lifetime_with_iframe_url()
                  : accept_ch_with_lifetime_url();
 
-  // Block the JavaScript: Client hint preferences should not be persisted.
+  // Block JavaScript: Client hint preferences should not be persisted.
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->SetContentSettingDefaultScope(
           gurl, GURL(), ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_BLOCK);
@@ -1986,7 +2305,48 @@
   EXPECT_EQ(0u, host_settings.size());
   VerifyContentSettingsNotNotified();
 
-  // Allow the JavaScript: Client hint preferences should be persisted.
+  // Allow JavaScript: Client hint preferences should be persisted.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetContentSettingDefaultScope(
+          gurl, GURL(), ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_ALLOW);
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url()));
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(1u, host_settings.size());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
+}
+IN_PROC_BROWSER_TEST_P(
+    ClientHintsBrowserTest,
+    ClientHintsLifetimeNotPersistedJavaScriptBlocked_MetaName) {
+  ContentSettingsForOneType host_settings;
+
+  // Start a navigation. This navigation makes it possible to block JavaScript
+  // later.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), without_accept_ch_without_lifetime_url()));
+
+  const GURL gurl = GetParam()
+                        ? meta_name_accept_ch_without_lifetime_with_iframe_url()
+                        : accept_ch_with_lifetime_url();
+
+  // Block JavaScript: Client hint preferences should not be persisted.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetContentSettingDefaultScope(
+          gurl, GURL(), ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_BLOCK);
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url()));
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+  VerifyContentSettingsNotNotified();
+
+  // Allow JavaScript: Client hint preferences should be persisted.
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->SetContentSettingDefaultScope(
           gurl, GURL(), ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_ALLOW);
@@ -2002,7 +2362,7 @@
       ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
 }
 
-// Ensure that when the JavaScript is blocked, persisted client hints are not
+// Ensure that when JavaScript is blocked, persisted client hints are not
 // attached to the request headers.
 IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                        ClientHintsLifetimeNotAttachedJavaScriptBlocked) {
@@ -2128,10 +2488,10 @@
       browser(), without_accept_ch_without_lifetime_url()));
 }
 
-// Ensure that when the JavaScript is blocked, client hints requested using
+// Ensure that when JavaScript is blocked, client hints requested using
 // Accept-CH are not attached to the request headers for subresources.
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       ClientHintsNoLifetimeScriptNotAllowed) {
+                       ClientHintsNoLifetimeScriptNotAllowed_HttpEquiv) {
   const GURL gurl = GetParam() ? http_equiv_accept_ch_with_lifetime()
                                : accept_ch_with_lifetime_url();
 
@@ -2143,7 +2503,7 @@
                               &host_settings);
   EXPECT_EQ(0u, host_settings.size());
 
-  // Block the Javascript: Client hints should not be attached.
+  // Block Javascript: Client hints should not be attached.
   SetClientHintExpectationsOnSubresources(false);
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->SetContentSettingDefaultScope(
@@ -2158,7 +2518,7 @@
   EXPECT_EQ(1u, third_party_request_count_seen());
   EXPECT_EQ(0u, third_party_client_hints_count_seen());
 
-  // Allow the Javascript: Client hints should now be attached.
+  // Allow Javascript: Client hints should now be attached.
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->SetContentSettingDefaultScope(
           accept_ch_without_lifetime_img_localhost(), GURL(),
@@ -2180,7 +2540,76 @@
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
 
-  // Block the Javascript again: Client hints should not be attached.
+  // Block Javascript again: Client hints should not be attached.
+  SetClientHintExpectationsOnSubresources(false);
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetContentSettingDefaultScope(
+          accept_ch_without_lifetime_img_localhost(), GURL(),
+          ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_BLOCK);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), accept_ch_without_lifetime_img_localhost()));
+  EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
+  EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
+  EXPECT_EQ(2u, count_ua_platform_client_hints_headers_seen());
+  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+  EXPECT_EQ(3u, third_party_request_count_seen());
+  EXPECT_EQ(3u, third_party_client_hints_count_seen());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
+}
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       ClientHintsNoLifetimeScriptNotAllowed_MetaName) {
+  const GURL gurl = GetParam() ? meta_name_accept_ch_with_lifetime()
+                               : accept_ch_with_lifetime_url();
+
+  base::HistogramTester histogram_tester;
+  ContentSettingsForOneType host_settings;
+
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+
+  // Block Javascript: Client hints should not be attached.
+  SetClientHintExpectationsOnSubresources(false);
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetContentSettingDefaultScope(
+          accept_ch_without_lifetime_img_localhost(), GURL(),
+          ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_BLOCK);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), accept_ch_without_lifetime_img_localhost()));
+  EXPECT_EQ(0u, count_user_agent_hint_headers_seen());
+  EXPECT_EQ(0u, count_ua_mobile_client_hints_headers_seen());
+  EXPECT_EQ(0u, count_ua_platform_client_hints_headers_seen());
+  EXPECT_EQ(0u, count_client_hints_headers_seen());
+  EXPECT_EQ(1u, third_party_request_count_seen());
+  EXPECT_EQ(0u, third_party_client_hints_count_seen());
+
+  // Allow Javascript: Client hints should now be attached.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetContentSettingDefaultScope(
+          accept_ch_without_lifetime_img_localhost(), GURL(),
+          ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_ALLOW);
+
+  SetClientHintExpectationsOnSubresources(true);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), accept_ch_without_lifetime_img_localhost()));
+
+  EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
+  EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
+  EXPECT_EQ(2u, count_ua_platform_client_hints_headers_seen());
+  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+  EXPECT_EQ(2u, third_party_request_count_seen());
+  EXPECT_EQ(3u, third_party_client_hints_count_seen());
+  VerifyContentSettingsNotNotified();
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(ContentSettingsType::JAVASCRIPT);
+
+  // Block Javascript again: Client hints should not be attached.
   SetClientHintExpectationsOnSubresources(false);
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->SetContentSettingDefaultScope(
@@ -2203,7 +2632,7 @@
 // Ensure that when the cookies is blocked, client hints are attached to the
 // request headers.
 IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
-                       ClientHintsLifetimeCookiesNotAllowed) {
+                       ClientHintsLifetimeCookiesNotAllowed_HttpEquiv) {
   const GURL gurl = GetParam()
                         ? http_equiv_accept_ch_without_lifetime_img_localhost()
                         : accept_ch_without_lifetime_img_localhost();
@@ -2237,6 +2666,41 @@
   HostContentSettingsMapFactory::GetForProfile(browser()->profile())
       ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest,
+                       ClientHintsLifetimeCookiesNotAllowed_MetaName) {
+  const GURL gurl = GetParam()
+                        ? meta_name_accept_ch_without_lifetime_img_localhost()
+                        : accept_ch_without_lifetime_img_localhost();
+
+  base::HistogramTester histogram_tester;
+  ContentSettingsForOneType host_settings;
+  scoped_refptr<content_settings::CookieSettings> cookie_settings_ =
+      CookieSettingsFactory::GetForProfile(browser()->profile());
+
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->GetSettingsForOneType(ContentSettingsType::CLIENT_HINTS,
+                              &host_settings);
+  EXPECT_EQ(0u, host_settings.size());
+
+  // Block cookies.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->SetContentSettingDefaultScope(
+          gurl, GURL(), ContentSettingsType::COOKIES, CONTENT_SETTING_BLOCK);
+  base::RunLoop().RunUntilIdle();
+
+  SetClientHintExpectationsOnSubresources(true);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+  EXPECT_EQ(2u, count_user_agent_hint_headers_seen());
+  EXPECT_EQ(2u, count_ua_mobile_client_hints_headers_seen());
+  EXPECT_EQ(2u, count_ua_platform_client_hints_headers_seen());
+  EXPECT_EQ(expected_client_hints_number, count_client_hints_headers_seen());
+  EXPECT_EQ(1u, third_party_request_count_seen());
+  EXPECT_EQ(3u, third_party_client_hints_count_seen());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(ContentSettingsType::COOKIES);
+}
 
 // Verify that client hints are sent in the incognito profiles, and server
 // client hint opt-ins are honored within the incognito profile.
@@ -2496,7 +2960,7 @@
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
 }
 
-IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, UseCounter) {
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, UseCounter_HttpEquiv) {
   auto web_feature_waiter =
       std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>(
           chrome_test_utils::GetActiveWebContents(this));
@@ -2510,6 +2974,20 @@
 
   web_feature_waiter->Wait();
 }
+IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTest, UseCounter_MetaName) {
+  auto web_feature_waiter =
+      std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>(
+          chrome_test_utils::GetActiveWebContents(this));
+
+  web_feature_waiter->AddWebFeatureExpectation(
+      blink::mojom::WebFeature::kClientHintsUAFullVersion);
+  const GURL gurl = GetParam() ? meta_name_accept_ch_with_lifetime()
+                               : accept_ch_with_lifetime_url();
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl));
+
+  web_feature_waiter->Wait();
+}
 
 class CriticalClientHintsBrowserTest : public InProcessBrowserTest {
  public:
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java
index dec71904..3ddba7d 100644
--- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java
+++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationBridge.java
@@ -11,6 +11,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.google.common.primitives.UnsignedLongs;
 import com.google.protobuf.ByteString;
 import com.google.protobuf.InvalidProtocolBufferException;
 
@@ -108,8 +109,8 @@
         String text = context.getString(R.string.price_drop_notification_content_text,
                 buildDisplayPrice(priceDropPayload.getCurrentPrice()), productUrl.getHost());
 
-        // TODO(crbug.com/1257380): Figure out how to serialize offer id correctly.
-        String offerId = String.valueOf(priceDropPayload.getOfferId());
+        // Use UnsignedLongs to convert OfferId to avoid overflow.
+        String offerId = UnsignedLongs.toString(priceDropPayload.getOfferId());
         ChromeMessage chromeMessage = chromeNotification.getChromeMessage();
         PriceDropNotifier.NotificationData notificationData =
                 new PriceDropNotifier.NotificationData(title, text,
diff --git a/chrome/browser/component_updater/media_foundation_widevine_cdm_component_installer.cc b/chrome/browser/component_updater/media_foundation_widevine_cdm_component_installer.cc
index fa5ea52b..c7644815 100644
--- a/chrome/browser/component_updater/media_foundation_widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/media_foundation_widevine_cdm_component_installer.cc
@@ -105,7 +105,7 @@
   content::CdmInfo cdm_info(
       kWidevineKeySystem, content::CdmInfo::Robustness::kHardwareSecure,
       /*capability=*/absl::nullopt, /*supports_sub_key_systems=*/false,
-      kMediaFoundationWidevineCdmDisplayName, kMediaFoundationWidevineCdmGuid,
+      kMediaFoundationWidevineCdmDisplayName, kMediaFoundationWidevineCdmType,
       version, GetCdmPath(install_dir), /*file_system_id=*/"");
   content::CdmRegistry::GetInstance()->RegisterCdm(cdm_info);
 }
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index a5bb502..5d35673 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -123,7 +123,7 @@
   content::CdmInfo cdm_info(
       kWidevineKeySystem, content::CdmInfo::Robustness::kSoftwareSecure,
       std::move(capability), /*supports_sub_key_systems=*/false,
-      kWidevineCdmDisplayName, kWidevineCdmGuid, cdm_version, cdm_path,
+      kWidevineCdmDisplayName, kWidevineCdmType, cdm_version, cdm_path,
       kWidevineCdmFileSystemId);
   CdmRegistry::GetInstance()->RegisterCdm(cdm_info);
 }
diff --git a/chrome/browser/download/download_ui_controller_unittest.cc b/chrome/browser/download/download_ui_controller_unittest.cc
index 432718c8..8890efed 100644
--- a/chrome/browser/download/download_ui_controller_unittest.cc
+++ b/chrome/browser/download/download_ui_controller_unittest.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/download/download_history.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ssl/security_state_tab_helper.h"
-#include "chrome/browser/ssl/tls_deprecation_test_utils.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/download/public/common/mock_download_item.h"
 #include "components/history/core/browser/download_row.h"
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
index 79e6ba3..9243460 100644
--- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
+++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -734,41 +734,6 @@
   EXPECT_TRUE(GetAllProvidedCertificates().empty());
 }
 
-// Tests the RSA MD5/SHA-1 signature algorithm. Note that TLS 1.1 is used in
-// order to make this algorithm employed.
-IN_PROC_BROWSER_TEST_F(CertificateProviderApiMockedExtensionTest, RsaMd5Sha1) {
-  ASSERT_TRUE(StartHttpsServer(net::SSL_PROTOCOL_VERSION_TLS1_1));
-
-  // Bypass the legacy TLS interstitial. Future connections to the test server
-  // will now succeed.
-  SetInterstitialBypass();
-
-  ExecuteJavascript("supportedAlgorithms = ['RSASSA_PKCS1_v1_5_MD5_SHA1'];");
-  ExecuteJavascript("registerForSignatureRequests();");
-  ExecuteJavascriptAndWaitForCallback("setCertificates();");
-  TestNavigationToCertificateRequestingWebPage("RSASSA_PKCS1_v1_5_MD5_SHA1",
-                                               SSL_SIGN_RSA_PKCS1_MD5_SHA1,
-                                               /*is_raw_data=*/true);
-}
-
-// Tests the RSA MD5/SHA-1 signature algorithm using the legacy version of the
-// API. Note that TLS 1.1 is used in order to make this algorithm employed.
-IN_PROC_BROWSER_TEST_F(CertificateProviderApiMockedExtensionTest,
-                       LegacyRsaMd5Sha1) {
-  ASSERT_TRUE(StartHttpsServer(net::SSL_PROTOCOL_VERSION_TLS1_1));
-
-  // Bypass the legacy TLS interstitial. Future connections to the test server
-  // will now succeed.
-  SetInterstitialBypass();
-
-  ExecuteJavascript("supportedLegacyHashes = ['MD5_SHA1'];");
-  ExecuteJavascript("registerAsLegacyCertificateProvider();");
-  ExecuteJavascript("registerForLegacySignatureRequests();");
-  TestNavigationToCertificateRequestingWebPage("MD5_SHA1",
-                                               SSL_SIGN_RSA_PKCS1_MD5_SHA1,
-                                               /*is_raw_data=*/false);
-}
-
 // Tests the RSA SHA-1 signature algorithm.
 IN_PROC_BROWSER_TEST_F(CertificateProviderApiMockedExtensionTest, RsaSha1) {
   ASSERT_TRUE(StartHttpsServer(net::SSL_PROTOCOL_VERSION_TLS1_2));
@@ -878,27 +843,6 @@
                                                /*is_raw_data=*/true);
 }
 
-// Tests that the RSA MD5/SHA-1 signature algorithm is used in case of TLS 1.1,
-// even when there are other algorithms specified (which are stronger but aren't
-// supported on TLS 1.1).
-IN_PROC_BROWSER_TEST_F(CertificateProviderApiMockedExtensionTest,
-                       RsaMd5Sha1AndOthers) {
-  ASSERT_TRUE(StartHttpsServer(net::SSL_PROTOCOL_VERSION_TLS1_1));
-
-  // Bypass the legacy TLS interstitial. Future connections to the test server
-  // will now succeed.
-  SetInterstitialBypass();
-
-  ExecuteJavascript(
-      "supportedAlgorithms = ['RSASSA_PKCS1_v1_5_SHA512', "
-      "'RSASSA_PKCS1_v1_5_SHA1', 'RSASSA_PKCS1_v1_5_MD5_SHA1'];");
-  ExecuteJavascript("registerForSignatureRequests();");
-  ExecuteJavascriptAndWaitForCallback("setCertificates();");
-  TestNavigationToCertificateRequestingWebPage("RSASSA_PKCS1_v1_5_MD5_SHA1",
-                                               SSL_SIGN_RSA_PKCS1_MD5_SHA1,
-                                               /*is_raw_data=*/true);
-}
-
 // Tests the RSA-PSS SHA-256 signature algorithm.
 IN_PROC_BROWSER_TEST_F(CertificateProviderApiMockedExtensionTest,
                        RsaPssSha256) {
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
index fcae3b1a..d749a6f 100644
--- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
+++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -24,6 +24,10 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
 
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ui/ozone/buildflags.h"
+#endif  // OS_LINUX || BUILDFLAG(IS_CHROMEOS_ASH)
+
 using content::DesktopMediaID;
 using content::WebContentsMediaCaptureId;
 
@@ -139,8 +143,24 @@
   ASSERT_TRUE(RunExtensionTest("desktop_capture")) << message_;
 }
 
-// Test is flaky http://crbug.com/301887.
-IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, DISABLED_Delegation) {
+// The build flag OZONE_PLATFORM_WAYLAND is only available on
+// Linux or ChromeOS, so this simplifies the next set of ifdefs.
+#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(OZONE_PLATFORM_WAYLAND)
+#define OZONE_PLATFORM_WAYLAND
+#endif  // BUILDFLAG(OZONE_PLATFORM_WAYLAND)
+#endif  // OS_LINUX || BUILDFLAG(IS_CHROMEOS_ASH)
+
+// TODO(https://crbug.com/1271673): Crashes on Lacros.
+// TODO(https://crbug.com/1271680): Fails on the linux-wayland-rel bot.
+// TODO(https://crbug.com/1271711): Fails on Mac.
+#if defined(OS_MAC) || defined(OZONE_PLATFORM_WAYLAND) || \
+    BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_Delegation DISABLED_Delegation
+#else
+#define MAYBE_Delegation Delegation
+#endif
+IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, MAYBE_Delegation) {
   // Initialize test server.
   base::FilePath test_data;
   EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data));
@@ -155,16 +175,22 @@
   ASSERT_TRUE(extension);
 
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), GetURLForPath("example.com", "/example.com.html")));
+      browser(), GetURLForPath("localhost", "/example.com.html")));
 
-  FakeDesktopMediaPickerFactory::TestFlags test_flags[] = {
-      {true, true, false, false, false,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId)},
-      {true, true, false, false, false,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId)},
-      {true, true, false, false, false,
-       DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId),
-       true},
+  static FakeDesktopMediaPickerFactory::TestFlags test_flags[] = {
+      {.expect_screens = true,
+       .expect_windows = true,
+       .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN,
+                                         webrtc::kFullDesktopScreenId)},
+      {.expect_screens = true,
+       .expect_windows = true,
+       .selected_source = DesktopMediaID(DesktopMediaID::TYPE_SCREEN,
+                                         DesktopMediaID::kNullId)},
+      {.expect_screens = true,
+       .expect_windows = true,
+       .selected_source =
+           DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId),
+       .cancelled = true},
   };
   picker_factory_.SetTestFlags(test_flags, base::size(test_flags));
 
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
index bb0d328..5723f8e 100644
--- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -61,13 +61,13 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc b/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
index 0c860964..bf048981 100644
--- a/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
@@ -174,6 +174,15 @@
   ASSERT_TRUE(RunExtensionTest("tabs/last_focused_window")) << message_;
 }
 
+// TODO(http://crbug.com/58229): The Linux and Lacros window managers
+// behave differently, which complicates the test. A separate  test should
+// be written for them to avoid complicating this one.
+#if !defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS)
+IN_PROC_BROWSER_TEST_P(NonPersistentExtensionTabsTest, WindowSetFocus) {
+  ASSERT_TRUE(RunExtensionTest("window_update/set_focus")) << message_;
+}
+#endif
+
 INSTANTIATE_TEST_SUITE_P(EventPage,
                          NonPersistentExtensionTabsTest,
                          ::testing::Values(ContextType::kEventPage));
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 2eccb45..dd0e1f08 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -786,6 +786,10 @@
                            DisableExtensionWhenSwitchingBetweenGreylistStates);
   FRIEND_TEST_ALL_PREFIXES(SafeBrowsingVerdictHandlerUnitTest,
                            AcknowledgedStateBackFilled);
+  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingVerdictHandlerUnitTest,
+                           ExtensionUninstalledWhenBlocklisted);
+  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingVerdictHandlerUnitTest,
+                           ExtensionUninstalledWhenBlocklistFetching);
   friend class ::BlocklistedExtensionSyncServiceTest;
   friend class SafeBrowsingVerdictHandlerUnitTest;
   friend class BlocklistStatesInteractionUnitTest;
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index aa3066b5..aa8fa29c 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -401,9 +401,13 @@
 // Test that loading an extension with a browser action does not create a
 // background page and that clicking on the action creates the appropriate
 // ExtensionHost.
-// Disabled due to flake, see http://crbug.com/315242
-IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
-                       DISABLED_PopupHostCreation) {
+// TODO(http://crbug.com/1271329): Times out frequently on Lacros.
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_PopupHostCreation DISABLED_PopupHostCreation
+#else
+#define MAYBE_PopupHostCreation PopupHostCreation
+#endif
+IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, MAYBE_PopupHostCreation) {
   ProcessManager* pm = ProcessManager::Get(profile());
 
   // Load an extension with the ability to open a popup but no background
@@ -445,7 +449,6 @@
   EXPECT_FALSE(pm->IsBackgroundHostClosing(popup->id()));
   EXPECT_EQ(-1, pm->GetLazyKeepaliveCount(popup.get()));
   EXPECT_TRUE(pm->GetLazyKeepaliveActivities(popup.get()).empty());
-  EXPECT_TRUE(pm->GetLazyKeepaliveActivities(popup.get()).empty());
 }
 
 // Content loaded from http://hlogonemlfkgpejgnedahbkiabcdhnnn should not
diff --git a/chrome/browser/extensions/safe_browsing_verdict_handler.cc b/chrome/browser/extensions/safe_browsing_verdict_handler.cc
index 71cb0f2..a8bc951 100644
--- a/chrome/browser/extensions/safe_browsing_verdict_handler.cc
+++ b/chrome/browser/extensions/safe_browsing_verdict_handler.cc
@@ -38,7 +38,11 @@
     ExtensionService* extension_service)
     : extension_prefs_(extension_prefs),
       registry_(registry),
-      extension_service_(extension_service) {}
+      extension_service_(extension_service) {
+  extension_registry_observation_.Observe(registry_);
+}
+
+SafeBrowsingVerdictHandler::~SafeBrowsingVerdictHandler() = default;
 
 void SafeBrowsingVerdictHandler::Init() {
   TRACE_EVENT0("browser,startup", "SafeBrowsingVerdictHandler::Init");
@@ -71,7 +75,14 @@
   ExtensionIdSet greylist;
   ExtensionIdSet unchanged;
 
+  ExtensionIdSet installed_ids =
+      registry_->GenerateInstalledExtensionsSet()->GetIDs();
   for (const auto& it : state_map) {
+    // It is possible that an extension is uninstalled when the blocklist is
+    // fetching asynchronously. In this case, we should ignore this extension.
+    if (!base::Contains(installed_ids, it.first)) {
+      continue;
+    }
     switch (it.second) {
       case NOT_BLOCKLISTED:
         break;
@@ -116,11 +127,8 @@
   for (const auto& id : not_yet_blocked) {
     scoped_refptr<const Extension> extension =
         registry_->GetInstalledExtension(id);
-    if (!extension.get()) {
-      NOTREACHED() << "Extension " << id << " needs to be "
-                   << "blocklisted, but it's not installed.";
-      continue;
-    }
+    DCHECK(extension.get()) << "Extension " << id << " needs to be "
+                            << "blocklisted, but it's not installed.";
 
     blocklist_.Insert(extension);
     blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
@@ -142,11 +150,8 @@
 
   for (const auto& id : no_longer_greylisted) {
     scoped_refptr<const Extension> extension = greylist_.GetByID(id);
-    if (!extension.get()) {
-      NOTREACHED() << "Extension " << id << " no longer greylisted, "
-                   << "but it was not marked as greylisted.";
-      continue;
-    }
+    DCHECK(extension.get()) << "Extension " << id << " no longer greylisted, "
+                            << "but it was not marked as greylisted.";
 
     greylist_.Remove(id);
     blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
@@ -163,11 +168,8 @@
   for (const auto& id : greylist) {
     scoped_refptr<const Extension> extension =
         registry_->GetInstalledExtension(id);
-    if (!extension.get()) {
-      NOTREACHED() << "Extension " << id << " needs to be "
-                   << "disabled, but it's not installed.";
-      continue;
-    }
+    DCHECK(extension.get()) << "Extension " << id << " needs to be "
+                            << "disabled, but it's not installed.";
 
     greylist_.Insert(extension);
     BlocklistState greylist_state = state_map.find(id)->second;
@@ -181,4 +183,12 @@
   }
 }
 
+void SafeBrowsingVerdictHandler::OnExtensionUninstalled(
+    content::BrowserContext* browser_context,
+    const extensions::Extension* extension,
+    extensions::UninstallReason reason) {
+  blocklist_.Remove(extension->id());
+  greylist_.Remove(extension->id());
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/safe_browsing_verdict_handler.h b/chrome/browser/extensions/safe_browsing_verdict_handler.h
index 45f9460..a7f1f8f6 100644
--- a/chrome/browser/extensions/safe_browsing_verdict_handler.h
+++ b/chrome/browser/extensions/safe_browsing_verdict_handler.h
@@ -5,16 +5,18 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_SAFE_BROWSING_VERDICT_HANDLER_H_
 #define CHROME_BROWSER_EXTENSIONS_SAFE_BROWSING_VERDICT_HANDLER_H_
 
+#include "base/scoped_observation.h"
 #include "chrome/browser/extensions/blocklist.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/extension_set.h"
 
 namespace extensions {
 class ExtensionPrefs;
-class ExtensionRegistry;
 class ExtensionService;
 
 // Manages the Safe Browsing blocklist/greylist state in extension pref.
-class SafeBrowsingVerdictHandler {
+class SafeBrowsingVerdictHandler : public ExtensionRegistryObserver {
  public:
   SafeBrowsingVerdictHandler(ExtensionPrefs* extension_prefs,
                              ExtensionRegistry* registry,
@@ -22,7 +24,7 @@
   SafeBrowsingVerdictHandler(const SafeBrowsingVerdictHandler&) = delete;
   SafeBrowsingVerdictHandler& operator=(const SafeBrowsingVerdictHandler&) =
       delete;
-  ~SafeBrowsingVerdictHandler() = default;
+  ~SafeBrowsingVerdictHandler() override;
 
   // Initializes and load greylist from prefs.
   void Init();
@@ -46,6 +48,14 @@
       const ExtensionIdSet& unchanged,
       const Blocklist::BlocklistStateMap& state_map);
 
+  // ExtensionRegistryObserver overrides.
+  void OnExtensionUninstalled(content::BrowserContext* browser_context,
+                              const extensions::Extension* extension,
+                              extensions::UninstallReason reason) override;
+
+  base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
+      extension_registry_observation_{this};
+
   ExtensionPrefs* extension_prefs_ = nullptr;
   ExtensionRegistry* registry_ = nullptr;
   ExtensionService* extension_service_ = nullptr;
diff --git a/chrome/browser/extensions/safe_browsing_verdict_handler_unittest.cc b/chrome/browser/extensions/safe_browsing_verdict_handler_unittest.cc
index 9c06e05..ca35cb7 100644
--- a/chrome/browser/extensions/safe_browsing_verdict_handler_unittest.cc
+++ b/chrome/browser/extensions/safe_browsing_verdict_handler_unittest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/extensions/test_blocklist.h"
 #include "components/safe_browsing/buildflags.h"
 #include "extensions/browser/blocklist_extension_prefs.h"
+#include "extensions/browser/blocklist_state.h"
 #include "extensions/test/extension_state_tester.h"
 
 // The blocklist tests rely on the safe-browsing database.
@@ -445,6 +446,62 @@
   EXPECT_TRUE(state_tester.ExpectEnabled(kGood0));
 }
 
+// Regression test for https://crbug.com/1267860. It should not crash if the
+// extension is uninstalled before it is removed from the blocklist.
+TEST_F(SafeBrowsingVerdictHandlerUnitTest,
+       ExtensionUninstalledWhenBlocklisted) {
+  TestBlocklist test_blocklist;
+  // A profile with 3 extensions installed: kGood0, kGood1, and kGood2.
+  InitializeGoodInstalledExtensionService();
+  test_blocklist.Attach(service()->blocklist_);
+  service()->Init();
+
+  SetBlocklistStateForExtension(kGood0, BLOCKLISTED_MALWARE, test_blocklist);
+
+  ExtensionStateTester state_tester(profile());
+
+  // kGood0 is blocklisted.
+  EXPECT_TRUE(state_tester.ExpectBlocklisted(kGood0));
+
+  // Now uninstall kGood0.
+  service()->UninstallExtension(kGood0, UNINSTALL_REASON_FOR_TESTING, nullptr);
+  // kGood0 should be removed from the blocklist.
+  EXPECT_EQ(0u, registry()->blocklisted_extensions().size());
+
+  // Should not crash.
+  SetBlocklistStateForExtension(kGood0, NOT_BLOCKLISTED, test_blocklist);
+}
+
+// Regression test for https://crbug.com/1267860. It should not crash if the
+// extension is uninstalled during blocklist fetching.
+TEST_F(SafeBrowsingVerdictHandlerUnitTest,
+       ExtensionUninstalledWhenBlocklistFetching) {
+  TestBlocklist test_blocklist;
+  // A profile with 3 extensions installed: kGood0, kGood1, and kGood2.
+  InitializeGoodInstalledExtensionService();
+  test_blocklist.Attach(service()->blocklist_);
+  service()->Init();
+
+  SetBlocklistStateForExtension(kGood0, BLOCKLISTED_MALWARE, test_blocklist);
+
+  ExtensionStateTester state_tester(profile());
+
+  // kGood0 is blocklisted.
+  EXPECT_TRUE(state_tester.ExpectBlocklisted(kGood0));
+
+  service()->blocklist_->ResetBlocklistStateCacheForTest();
+  // Use TestBlocklist::SetBlocklistState() here instead of
+  // SetBlocklistStateForExtension(). This makes the blocklisting process
+  // asynchronous, so that we can simulate uninstalling the extension
+  // during a blocklist state fetch.
+  test_blocklist.SetBlocklistState(kGood0, BLOCKLISTED_MALWARE, true);
+
+  // Uninstalled the extension in the middle of the update.
+  service()->UninstallExtension(kGood0, UNINSTALL_REASON_FOR_TESTING, nullptr);
+  // Should not crash when the update finishes.
+  task_environment()->RunUntilIdle();
+}
+
 #endif  // defined(ENABLE_BLOCKLIST_TESTS)
 
 }  // namespace extensions
diff --git a/chrome/browser/feed/android/feed_process_scope_dependency_provider.cc b/chrome/browser/feed/android/feed_process_scope_dependency_provider.cc
index 4c8d76a..916ce25 100644
--- a/chrome/browser/feed/android/feed_process_scope_dependency_provider.cc
+++ b/chrome/browser/feed/android/feed_process_scope_dependency_provider.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/feed/android/jni_headers/FeedProcessScopeDependencyProvider_jni.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "components/feed/core/proto/v2/ui.pb.h"
 #include "components/feed/core/v2/public/feed_api.h"
 #include "components/feed/core/v2/public/feed_service.h"
 #include "components/feed/core/v2/public/feed_stream_surface.h"
@@ -36,6 +37,28 @@
   feed_stream_api->ProcessViewAction(data_string);
 }
 
+static void
+JNI_FeedProcessScopeDependencyProvider_ProcessViewActionWithLoggingParameters(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jbyteArray>& action_data,
+    const base::android::JavaParamRef<jbyteArray>& logging_parameters) {
+  FeedApi* feed_stream_api = GetFeedApi();
+  if (!feed_stream_api)
+    return;
+  std::string action_data_string;
+  base::android::JavaByteArrayToString(env, action_data, &action_data_string);
+  std::string logging_parameters_string;
+  base::android::JavaByteArrayToString(env, logging_parameters,
+                                       &logging_parameters_string);
+  feedui::LoggingParameters logging_parameters_value;
+  if (!logging_parameters_value.ParseFromString(logging_parameters_string)) {
+    DLOG(ERROR) << "Error parsing logging parameters";
+    return;
+  }
+  feed_stream_api->ProcessViewAction(action_data_string,
+                                     logging_parameters_value);
+}
+
 static base::android::ScopedJavaLocalRef<jstring>
 JNI_FeedProcessScopeDependencyProvider_GetSessionId(JNIEnv* env) {
   std::string session;
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParameters.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParameters.java
index 7fa8468..0e100e82 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParameters.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParameters.java
@@ -13,21 +13,34 @@
  */
 class FeedLoggingParameters implements LoggingParameters {
     private final String mClientInstanceId;
-    private final String mSignedOutSessionId;
     private final String mAccountName;
+    private final boolean mLoggingEnabled;
+    private final boolean mViewActionsEnabled;
 
     /**
      * Creates logging parameters. Creation of this implies that logging is enabled.
      */
-    public FeedLoggingParameters(
-            String clientInstanceId, String accountName, String signedOutSessionId) {
+    public FeedLoggingParameters(String clientInstanceId, String accountName,
+            boolean loggingEnabled, boolean viewActionsEnabled) {
         mClientInstanceId = clientInstanceId;
-        mSignedOutSessionId = signedOutSessionId;
         mAccountName = accountName;
+        mLoggingEnabled = loggingEnabled;
+        mViewActionsEnabled = viewActionsEnabled;
     }
 
     public FeedLoggingParameters(FeedUiProto.LoggingParameters proto) {
-        this(proto.getClientInstanceId(), proto.getEmail(), proto.getSessionId());
+        this(proto.getClientInstanceId(), proto.getEmail(), proto.getLoggingEnabled(),
+                proto.getViewActionsEnabled());
+    }
+
+    public static FeedUiProto.LoggingParameters convertToProto(
+            LoggingParameters loggingParameters) {
+        return FeedUiProto.LoggingParameters.newBuilder()
+                .setEmail(loggingParameters.accountName())
+                .setClientInstanceId(loggingParameters.clientInstanceId())
+                .setLoggingEnabled(loggingParameters.loggingEnabled())
+                .setViewActionsEnabled(loggingParameters.viewActionsEnabled())
+                .build();
     }
 
     @Override
@@ -39,18 +52,23 @@
         return mClientInstanceId;
     }
     @Override
-    public String signedOutSessionId() {
-        return mSignedOutSessionId;
-    }
-    @Override
     public boolean loggingParametersEquals(LoggingParameters otherObject) {
         if (otherObject == null) {
             return false;
         }
         FeedLoggingParameters rhs = (FeedLoggingParameters) otherObject;
-        return nullableStringEqual(mAccountName, rhs.mAccountName)
-                && nullableStringEqual(mClientInstanceId, rhs.mClientInstanceId)
-                && nullableStringEqual(mSignedOutSessionId, rhs.mSignedOutSessionId);
+        return mLoggingEnabled == rhs.mLoggingEnabled
+                && mViewActionsEnabled == rhs.mViewActionsEnabled
+                && nullableStringEqual(mAccountName, rhs.mAccountName)
+                && nullableStringEqual(mClientInstanceId, rhs.mClientInstanceId);
+    }
+    @Override
+    public boolean loggingEnabled() {
+        return mLoggingEnabled;
+    }
+    @Override
+    public boolean viewActionsEnabled() {
+        return mViewActionsEnabled;
     }
     static boolean nullableStringEqual(@Nullable String a, @Nullable String b) {
         return (a == null ? "" : a).equals(b == null ? "" : b);
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParametersTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParametersTest.java
index 108ec0b..279788e 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParametersTest.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedLoggingParametersTest.java
@@ -23,25 +23,39 @@
     @Test
     @SmallTest
     public void testEquality() {
-        FeedLoggingParameters allNull = new FeedLoggingParameters(null, null, null);
+        FeedLoggingParameters allNull = new FeedLoggingParameters(null, null, false, false);
 
         assertFalse(allNull.loggingParametersEquals(null));
 
         // Null and empty string are considered equivalent.
-        assertTrue(new FeedLoggingParameters("", "", "").loggingParametersEquals(allNull));
-        assertTrue(allNull.loggingParametersEquals(new FeedLoggingParameters("", "", "")));
-        assertFalse(new FeedLoggingParameters(null, null, "a").loggingParametersEquals(allNull));
-        assertFalse(new FeedLoggingParameters(null, "a", null).loggingParametersEquals(allNull));
-        assertFalse(new FeedLoggingParameters("a", null, null).loggingParametersEquals(allNull));
+        assertTrue(
+                new FeedLoggingParameters("", "", false, false).loggingParametersEquals(allNull));
+        assertTrue(
+                allNull.loggingParametersEquals(new FeedLoggingParameters("", "", false, false)));
+        assertFalse(new FeedLoggingParameters(null, null, false, true)
+                            .loggingParametersEquals(allNull));
+        assertFalse(new FeedLoggingParameters(null, null, true, false)
+                            .loggingParametersEquals(allNull));
+        assertFalse(new FeedLoggingParameters(null, "a", false, false)
+                            .loggingParametersEquals(allNull));
+        assertFalse(new FeedLoggingParameters("a", null, false, false)
+                            .loggingParametersEquals(allNull));
 
-        assertTrue(new FeedLoggingParameters("a", "b", "c")
-                           .loggingParametersEquals(new FeedLoggingParameters("a", "b", "c")));
-        assertFalse(new FeedLoggingParameters("a", "b", "c")
-                            .loggingParametersEquals(new FeedLoggingParameters("x", "b", "c")));
-        assertFalse(new FeedLoggingParameters("a", "b", "c")
-                            .loggingParametersEquals(new FeedLoggingParameters("a", "x", "c")));
-        assertFalse(new FeedLoggingParameters("a", "b", "c")
-                            .loggingParametersEquals(new FeedLoggingParameters("a", "x", "x")));
+        assertTrue(
+                new FeedLoggingParameters("a", "b", true, true)
+                        .loggingParametersEquals(new FeedLoggingParameters("a", "b", true, true)));
+        assertFalse(
+                new FeedLoggingParameters("a", "b", true, true)
+                        .loggingParametersEquals(new FeedLoggingParameters("x", "b", true, true)));
+        assertFalse(
+                new FeedLoggingParameters("a", "b", true, true)
+                        .loggingParametersEquals(new FeedLoggingParameters("a", "x", true, true)));
+        assertFalse(
+                new FeedLoggingParameters("a", "b", true, true)
+                        .loggingParametersEquals(new FeedLoggingParameters("a", "b", false, true)));
+        assertFalse(
+                new FeedLoggingParameters("a", "b", true, true)
+                        .loggingParametersEquals(new FeedLoggingParameters("a", "b", true, false)));
     }
 
     @Test
@@ -50,9 +64,10 @@
         FeedUiProto.LoggingParameters proto = FeedUiProto.LoggingParameters.newBuilder()
                                                       .setEmail("user@foo.com")
                                                       .setClientInstanceId("cid")
-                                                      .setSessionId("session")
+                                                      .setLoggingEnabled(true)
+                                                      .setViewActionsEnabled(false)
                                                       .build();
         assertTrue(new FeedLoggingParameters(proto).loggingParametersEquals(
-                new FeedLoggingParameters("cid", "user@foo.com", "session")));
+                new FeedLoggingParameters("cid", "user@foo.com", true, false)));
     }
 }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeDependencyProvider.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeDependencyProvider.java
index f95210c3..d1ebe99 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeDependencyProvider.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeDependencyProvider.java
@@ -23,6 +23,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.xsurface.ImageFetchClient;
+import org.chromium.chrome.browser.xsurface.LoggingParameters;
 import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache;
 import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider;
 import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider.VisibilityLogType;
@@ -199,6 +200,11 @@
     public void processViewAction(byte[] data) {
         FeedProcessScopeDependencyProviderJni.get().processViewAction(data);
     }
+    @Override
+    public void processViewAction(byte[] data, LoggingParameters loggingParameters) {
+        FeedProcessScopeDependencyProviderJni.get().processViewActionWithLoggingParameters(
+                data, FeedLoggingParameters.convertToProto(loggingParameters).toByteArray());
+    }
 
     @Override
     public void reportOnUploadVisibilityLog(@VisibilityLogType int logType, boolean success) {
@@ -232,5 +238,6 @@
         int[] getExperimentIds();
         String getSessionId();
         void processViewAction(byte[] data);
+        void processViewActionWithLoggingParameters(byte[] actionData, byte[] loggingParameters);
     }
 }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NtpListContentManagerTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NtpListContentManagerTest.java
index 5f4b2e6..68aca9b 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NtpListContentManagerTest.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NtpListContentManagerTest.java
@@ -59,10 +59,10 @@
     private int mItemMovedCurIndex;
     private int mItemMovedNewIndex;
     private String mObservedChanges = "";
-    private final FeedLoggingParameters mLoggingParametersA =
-            new FeedLoggingParameters("instance-id", "A", "");
-    private final FeedLoggingParameters mLoggingParametersB =
-            new FeedLoggingParameters("instance-id", "", "B");
+    private final FeedLoggingParameters mLoggingParametersA = new FeedLoggingParameters(
+            "instance-id", "A", /*loggingEnabled=*/true, /*viewActionsEnabled=*/true);
+    private final FeedLoggingParameters mLoggingParametersB = new FeedLoggingParameters(
+            "instance-id", "B", /*loggingEnabled=*/true, /*viewActionsEnabled=*/true);
 
     @Before
     public void setUp() {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 7c51263..62a7055 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -64,11 +64,6 @@
     "expiry_milestone": 100
   },
   {
-    "name": "align-font-display-auto-lcp",
-    "owners": [ "xiaochengh" ],
-    "expiry_milestone": 87
-  },
-  {
     "name": "allow-all-sites-to-initiate-mirroring",
     "owners": [ "takumif", "openscreen-eng@google.com" ],
     // This flag is used in regular manual QA and should not be removed.
@@ -1724,6 +1719,11 @@
     "expiry_milestone": 100
   },
   {
+    "name": "enable-css-selector-fragment-anchor",
+    "owners": [ "mehdika", "blink-interactions-team@google.com" ],
+    "expiry_milestone": 102
+  },
+  {
     "name": "enable-dangerous-download-dialog",
     "owners": [ "qinmin", "chrome-downloads@google.com" ],
     "expiry_milestone": 99
@@ -5397,6 +5397,11 @@
     "expiry_milestone": -1
   },
   {
+    "name" : "unified-side-panel",
+    "owners": [ "chrome-desktop-ui-sea@google.com", "corising", "pbos", "tluk" ],
+    "expiry_milestone" : 105
+  },
+  {
     "name": "unsafely-treat-insecure-origin-as-secure",
     "owners": [ "security-dev" ],
     // This flag is supported for bypassing security restrictions on HTTP pages,
@@ -5586,11 +5591,6 @@
     "expiry_milestone": 98
   },
   {
-    "name": "wallpaper-webui",
-    "owners": [ "cowmoo@google.com", "assistive-eng@google.com" ],
-    "expiry_milestone": 98
-  },
-  {
     "name": "web-apps-crosapi",
     "owners": [ "mxcai", "raymes", "chromeos-apps-foundation-team@google.com" ],
     "expiry_milestone": 98
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f062f9f..d8f3692 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -54,13 +54,6 @@
     "To evaluate an enhanced Launcher experience that enables users to reorder "
     "their apps in order to find them more easily.";
 
-const char kAlignFontDisplayAutoTimeoutWithLCPGoalName[] =
-    "Align 'font-display: auto' timeout with LCP goal";
-const char kAlignFontDisplayAutoTimeoutWithLCPGoalDescription[] =
-    "Make pending 'display: auto' web fonts enter the swap or failure period "
-    "immediately before reaching the LCP time limit (~2500ms), so that web "
-    "fonts do not become a source of bad LCP (Largest Contentful Paint).";
-
 const char kAllowInsecureLocalhostName[] =
     "Allow invalid certificates for resources loaded from localhost.";
 const char kAllowInsecureLocalhostDescription[] =
@@ -1202,6 +1195,12 @@
     "Reduces the velocity of horizontal flings to 20\% of their original"
     "velocity.";
 
+const char kEnableCssSelectorFragmentAnchorName[] =
+    "Enables CSS selector fragment anchors";
+const char kEnableCssSelectorFragmentAnchorDescription[] =
+    "Similar to text directives, CSS selector directives can be specified "
+    "in a url which is to be scrolled into view and highlighted.";
+
 const char kRetailCouponsName[] = "Enable to fetch for retail coupons";
 const char kRetailCouponsDescription[] =
     "Allow to fetch retail coupons for consented users";
@@ -2586,6 +2585,10 @@
     "Reduces disk activity during media playback, which can result in "
     "power savings.";
 
+const char kUnifiedSidePanelFlagId[] = "unified-side-panel";
+const char kUnifiedSidePanelName[] = "Unified side panel";
+const char kUnifiedSidePanelDescription[] = "Revamp the side panel experience.";
+
 const char kUnifiedPasswordManagerAndroidName[] =
     "Google Mobile Services for passwords";
 const char kUnifiedPasswordManagerAndroidDescription[] =
@@ -2664,11 +2667,6 @@
 const char kWalletServiceUseSandboxDescription[] =
     "For developers: use the sandbox service for Google Payments API calls.";
 
-const char kWallpaperWebUIName[] = "Enable new wallpaper experience";
-const char kWallpaperWebUIDescription[] =
-    "Enables the wallpaper picker "
-    "in ChromeOS Settings";
-
 const char kWallpaperFullScreenPreviewName[] =
     "Enable wallpaper full screen preview UI";
 const char kWallpaperFullScreenPreviewDescription[] =
@@ -3545,6 +3543,10 @@
     "#site-isolation-trial-opt-out for how to disable site isolation for "
     "testing.";
 
+const char kThemeRefactorAndroidName[] = "Theme refactor on Android";
+const char kThemeRefactorAndroidDescription[] =
+    "Enables the theme refactoring on Android.";
+
 const char kToolbarIphAndroidName[] = "Enable Toolbar IPH on Android";
 const char kToolbarIphAndroidDescription[] =
     "Enables in product help bubbles on the toolbar. In particular, the home "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 32fabe22..d8936244 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -69,9 +69,6 @@
 extern const char kAddPasswordsInSettingsName[];
 extern const char kAddPasswordsInSettingsDescription[];
 
-extern const char kAlignFontDisplayAutoTimeoutWithLCPGoalName[];
-extern const char kAlignFontDisplayAutoTimeoutWithLCPGoalDescription[];
-
 extern const char kAllowInsecureLocalhostName[];
 extern const char kAllowInsecureLocalhostDescription[];
 
@@ -691,6 +688,9 @@
 extern const char kRetailCouponsName[];
 extern const char kRetailCouponsDescription[];
 
+extern const char kEnableCssSelectorFragmentAnchorName[];
+extern const char kEnableCssSelectorFragmentAnchorDescription[];
+
 extern const char kEnableResamplingInputEventsName[];
 extern const char kEnableResamplingInputEventsDescription[];
 extern const char kEnableResamplingScrollEventsName[];
@@ -1493,6 +1493,10 @@
 extern const char kTurnOffStreamingMediaCachingAlwaysName[];
 extern const char kTurnOffStreamingMediaCachingAlwaysDescription[];
 
+extern const char kUnifiedSidePanelFlagId[];
+extern const char kUnifiedSidePanelName[];
+extern const char kUnifiedSidePanelDescription[];
+
 extern const char kUnifiedPasswordManagerAndroidName[];
 extern const char kUnifiedPasswordManagerAndroidDescription[];
 
@@ -1523,9 +1527,6 @@
 extern const char kWalletServiceUseSandboxName[];
 extern const char kWalletServiceUseSandboxDescription[];
 
-extern const char kWallpaperWebUIName[];
-extern const char kWallpaperWebUIDescription[];
-
 extern const char kWallpaperFullScreenPreviewName[];
 extern const char kWallpaperFullScreenPreviewDescription[];
 
@@ -2033,6 +2034,9 @@
 extern const char kStrictSiteIsolationName[];
 extern const char kStrictSiteIsolationDescription[];
 
+extern const char kThemeRefactorAndroidName[];
+extern const char kThemeRefactorAndroidDescription[];
+
 extern const char kToolbarIphAndroidName[];
 extern const char kToolbarIphAndroidDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index c8d8f110..4393696e 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -283,6 +283,7 @@
     &kTabToGTSAnimation,
     &kTestDefaultDisabled,
     &kTestDefaultEnabled,
+    &kThemeRefactorAndroid,
     &kToolbarIphAndroid,
     &kToolbarMicIphAndroid,
     &kTrustedWebActivityLocationDelegation,
@@ -582,7 +583,7 @@
                                              base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kDownloadProgressMessage{"DownloadProgressMessage",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kDownloadFileProvider{"DownloadFileProvider",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
@@ -759,6 +760,9 @@
 const base::Feature kTestDefaultEnabled{"TestDefaultEnabled",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kThemeRefactorAndroid{"ThemeRefactorAndroid",
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
+
 const base::Feature kToolbarIphAndroid{"ToolbarIphAndroid",
                                        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 c5d8f70..92496016 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -143,6 +143,7 @@
 extern const base::Feature kTabToGTSAnimation;
 extern const base::Feature kTestDefaultDisabled;
 extern const base::Feature kTestDefaultEnabled;
+extern const base::Feature kThemeRefactorAndroid;
 extern const base::Feature kToolbarIphAndroid;
 extern const base::Feature kToolbarMicIphAndroid;
 extern const base::Feature kToolbarUseHardwareBitmapDraw;
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 026bddd..566a807 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
@@ -82,6 +82,7 @@
                     .put(ChromeFeatureList.TEST_DEFAULT_DISABLED, false)
                     .put(ChromeFeatureList.TEST_DEFAULT_ENABLED, true)
                     .put(ChromeFeatureList.INTEREST_FEED_V2, true)
+                    .put(ChromeFeatureList.THEME_REFACTOR_ANDROID, false)
                     .put(ChromeFeatureList.USE_CHIME_ANDROID_SDK, false)
                     .put(ChromeFeatureList.CCT_INCOGNITO_AVAILABLE_TO_THIRD_PARTY, false)
                     .put(ChromeFeatureList.READ_LATER, 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 8e60be0..0b85e8d 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
@@ -518,6 +518,7 @@
     public static final String TAB_TO_GTS_ANIMATION = "TabToGTSAnimation";
     public static final String TEST_DEFAULT_DISABLED = "TestDefaultDisabled";
     public static final String TEST_DEFAULT_ENABLED = "TestDefaultEnabled";
+    public static final String THEME_REFACTOR_ANDROID = "ThemeRefactorAndroid";
     public static final String TOOLBAR_IPH_ANDROID = "ToolbarIphAndroid";
     public static final String TOOLBAR_MIC_IPH_ANDROID = "ToolbarMicIphAndroid";
     public static final String TOOLBAR_USE_HARDWARE_BITMAP_DRAW = "ToolbarUseHardwareBitmapDraw";
diff --git a/chrome/browser/history_clusters/history_clusters_service_factory.cc b/chrome/browser/history_clusters/history_clusters_service_factory.cc
index 03225c1..4fea5ca 100644
--- a/chrome/browser/history_clusters/history_clusters_service_factory.cc
+++ b/chrome/browser/history_clusters/history_clusters_service_factory.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/history_clusters/history_clusters_service_factory.h"
 
+#include "chrome/browser/engagement/site_engagement_service_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/optimization_guide/page_content_annotations_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -12,6 +13,7 @@
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/optimization_guide/content/browser/page_content_annotations_service.h"
+#include "components/site_engagement/content/site_engagement_service.h"
 #include "content/public/browser/storage_partition.h"
 
 // static
@@ -35,6 +37,7 @@
   DependsOn(HistoryServiceFactory::GetInstance());
   DependsOn(TemplateURLServiceFactory::GetInstance());
   DependsOn(PageContentAnnotationsServiceFactory::GetInstance());
+  DependsOn(site_engagement::SiteEngagementServiceFactory::GetInstance());
 }
 
 HistoryClustersServiceFactory::~HistoryClustersServiceFactory() = default;
@@ -55,7 +58,7 @@
   return new history_clusters::HistoryClustersService(
       history_service, TemplateURLServiceFactory::GetForProfile(profile),
       PageContentAnnotationsServiceFactory::GetForProfile(profile),
-      url_loader_factory);
+      url_loader_factory, site_engagement::SiteEngagementService::Get(profile));
 }
 
 content::BrowserContext* HistoryClustersServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/interstitials/security_interstitial_page_test_utils.cc b/chrome/browser/interstitials/security_interstitial_page_test_utils.cc
index ba3099f0..9f989863 100644
--- a/chrome/browser/interstitials/security_interstitial_page_test_utils.cc
+++ b/chrome/browser/interstitials/security_interstitial_page_test_utils.cc
@@ -80,12 +80,6 @@
                                       "Anything you type, any pages you view");
 }
 
-bool IsShowingLegacyTLSInterstitial(content::WebContents* tab) {
-  return IsShowingInterstitial(tab) &&
-         IsInterstitialDisplayingText(tab->GetMainFrame(),
-                                      "outdated security configuration");
-}
-
 bool IsShowingHttpsFirstModeInterstitial(content::WebContents* tab) {
   return IsShowingInterstitial(tab) &&
          IsInterstitialDisplayingText(tab->GetMainFrame(),
diff --git a/chrome/browser/interstitials/security_interstitial_page_test_utils.h b/chrome/browser/interstitials/security_interstitial_page_test_utils.h
index 102dd320..7ee50c3 100644
--- a/chrome/browser/interstitials/security_interstitial_page_test_utils.h
+++ b/chrome/browser/interstitials/security_interstitial_page_test_utils.h
@@ -52,9 +52,6 @@
 // Returns true if |tab| is displaying a known-interception interstitial.
 bool IsShowingBlockedInterceptionInterstitial(content::WebContents* tab);
 
-// Returns true if |tab| is displaying a legacy TLS interstitial.
-bool IsShowingLegacyTLSInterstitial(content::WebContents* tab);
-
 // Returns true if `tab` is displaying an HTTPS-First Mode interstitial.
 bool IsShowingHttpsFirstModeInterstitial(content::WebContents* tab);
 
diff --git a/chrome/browser/language/android/BUILD.gn b/chrome/browser/language/android/BUILD.gn
index d341805a..d8419cd8 100644
--- a/chrome/browser/language/android/BUILD.gn
+++ b/chrome/browser/language/android/BUILD.gn
@@ -14,7 +14,7 @@
   deps = [
     "//base:base_java",
     "//chrome/browser/preferences:java",
-    "//components/language/android:language_bridge_java",
+    "//components/language/android:java",
     "//third_party/android_deps:com_google_android_play_core_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//ui/android:ui_no_recycler_view_java",
@@ -53,7 +53,7 @@
     "//chrome/browser/ui/messages/android:java",
     "//components/browser_ui/settings/android:java",
     "//components/browser_ui/widget/android:java",
-    "//components/language/android:language_bridge_java",
+    "//components/language/android:java",
     "//components/prefs/android:java",
     "//components/user_prefs/android:java",
     "//content/public/android:content_java",
@@ -132,8 +132,7 @@
     "//components/browser_ui/settings/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/browser_ui/widget/android:test_support_java",
-    "//components/language/android:language_bridge_java",
-    "//components/language/android:language_bridge_javatests",
+    "//components/language/android:java",
     "//components/prefs/android:java",
     "//components/user_prefs/android:java",
     "//content/public/android:content_full_java",
diff --git a/chrome/browser/lifetime/browser_shutdown.cc b/chrome/browser/lifetime/browser_shutdown.cc
index 55287cc1..19dd213 100644
--- a/chrome/browser/lifetime/browser_shutdown.cc
+++ b/chrome/browser/lifetime/browser_shutdown.cc
@@ -74,15 +74,9 @@
 #endif
 
 #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) && BUILDFLAG(CLANG_PGO)
-#include "content/public/browser/browser_child_process_host_iterator.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/gpu_utils.h"
-#include "content/public/common/child_process_host.h"
-#include "content/public/common/profiling_utils.h"
+#include "content/public/browser/profiling_utils.h"
 #endif
 
-
 namespace browser_shutdown {
 namespace {
 
@@ -147,41 +141,7 @@
   // TODO(https://crbug.com/1071664): Check if this should also be enabled for
   // coverage builds.
 #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) && BUILDFLAG(CLANG_PGO)
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kSingleProcess)) {
-    content::WaitForProcessesToDumpProfilingInfo wait_for_profiling_data;
-
-    // Ask all the renderer processes to dump their profiling data.
-    for (content::RenderProcessHost::iterator i(
-             content::RenderProcessHost::AllHostsIterator());
-         !i.IsAtEnd(); i.Advance()) {
-      DCHECK(!i.GetCurrentValue()->GetProcess().is_current());
-      if (!i.GetCurrentValue()->IsInitializedAndNotDead())
-        continue;
-      i.GetCurrentValue()->DumpProfilingData(base::BindOnce(
-          &base::WaitableEvent::Signal,
-          base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
-    }
-
-    // Ask all the other child processes to dump their profiling data
-    for (content::BrowserChildProcessHostIterator browser_child_iter;
-         !browser_child_iter.Done(); ++browser_child_iter) {
-      browser_child_iter.GetHost()->DumpProfilingData(base::BindOnce(
-          &base::WaitableEvent::Signal,
-          base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
-    }
-
-    if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kInProcessGPU)) {
-      content::DumpGpuProfilingData(base::BindOnce(
-          &base::WaitableEvent::Signal,
-          base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
-    }
-
-    // This will block until all the child processes have saved their profiling
-    // data to disk.
-    wait_for_profiling_data.WaitForAll();
-  }
+  content::WaitForAllChildrenToDumpProfilingData();
 #endif  // BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) && BUILDFLAG(CLANG_PGO)
 
   // Call FastShutdown on all of the RenderProcessHosts.  This will be
@@ -190,7 +150,7 @@
   g_shutdown_num_processes = 0;
   g_shutdown_num_processes_slow = 0;
   for (content::RenderProcessHost::iterator i(
-          content::RenderProcessHost::AllHostsIterator());
+           content::RenderProcessHost::AllHostsIterator());
        !i.IsAtEnd(); i.Advance()) {
     ++g_shutdown_num_processes;
     if (!i.GetCurrentValue()->FastShutdownIfPossible())
diff --git a/chrome/browser/media/library_cdm_test_helper.h b/chrome/browser/media/library_cdm_test_helper.h
index 9809656..65723ccd 100644
--- a/chrome/browser/media/library_cdm_test_helper.h
+++ b/chrome/browser/media/library_cdm_test_helper.h
@@ -14,6 +14,6 @@
 void RegisterClearKeyCdm(base::CommandLine* command_line,
                          bool use_wrong_cdm_path = false);
 
-bool IsLibraryCdmRegistered(const base::Token& cdm_guid);
+bool IsLibraryCdmRegistered(const base::Token& cdm_type);
 
 #endif  // CHROME_BROWSER_MEDIA_LIBRARY_CDM_TEST_HELPER_H_
diff --git a/chrome/browser/media/router/discovery/access_code/OWNERS b/chrome/browser/media/router/discovery/access_code/OWNERS
index da84d320..21a5668 100644
--- a/chrome/browser/media/router/discovery/access_code/OWNERS
+++ b/chrome/browser/media/router/discovery/access_code/OWNERS
@@ -1,6 +1,4 @@
-file://chrome/browser/media/router/discovery/access_code/OWNERS
-
-# Cros Edu Team Members
+# ChromeOS EDU Team Members
 gbj@google.com
 bzielinski@google.com
 bmalcolm@google.com
diff --git a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
index 7bfff140..0f5a418 100644
--- a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
@@ -844,7 +844,9 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(GetDisplayMediaChangeSourceBrowserTest, ChangeSource) {
+// TODO(crbug.com/1272023): Flaky on Linux Wayland, Win7.
+IN_PROC_BROWSER_TEST_F(GetDisplayMediaChangeSourceBrowserTest,
+                       DISABLED_ChangeSource) {
   ASSERT_TRUE(embedded_test_server()->Start());
   content::WebContents* captured_tab = OpenTestPageInNewTab(kCapturedPageMain);
   content::WebContents* other_tab = OpenTestPageInNewTab(kMainHtmlPage);
@@ -874,10 +876,7 @@
   // Click the secondary button, i.e., the "Share this tab instead" button
   GetDelegate(other_tab)->Cancel();
 
-  // Wait until the capture of the other tab has started.
-  while (!other_tab->IsBeingCaptured()) {
-    base::RunLoop().RunUntilIdle();
-  }
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(captured_tab->IsBeingCaptured());
   EXPECT_TRUE(other_tab->IsBeingCaptured());
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc
index b1815599..0240d86 100644
--- a/chrome/browser/metrics/chrome_feature_list_creator.cc
+++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -171,6 +171,11 @@
   metrics_services_manager_->InstantiateFieldTrialList(
       cc::switches::kEnableGpuBenchmarking);
   auto feature_list = std::make_unique<base::FeatureList>();
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // On Chrome OS, the platform needs to be able to access the
+  // FeatureList::Accessor. On other platforms, this API should not be used.
+  cros_feature_list_accessor_ = feature_list->ConstructAccessor();
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Associate parameters chosen in about:flags and create trial/group for them.
   flags_ui::PrefServiceFlagsStorage flags_storage(local_state_.get());
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.h b/chrome/browser/metrics/chrome_feature_list_creator.h
index 51fd4d72..3b98f19 100644
--- a/chrome/browser/metrics/chrome_feature_list_creator.h
+++ b/chrome/browser/metrics/chrome_feature_list_creator.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "base/types/pass_key.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/chrome_browser_field_trials.h"
@@ -16,6 +17,10 @@
 #include "components/metrics_services_manager/metrics_services_manager.h"
 #include "components/prefs/pref_service.h"
 
+namespace ash {
+class ChromeBrowserMainPartsAsh;
+}  // namespace ash
+
 class ChromeMetricsServicesManagerClient;
 
 // The ChromeFeatureListCreator creates the FeatureList and classes required for
@@ -73,6 +78,15 @@
     return browser_field_trials_.get();
   }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // Get the FeatureList::Accessor, clearing immediately -- this must only be
+  // used by ChromeBrowserMainPartsAsh.
+  std::unique_ptr<base::FeatureList::Accessor> GetAndClearFeatureListAccessor(
+      base::PassKey<ash::ChromeBrowserMainPartsAsh> key) {
+    return std::move(cros_feature_list_accessor_);
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
  private:
   void CreatePrefService();
   void ConvertFlagsToSwitches();
@@ -107,6 +121,12 @@
 #if !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<installer::InitialPreferences> installer_initial_prefs_;
 #endif
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // On Chrome OS, the platform needs to be able to access the
+  // FeatureList::Accessor. On other platforms, this API should not be used.
+  std::unique_ptr<base::FeatureList::Accessor> cros_feature_list_accessor_;
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
 
 #endif  // CHROME_BROWSER_METRICS_CHROME_FEATURE_LIST_CREATOR_H_
diff --git a/chrome/browser/net/errorpage_browsertest.cc b/chrome/browser/net/errorpage_browsertest.cc
index 89e505fe..a875464 100644
--- a/chrome/browser/net/errorpage_browsertest.cc
+++ b/chrome/browser/net/errorpage_browsertest.cc
@@ -1083,7 +1083,7 @@
 };
 
 // TODO(https://crbug.com/1267299): Re-enable.
-#if defined(ADDRESS_SANITIZER)
+#if defined(ADDRESS_SANITIZER) | defined(OS_CHROMEOS)
 #define MAYBE_DiagnosticsConnectivity DISABLED_DiagnosticsConnectivity
 #else
 #define MAYBE_DiagnosticsConnectivity DiagnosticsConnectivity
diff --git a/chrome/browser/net/system_network_context_manager_browsertest.cc b/chrome/browser/net/system_network_context_manager_browsertest.cc
index 8fcb12c..2babc48f 100644
--- a/chrome/browser/net/system_network_context_manager_browsertest.cc
+++ b/chrome/browser/net/system_network_context_manager_browsertest.cc
@@ -10,7 +10,6 @@
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "base/time/time.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -58,47 +57,24 @@
   mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
   content::GetNetworkService()->BindTestInterface(
       network_service_test.BindNewPipeAndPassReceiver());
-  network_service_test.FlushForTesting();
-
-  mojo::ScopedAllowSyncCallForTesting allow_sync_call;
 
   int64_t count = 0;
-  EXPECT_TRUE(network_service_test->GetFirstPartySetEntriesCount(&count));
+  base::RunLoop run_loop;
+  network_service_test->GetFirstPartySetEntriesCount(
+      base::BindLambdaForTesting([&](int64_t count_from_network_service) {
+        count = count_from_network_service;
+        run_loop.Quit();
+      }));
+  run_loop.Run();
 
   return count;
 }
 
-void Sleep(base::TimeDelta duration) {
-  base::RunLoop run_loop;
-  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, run_loop.QuitClosure(), duration);
-  run_loop.Run();
-}
-
-// Calls a predicate periodically until it becomes true, or until a timeout
-// elapses. The predicate is expected to be monotonic (i.e. once it becomes
-// true, it will remain true until the next time `predicate` is invoked).
-// Returns true if the predicate became true; false otherwise.
-bool PollWithTimeout(base::TimeDelta timeout,
-                     base::RepeatingCallback<bool()> predicate) {
-  base::TimeTicks deadline = base::TimeTicks::Now() + timeout;
-  while (base::TimeTicks::Now() <= deadline) {
-    if (predicate.Run())
-      return true;
-    Sleep(base::Milliseconds(5));
-  }
-  return false;
-}
-
-void PollForFirstPartySetEntryCount(base::TimeDelta timeout,
-                                    int64_t expected_count) {
-  if (!PollWithTimeout(
-          timeout, base::BindLambdaForTesting([expected_count]() {
-            return GetFirstPartySetEntriesCountFromNetworkService() ==
-                   expected_count;
-          }))) {
-    FAIL() << "Polled for " << timeout << " but never found exactly "
-           << expected_count << " First-Party Set entries.";
+void PollForFirstPartySetEntryCount(int64_t expected_count) {
+  auto has_expected_count = base::BindLambdaForTesting([expected_count]() {
+    return GetFirstPartySetEntriesCountFromNetworkService() == expected_count;
+  });
+  while (!has_expected_count.Run()) {
   }
 }
 
@@ -269,27 +245,18 @@
   base::ScopedTempDir component_dir_;
 };
 
-// Flaky on Windows + Linux, crbug.com/1272198
-#if defined(OS_WIN) || defined(OS_LINUX)
-#define MAYBE_ReloadsFirstPartySetsAfterCrash \
-  DISABLED_ReloadsFirstPartySetsAfterCrash
-#else
-#define MAYBE_ReloadsFirstPartySetsAfterCrash ReloadsFirstPartySetsAfterCrash
-#endif
 IN_PROC_BROWSER_TEST_P(
     SystemNetworkContextManagerWithFirstPartySetComponentBrowserTest,
-    MAYBE_ReloadsFirstPartySetsAfterCrash) {
+    ReloadsFirstPartySetsAfterCrash) {
   // Network service is not running out of process, so cannot be crashed.
   if (!content::IsOutOfProcessNetworkService())
     return;
 
-  PollForFirstPartySetEntryCount(base::Seconds(5),
-                                 /*expected_count=*/6);
+  PollForFirstPartySetEntryCount(/*expected_count=*/6);
 
   SimulateNetworkServiceCrash();
 
-  PollForFirstPartySetEntryCount(base::Seconds(5),
-                                 /*expected_count=*/6);
+  PollForFirstPartySetEntryCount(/*expected_count=*/6);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 977f48ee..0e6f59e 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -166,7 +166,6 @@
 using ::pdf_extension_test_util::ConvertPageCoordToScreenCoord;
 using ::testing::Contains;
 using ::testing::IsEmpty;
-using ::testing::MatchesRegex;
 using ::testing::Not;
 using ::testing::StartsWith;
 using ::ui::AXTreeFormatter;
@@ -1679,8 +1678,12 @@
                             /*alt=*/false, command);
   run_loop.Run();
 
-  EXPECT_THAT(base::UTF16ToUTF8(view->GetSelectedText()),
-              MatchesRegex("this is some text\r?\nsome more text"));
+#if defined(OS_WIN)
+  constexpr char kExpectedText[] = "this is some text\r\nsome more text";
+#else
+  constexpr char kExpectedText[] = "this is some text\nsome more text";
+#endif
+  EXPECT_EQ(base::UTF16ToUTF8(view->GetSelectedText()), kExpectedText);
 }
 
 // TODO(crbug.com/1253714): Add tests for using space and shift+space shortcuts
diff --git a/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc b/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc
index 0094daf7f..9e27a954 100644
--- a/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc
+++ b/chrome/browser/performance_manager/mechanisms/working_set_trimmer_chromeos_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "ash/components/arc/memory/arc_memory_bridge.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
@@ -16,7 +17,6 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
-#include "components/arc/session/arc_service_manager.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/performance_manager/policies/working_set_trimmer_policy_arcvm.cc b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.cc
index 62ba597..c9600db 100644
--- a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.cc
+++ b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.cc
@@ -6,6 +6,7 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
@@ -13,7 +14,6 @@
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/wm_helper.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -68,7 +68,7 @@
 
   // If app() is already connected to the AppInstance in the guest, the
   // OnConnectionReady() function is synchronously called before returning
-  // from AddObserver. See components/arc/session/connection_holder.h for
+  // from AddObserver. See ash/components/arc/session/connection_holder.h for
   // more details, especially its AddObserver() function.
   auto* arc_service_manager = arc::ArcServiceManager::Get();
   // ArcServiceManager and objects owned by the manager are created very early
diff --git a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.h b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.h
index 02c2bf8..1fdcf3a 100644
--- a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.h
+++ b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm.h
@@ -6,14 +6,14 @@
 #define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_WORKING_SET_TRIMMER_POLICY_ARCVM_H_
 
 #include "ash/components/arc/metrics/arc_metrics_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/no_destructor.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
 #include "chrome/browser/performance_manager/policies/working_set_trimmer_policy_chromeos.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/connection_holder.h"
 #include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
diff --git a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc
index 5e70872..8d9163f2 100644
--- a/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc
+++ b/chrome/browser/performance_manager/policies/working_set_trimmer_policy_arcvm_unittest.cc
@@ -10,6 +10,7 @@
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
 #include "ash/components/arc/metrics/stability_metrics_manager.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "ash/constants/app_types.h"
 #include "ash/public/cpp/app_types_util.h"
@@ -19,7 +20,6 @@
 #include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/policy/test/arc_policy_browsertest.cc b/chrome/browser/policy/test/arc_policy_browsertest.cc
index d3d25de..6b536be 100644
--- a/chrome/browser/policy/test/arc_policy_browsertest.cc
+++ b/chrome/browser/policy/test/arc_policy_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/memory/ptr_util.h"
@@ -11,7 +12,6 @@
 #include "chrome/browser/policy/policy_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/policy/test/promotional_tabs_enabled_policy_browsertest.cc b/chrome/browser/policy/test/promotional_tabs_enabled_policy_browsertest.cc
index 004b5c2..dc1bfdc4 100644
--- a/chrome/browser/policy/test/promotional_tabs_enabled_policy_browsertest.cc
+++ b/chrome/browser/policy/test/promotional_tabs_enabled_policy_browsertest.cc
@@ -8,7 +8,10 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/json/json_writer.h"
+#include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/policy_test_utils.h"
@@ -214,6 +217,11 @@
 };
 
 IN_PROC_BROWSER_TEST_P(PromotionalTabsEnabledPolicyWhatsNewTest, RunTest) {
+  // Delay to allow the network request simulation to finish.
+  base::RunLoop run_loop;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), TestTimeouts::action_timeout());
+  run_loop.Run();
   TabStripModel* tab_strip = browser()->tab_strip_model();
   ASSERT_GE(tab_strip->count(), 1);
   const auto& url = tab_strip->GetWebContentsAt(0)->GetURL();
@@ -264,6 +272,11 @@
 
 IN_PROC_BROWSER_TEST_P(PromotionalTabsEnabledPolicyWhatsNewInvalidTest,
                        RunTest) {
+  // Delay to allow the network request simulation to finish.
+  base::RunLoop run_loop;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), TestTimeouts::action_timeout());
+  run_loop.Run();
   TabStripModel* tab_strip = browser()->tab_strip_model();
   ASSERT_GE(tab_strip->count(), 1);
   const auto& url = tab_strip->GetWebContentsAt(0)->GetURL();
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index eb6d9f8..eb6b77d 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -692,6 +692,9 @@
 // Deprecated 10/2021.
 const char kAppCacheForceEnabled[] = "app_cache_force_enabled";
 
+// Deprecated 11/2021.
+const char kWasPreviouslySetUpPrefName[] = "android_sms.was_previously_set_up";
+
 // Register local state used only for migration (clearing or moving to a new
 // key).
 void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
@@ -902,6 +905,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   registry->RegisterBooleanPref(kAppCacheForceEnabled, false);
+  registry->RegisterBooleanPref(kWasPreviouslySetUpPrefName, false);
 }
 
 }  // namespace
@@ -1780,6 +1784,7 @@
 
   // Added 11/2021.
   syncer::ClearObsoleteKeystoreBootstrapTokenPref(profile_prefs);
+  profile_prefs->ClearPref(kWasPreviouslySetUpPrefName);
 
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_PROFILE_PREFS
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
index 55f585d3..fb6b838 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service_unittest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
 #include "chrome/browser/service_process/service_process_control.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/cloud_print.mojom.h"
 #include "chrome/common/cloud_print/cloud_print_proxy_info.h"
@@ -214,8 +215,8 @@
   bool LaunchBrowser(const base::CommandLine& command_line, Profile* profile) {
     StartupBrowserCreator browser_creator;
     return browser_creator.ProcessCmdLineImpl(
-        command_line, base::FilePath(), false, profile,
-        StartupBrowserCreator::Profiles());
+        command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
+        profile, StartupBrowserCreator::Profiles());
   }
 
  protected:
diff --git a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
index 9f780ed..3d7f4b60 100644
--- a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
+++ b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/service_process/service_process_control.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/cloud_print/cloud_print_proxy_info.h"
@@ -306,8 +307,8 @@
   bool LaunchBrowser(const base::CommandLine& command_line, Profile* profile) {
     StartupBrowserCreator browser_creator;
     return browser_creator.ProcessCmdLineImpl(
-        command_line, base::FilePath(), false, profile,
-        StartupBrowserCreator::Profiles());
+        command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
+        profile, StartupBrowserCreator::Profiles());
   }
 
  protected:
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 0b2014bc..58283f4 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -144,12 +144,12 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "ash/constants/ash_switches.h"
 #include "chrome/browser/ash/account_manager/account_manager_policy_controller_factory.h"
 #include "chrome/browser/ash/arc/policy/arc_policy_util.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
-#include "components/arc/session/arc_management_transition.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_type.h"
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index 4943082..cda44eee 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -65,6 +65,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/components/arc/arc_features.h"
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_management_transition.h"
 #include "ash/constants/ash_switches.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/login/users/scoped_test_user_manager.h"
@@ -72,7 +73,6 @@
 #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/browser/ui/ash/test_wallpaper_controller.h"
 #include "chrome/browser/ui/ash/wallpaper_controller_client_impl.h"
-#include "components/arc/session/arc_management_transition.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_names.h"
diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc
index b9cb488..58a47365 100644
--- a/chrome/browser/profiles/profile_window.cc
+++ b/chrome/browser/profiles/profile_window.cc
@@ -148,14 +148,14 @@
   if (status != Profile::CREATE_STATUS_INITIALIZED)
     return;
 
-  chrome::startup::IsProcessStartup is_process_startup =
-      chrome::startup::IS_NOT_PROCESS_STARTUP;
-  chrome::startup::IsFirstRun is_first_run = chrome::startup::IS_NOT_FIRST_RUN;
+  chrome::startup::IsProcessStartup process_startup =
+      chrome::startup::IsProcessStartup::kNo;
+  chrome::startup::IsFirstRun is_first_run = chrome::startup::IsFirstRun::kNo;
 
   // If this is a brand new profile, then start a first run window.
   if (is_new_profile) {
-    is_process_startup = chrome::startup::IS_PROCESS_STARTUP;
-    is_first_run = chrome::startup::IS_FIRST_RUN;
+    process_startup = chrome::startup::IsProcessStartup::kYes;
+    is_first_run = chrome::startup::IsFirstRun::kYes;
   }
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -212,7 +212,7 @@
   // existed, which means that here a browser definitely needs to be created.
   // Passing true for |always_create| means we won't duplicate the code that
   // tries to find a browser.
-  profiles::FindOrCreateNewWindowForProfile(profile, is_process_startup,
+  profiles::FindOrCreateNewWindowForProfile(profile, process_startup,
                                             is_first_run, true);
 }
 
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 5fe9454..1c89efe 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -257,8 +257,8 @@
   // Open a second guest window and close one. This should not affect the find
   // in page cache as the guest session hasn't been ended.
   profiles::FindOrCreateNewWindowForProfile(
-      guest_profile, chrome::startup::IS_NOT_PROCESS_STARTUP,
-      chrome::startup::IS_NOT_FIRST_RUN, true /*always_create*/);
+      guest_profile, chrome::startup::IsProcessStartup::kNo,
+      chrome::startup::IsFirstRun::kNo, true /*always_create*/);
   CloseBrowserSynchronously(guest_browser);
   EXPECT_EQ(fip_text, FindBarStateFactory::GetForBrowserContext(guest_profile)
                           ->GetSearchPrepopulateText());
@@ -271,9 +271,9 @@
 
   // Open a new guest browser window. Since this is a separate session, the find
   // in page text should have been cleared (along with all other browsing data).
-    profiles::FindOrCreateNewWindowForProfile(
-        guest_profile, chrome::startup::IS_NOT_PROCESS_STARTUP,
-        chrome::startup::IS_NOT_FIRST_RUN, true /*always_create*/);
+  profiles::FindOrCreateNewWindowForProfile(
+      guest_profile, chrome::startup::IsProcessStartup::kNo,
+      chrome::startup::IsFirstRun::kNo, true /*always_create*/);
 
   EXPECT_EQ(std::u16string(),
             FindBarStateFactory::GetForBrowserContext(guest_profile)
diff --git a/chrome/browser/profiling_host/OWNERS b/chrome/browser/profiling_host/OWNERS
index 68612fd..9cc3a5e 100644
--- a/chrome/browser/profiling_host/OWNERS
+++ b/chrome/browser/profiling_host/OWNERS
@@ -1,3 +1,2 @@
-ajwong@chromium.org
 alph@chromium.org
 erikchen@chromium.org
diff --git a/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc b/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc
index bbbdb20..ac1a5d4 100644
--- a/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc
+++ b/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc
@@ -15,9 +15,9 @@
 #include "components/feature_engagement/public/tracker.h"
 #include "components/renderer_context_menu/render_view_context_menu_proxy.h"
 #include "components/shared_highlighting/core/common/disabled_sites.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #include "components/shared_highlighting/core/common/shared_highlighting_features.h"
 #include "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
-#include "components/shared_highlighting/core/common/text_fragments_utils.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/context_menu_params.h"
 #include "content/public/browser/render_view_host.h"
@@ -246,7 +246,8 @@
   ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste,
                                 std::move(data_transfer_endpoint));
 
-  GURL url_to_share = shared_highlighting::RemoveTextFragments(url_);
+  GURL url_to_share =
+      shared_highlighting::RemoveFragmentSelectorDirectives(url_);
   url_to_share = shared_highlighting::AppendSelectors(url_to_share, selectors);
 
   scw.WriteText(base::UTF8ToUTF16(url_to_share.spec()));
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc b/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
index 295dd82..2110b82 100644
--- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/renderer_context_menu/quick_answers_menu_observer.h"
 
-#include "ash/constants/ash_features.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h"
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 71898a98..86e7b82 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1377,8 +1377,8 @@
   }
 
   profiles::FindOrCreateNewWindowForProfile(
-      profile, chrome::startup::IS_NOT_PROCESS_STARTUP,
-      chrome::startup::IS_NOT_FIRST_RUN, false);
+      profile, chrome::startup::IsProcessStartup::kNo,
+      chrome::startup::IsFirstRun::kNo, false);
 
   {
     std::unique_ptr<TestRenderViewContextMenu> menu(
@@ -1460,8 +1460,8 @@
       entry->LockForceSigninProfile(true);
     } else {
       profiles::FindOrCreateNewWindowForProfile(
-          profile, chrome::startup::IS_NOT_PROCESS_STARTUP,
-          chrome::startup::IS_NOT_FIRST_RUN, false);
+          profile, chrome::startup::IsProcessStartup::kNo,
+          chrome::startup::IsFirstRun::kNo, false);
       profiles_in_menu.push_back(profile);
     }
   }
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
index 1a1a1584..d135415 100644
--- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
@@ -13,6 +13,8 @@
 #include <vector>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/shell.h"
 #include "base/bind.h"
@@ -40,8 +42,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/memory/pressure/system_memory_pressure_evaluator.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/device_event_log/device_event_log.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 4d890ed..684f735b 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -168,9 +168,6 @@
     if (enable_pdf) {
       deps += [ "pdf:closure_compile" ]
     }
-    if (enable_webui_tab_strip) {
-      deps += [ "tab_strip:closure_compile" ]
-    }
     if (is_android) {
       deps += [
         "explore_sites_internals:closure_compile",
diff --git a/chrome/browser/resources/browser_switch/internals/browser_switch_internals.ts b/chrome/browser/resources/browser_switch/internals/browser_switch_internals.ts
index b5e15acfc..4b84235d 100644
--- a/chrome/browser/resources/browser_switch/internals/browser_switch_internals.ts
+++ b/chrome/browser/resources/browser_switch/internals/browser_switch_internals.ts
@@ -129,7 +129,7 @@
   // TODO (crbug.com/1258133): if you change the AlternativeBrowserPath
   // policy, then loadTimeData can contain stale data. It won't update
   // until you refresh (despite the rest of the page auto-updating).
-  return loadTimeData.getString('altBrowserName');
+  return loadTimeData.getString('altBrowserName') || 'alternative browser';
 }
 
 /**
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
index c2e4298..958a7c9 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
+++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.html
@@ -1,15 +1,15 @@
 <style include="cr-shared-style cr-hidden-style">
-  #destination-dropdown {
+  #destinationDropdown {
     outline: none;
     position: relative;
   }
 
-  #destination-dropdown:focus {
+  #destinationDropdown:focus {
     border-radius: 4px;
     box-shadow: 0 0 0 2px rgba(var(--google-blue-600-rgb), .4);
   }
 
-  #destination-dropdown,
+  #destinationDropdown,
   iron-dropdown {
     width: var(--print-preview-dropdown-width);
   }
@@ -98,7 +98,7 @@
     width: 100%;
   }
 </style>
-<div id="destination-dropdown" on-keydown="onKeyDown_" tabindex="0"
+<div id="destinationDropdown" on-keydown="onKeyDown_" tabindex="0"
     on-blur="onBlur_" on-click="onClick_" role="button" aria-haspopup="true"
     aria-label="$i18n{destinationLabel} [[value.displayName]]"
     aria-description$="[[destinationStatusText]]">
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts
index 904b5e83..fbb28c1 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts
+++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts
@@ -23,6 +23,12 @@
   }
 }
 
+export interface PrintPreviewDestinationDropdownCrosElement {
+  $: {
+    destinationDropdown: HTMLDivElement,
+  }
+}
+
 const PrintPreviewDestinationDropdownCrosElementBase =
     I18nMixin(PolymerElement);
 
@@ -82,6 +88,7 @@
   disabled: boolean;
   driveDestinationKey: string;
   noDestinations: boolean;
+  pdfDestinationKey: string;
   pdfPrinterDisabled: boolean;
   destinationStatusText: string;
   private highlightedIndex_: number;
@@ -103,8 +110,7 @@
   }
 
   focus() {
-    this.shadowRoot!.querySelector<HTMLElement>(
-                        '#destination-dropdown')!.focus();
+    this.$.destinationDropdown.focus();
   }
 
   private fireDropdownValueSelected_(element: Element) {
@@ -183,10 +189,10 @@
   private onKeyDown_(event: KeyboardEvent) {
     event.stopPropagation();
     const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!;
-    switch (event.code) {
+    switch (event.key) {
       case 'ArrowUp':
       case 'ArrowDown':
-        this.onArrowKeyPress_(event.code);
+        this.onArrowKeyPress_(event.key);
         break;
       case 'Enter': {
         if (dropdown.opened) {
@@ -207,7 +213,7 @@
     }
   }
 
-  private onArrowKeyPress_(eventCode: string) {
+  private onArrowKeyPress_(eventKey: string) {
     const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!;
     const items = this.getButtonListFromDropdown_();
     if (items.length === 0) {
@@ -219,7 +225,7 @@
     // press to change the selected destination.
     if (dropdown.opened) {
       const nextIndex = this.getNextItemIndexInList_(
-          eventCode, this.highlightedIndex_, items.length);
+          eventKey, this.highlightedIndex_, items.length);
       if (nextIndex === -1) {
         return;
       }
@@ -230,7 +236,7 @@
 
     const currentIndex = items.findIndex(item => item.value === this.value.key);
     const nextIndex =
-        this.getNextItemIndexInList_(eventCode, currentIndex, items.length);
+        this.getNextItemIndexInList_(eventKey, currentIndex, items.length);
     if (nextIndex === -1) {
       return;
     }
@@ -241,9 +247,9 @@
    * @return -1 when the next item would be outside the list.
    */
   private getNextItemIndexInList_(
-      eventCode: string, currentIndex: number, numItems: number): number {
+      eventKey: string, currentIndex: number, numItems: number): number {
     const nextIndex =
-        eventCode === 'ArrowDown' ? currentIndex + 1 : currentIndex - 1;
+        eventKey === 'ArrowDown' ? currentIndex + 1 : currentIndex - 1;
     return nextIndex >= 0 && nextIndex < numItems ? nextIndex : -1;
   }
 
@@ -252,8 +258,7 @@
     if (dropdownItem) {
       this.fireDropdownValueSelected_(dropdownItem);
     }
-    this.shadowRoot!.querySelector<HTMLElement>(
-                        '#destination-dropdown')!.focus();
+    this.$.destinationDropdown.focus();
   }
 
   /**
@@ -275,7 +280,7 @@
    * being focusable.
    */
   private updateTabIndex_() {
-    this.shadowRoot!.querySelector('#destination-dropdown')!.setAttribute(
+    this.$.destinationDropdown.setAttribute(
         'tabindex', this.disabled ? '-1' : '0');
   }
 
diff --git a/chrome/browser/resources/read_later/BUILD.gn b/chrome/browser/resources/read_later/BUILD.gn
index f344a0c..851e37a 100644
--- a/chrome/browser/resources/read_later/BUILD.gn
+++ b/chrome/browser/resources/read_later/BUILD.gn
@@ -63,11 +63,11 @@
 }
 
 preprocess_if_expr("preprocess_mojo") {
-  deps = [ "//chrome/browser/ui/webui/read_later:mojo_bindings_js" ]
-  in_folder = "$root_gen_dir/chrome/browser/ui/webui/read_later/"
+  deps = [ "//chrome/browser/ui/webui/read_later:mojo_bindings_webui_js" ]
+  in_folder = "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/read_later/"
   out_folder = "$target_gen_dir/$preprocess_folder"
   out_manifest = "$target_gen_dir/$preprocess_mojo_manifest"
-  in_files = [ "read_later.mojom-lite.js" ]
+  in_files = [ "read_later.mojom-webui.js" ]
 }
 
 preprocess_if_expr("preprocess_web_components") {
@@ -83,6 +83,13 @@
 }
 
 js_type_check("closure_compile") {
+  closure_flags =
+      default_closure_args + mojom_js_args + [
+        "js_module_root=" + rebase_path(".", root_build_dir),
+        "js_module_root=" + rebase_path(
+                "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/read_later",
+                root_build_dir),
+      ]
   is_polymer3 = true
   deps = [
     ":app",
@@ -95,6 +102,7 @@
   deps = [
     ":read_later_api_proxy",
     ":read_later_item",
+    "//chrome/browser/ui/webui/read_later:mojo_bindings_webui_js",
     "//third_party/polymer/v3_0/components-chromium/iron-selector:iron-selector",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
@@ -108,7 +116,7 @@
 
 js_library("read_later_api_proxy") {
   deps = [
-    "//chrome/browser/ui/webui/read_later:mojo_bindings_js_library_for_compile",
+    "//chrome/browser/ui/webui/read_later:mojo_bindings_webui_js",
     "//ui/webui/resources/js:cr.m",
   ]
 }
@@ -116,6 +124,7 @@
 js_library("read_later_item") {
   deps = [
     ":read_later_api_proxy",
+    "//chrome/browser/ui/webui/read_later:mojo_bindings_webui_js",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements:mouse_hoverable_mixin",
     "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
diff --git a/chrome/browser/resources/read_later/app.js b/chrome/browser/resources/read_later/app.js
index 7ee35865..dfd481f 100644
--- a/chrome/browser/resources/read_later/app.js
+++ b/chrome/browser/resources/read_later/app.js
@@ -10,7 +10,6 @@
 import 'chrome://resources/cr_elements/mwb_shared_style.js';
 import 'chrome://resources/cr_elements/mwb_shared_vars.js';
 import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
-
 import './strings.m.js';
 
 import {assertNotReached} from 'chrome://resources/js/assert.m.js';
@@ -18,6 +17,7 @@
 import {listenOnce} from 'chrome://resources/js/util.m.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {CurrentPageActionButtonState, ReadLaterEntriesByStatus, ReadLaterEntry} from './read_later.mojom-webui.js';
 import {ReadLaterApiProxy, ReadLaterApiProxyImpl} from './read_later_api_proxy.js';
 import {ReadLaterItemElement} from './read_later_item.js';
 
@@ -35,22 +35,22 @@
 
   static get properties() {
     return {
-      /** @private {!Array<!readLater.mojom.ReadLaterEntry>} */
+      /** @private {!Array<!ReadLaterEntry>} */
       unreadItems_: {
         type: Array,
         value: [],
       },
 
-      /** @private {!Array<!readLater.mojom.ReadLaterEntry>} */
+      /** @private {!Array<!ReadLaterEntry>} */
       readItems_: {
         type: Array,
         value: [],
       },
 
-      /** @private {!readLater.mojom.CurrentPageActionButtonState} */
+      /** @private {!CurrentPageActionButtonState} */
       currentPageActionButtonState_: {
         type: Number,
-        value: readLater.mojom.CurrentPageActionButtonState.kDisabled,
+        value: CurrentPageActionButtonState.kDisabled,
       },
 
       /** @type {boolean} */
@@ -144,7 +144,7 @@
   }
 
   /**
-   * @param {!readLater.mojom.ReadLaterEntriesByStatus} entries
+   * @param {!ReadLaterEntriesByStatus} entries
    * @private
    */
   updateItems_(entries) {
@@ -154,7 +154,7 @@
   }
 
   /**
-   * @param {!readLater.mojom.CurrentPageActionButtonState} state
+   * @param {!CurrentPageActionButtonState} state
    * @private
    */
   updateCurrentPageActionButton_(state) {
@@ -162,7 +162,7 @@
   }
 
   /**
-   * @param {!readLater.mojom.ReadLaterEntry} item
+   * @param {!ReadLaterEntry} item
    * @return {string}
    * @private
    */
@@ -196,7 +196,7 @@
    */
   getCurrentPageActionButtonDisabled_() {
     return this.currentPageActionButtonState_ ===
-        readLater.mojom.CurrentPageActionButtonState.kDisabled;
+        CurrentPageActionButtonState.kDisabled;
   }
 
   /**
diff --git a/chrome/browser/resources/read_later/read_later_api_proxy.js b/chrome/browser/resources/read_later/read_later_api_proxy.js
index c464fb8..9b34dbc 100644
--- a/chrome/browser/resources/read_later/read_later_api_proxy.js
+++ b/chrome/browser/resources/read_later/read_later_api_proxy.js
@@ -2,11 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
-import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
-import 'chrome://resources/mojo/ui/base/mojom/window_open_disposition.mojom-lite.js';
-
-import './read_later.mojom-lite.js';
+import {ClickModifiers} from 'chrome://resources/mojo/ui/base/mojom/window_open_disposition.mojom-webui.js';
+import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';
+import {PageCallbackRouter, PageHandlerFactory, PageHandlerRemote, ReadLaterEntriesByStatus} from './read_later.mojom-webui.js';
 
 /** @type {?ReadLaterApiProxy} */
 let instance = null;
@@ -14,30 +12,30 @@
 /** @interface */
 export class ReadLaterApiProxy {
   /**
-   * @return {!Promise<!{entries: !readLater.mojom.ReadLaterEntriesByStatus}>}
+   * @return {!Promise<!{entries: !ReadLaterEntriesByStatus}>}
    */
   getReadLaterEntries() {}
 
   /**
-   * @param {!url.mojom.Url} url
+   * @param {!Url} url
    * @param {boolean} mark_as_read
-   * @param {!ui.mojom.ClickModifiers} click_modifiers
+   * @param {!ClickModifiers} click_modifiers
    */
   openURL(url, mark_as_read, click_modifiers) {}
 
   /**
-   * @param {!url.mojom.Url} url
+   * @param {!Url} url
    * @param {boolean} read
    */
   updateReadStatus(url, read) {}
 
   addCurrentTab() {}
 
-  /** @param {!url.mojom.Url} url */
+  /** @param {!Url} url */
   removeEntry(url) {}
 
   /**
-   * @param {!url.mojom.Url} url
+   * @param {!Url} url
    * @param {number} locationX
    * @param {number} locationY
    */
@@ -49,20 +47,20 @@
 
   closeUI() {}
 
-  /** @return {!readLater.mojom.PageCallbackRouter} */
+  /** @return {!PageCallbackRouter} */
   getCallbackRouter() {}
 }
 
 /** @implements {ReadLaterApiProxy} */
 export class ReadLaterApiProxyImpl {
   constructor() {
-    /** @type {!readLater.mojom.PageCallbackRouter} */
-    this.callbackRouter = new readLater.mojom.PageCallbackRouter();
+    /** @type {!PageCallbackRouter} */
+    this.callbackRouter = new PageCallbackRouter();
 
-    /** @type {!readLater.mojom.PageHandlerRemote} */
-    this.handler = new readLater.mojom.PageHandlerRemote();
+    /** @type {!PageHandlerRemote} */
+    this.handler = new PageHandlerRemote();
 
-    const factory = readLater.mojom.PageHandlerFactory.getRemote();
+    const factory = PageHandlerFactory.getRemote();
     factory.createPageHandler(
         this.callbackRouter.$.bindNewPipeAndPassRemote(),
         this.handler.$.bindNewPipeAndPassReceiver());
diff --git a/chrome/browser/resources/read_later/read_later_item.js b/chrome/browser/resources/read_later/read_later_item.js
index 30add3b..58fd809b 100644
--- a/chrome/browser/resources/read_later/read_later_item.js
+++ b/chrome/browser/resources/read_later/read_later_item.js
@@ -15,6 +15,7 @@
 import {getFaviconForPageURL} from 'chrome://resources/js/icon.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {ReadLaterEntry} from './read_later.mojom-webui.js';
 import {ReadLaterApiProxy, ReadLaterApiProxyImpl} from './read_later_api_proxy.js';
 
 /** @type {!Set<string>} */
@@ -40,7 +41,7 @@
 
   static get properties() {
     return {
-      /** @type {!readLater.mojom.ReadLaterEntry} */
+      /** @type {!ReadLaterEntry} */
       data: Object,
 
       /** @type {boolean} */
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
index 19d9e36..470f6db 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
@@ -174,7 +174,8 @@
    * @private
    */
   isPhoneHubAppsSetupRequired_() {
-    return !this.pageContentData.isPhoneHubAppsAccessGranted;
+    return this.isFeatureSupported(settings.MultiDeviceFeature.ECHE) &&
+        !this.pageContentData.isPhoneHubAppsAccessGranted;
   },
 
   /**
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 aa6e4be..623eed9d 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
@@ -38,6 +38,13 @@
 <div class="device-lists-separator"></div>
 <div id="container">
   <template is="dom-if"
+      if="[[shouldShowNoDevicesFound_(unconnectedDevices_.length,
+          connectedDevices_.length)]]" restamp>
+    <div id="noDevices" class="settings-box-text">
+      $i18n{bluetoothDeviceListNoConnectedDevices}
+    </div>
+  </template>
+  <template is="dom-if"
       if="[[shouldShowDeviceList_(connectedDevices_,
           connectedDevices_.length)]]" restamp>
     <div class="settings-box-text">
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 ee682ae..e0d9bc2 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
@@ -157,6 +157,14 @@
   shouldShowDeviceList_(devices) {
     return devices.length > 0;
   }
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowNoDevicesFound_() {
+    return !this.connectedDevices_.length && !this.unconnectedDevices_.length;
+  }
 }
 
 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 d3157b65..9d811648 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
@@ -1,4 +1,8 @@
 <style include="settings-shared iron-flex">
+  iron-icon[icon='cr:add'] {
+    --iron-icon-fill-color: var(--cros-icon-color-prominent);
+    margin-inline-end: 8px;
+  }
 </style>
 <settings-animated-pages id="pages" section="bluetooth">
   <div route-path="default">
@@ -9,6 +13,15 @@
   </div>
   <template is="dom-if" route-path="/bluetoothDevices">
     <settings-subpage page-title="$i18n{bluetoothPageTitle}">
+      <div slot="subpage-title-extra">
+        <cr-button id="pairNewDevice"
+            on-click="onStartPairing_"
+            class="cancel-button">
+          <iron-icon icon="cr:add">
+          </iron-icon>
+          $i18n{bluetoothPairNewDevice}
+        </cr-button>
+      </div>
       <os-settings-bluetooth-devices-subpage
           prefs="{{prefs}}"
           system-properties="[[systemProperties_]]">
diff --git a/chrome/browser/resources/tab_strip/BUILD.gn b/chrome/browser/resources/tab_strip/BUILD.gn
index 66338ac..190b3fb3 100644
--- a/chrome/browser/resources/tab_strip/BUILD.gn
+++ b/chrome/browser/resources/tab_strip/BUILD.gn
@@ -3,12 +3,14 @@
 # found in the LICENSE file.
 
 import("//chrome/common/features.gni")
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/preprocess_if_expr.gni")
 import("//tools/polymer/html_to_js.gni")
 import("//tools/typescript/ts_library.gni")
 import("//ui/webui/resources/tools/generate_grd.gni")
+import("//ui/webui/webui_features.gni")
+
+assert(enable_webui_tab_strip)
 
 preprocess_folder = "preprocessed"
 
@@ -52,10 +54,9 @@
   in_folder = "./"
   out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = [
-    "drag_manager.js",
-    "tabs_api_proxy.js",
-    "tab_strip_embedder_proxy.js",
-    "tab_swiper.js",
+    "drag_manager.ts",
+    "tabs_api_proxy.ts",
+    "tab_swiper.ts",
   ]
 }
 
@@ -64,11 +65,11 @@
   in_folder = target_gen_dir
   out_folder = "$target_gen_dir/$preprocess_folder"
   in_files = [
-    "alert_indicator.js",
-    "alert_indicators.js",
-    "tab_group.js",
-    "tab_list.js",
-    "tab.js",
+    "alert_indicator.ts",
+    "alert_indicators.ts",
+    "tab_group.ts",
+    "tab_list.ts",
+    "tab.ts",
   ]
 }
 
@@ -89,114 +90,13 @@
   output_dir = "$root_gen_dir/chrome"
 }
 
-js_type_check("closure_compile") {
-  closure_flags =
-      default_closure_args + mojom_js_args + [
-        "js_module_root=" + rebase_path(".", root_build_dir),
-        "js_module_root=" + rebase_path(
-                "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/tab_strip",
-                root_build_dir),
-        "js_module_root=" + rebase_path(
-                "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/tabs",
-                root_build_dir),
-      ]
-  deps = [
-    ":alert_indicator",
-    ":alert_indicators",
-    ":drag_manager",
-    ":tab",
-    ":tab_group",
-    ":tab_list",
-    ":tab_swiper",
-    ":tabs_api_proxy",
-  ]
-}
-
-js_library("alert_indicator") {
-  deps = [
-    ":tabs_api_proxy",
-    "//chrome/browser/ui/webui/tabs:mojo_bindings_webui_js",
-    "//ui/webui/resources/js:custom_element",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-}
-
-js_library("alert_indicators") {
-  deps = [
-    ":alert_indicator",
-    ":tabs_api_proxy",
-    "//chrome/browser/ui/webui/tabs:mojo_bindings_webui_js",
-    "//ui/webui/resources/js:custom_element",
-  ]
-}
-
-js_library("drag_manager") {
-  deps = [
-    ":tab",
-    ":tab_group",
-    ":tabs_api_proxy",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-}
-
-js_library("tabs_api_proxy") {
-  deps = [
-    "//chrome/browser/ui/webui/tab_strip:mojo_bindings_webui_js",
-    "//ui/webui/resources/js:cr.m",
-  ]
-  externs_list = [
-    "$externs_path/chrome_extensions.js",
-    "$externs_path/metrics_private.js",
-  ]
-}
-
-js_library("tab") {
-  deps = [
-    ":alert_indicators",
-    ":tab_swiper",
-    ":tabs_api_proxy",
-    "//ui/webui/resources/js:custom_element",
-    "//ui/webui/resources/js:icon",
-    "//ui/webui/resources/js:load_time_data.m",
-    "//ui/webui/resources/js:util.m",
-  ]
-  externs_list = [ "$externs_path/metrics_private.js" ]
-}
-
-js_library("tab_group") {
-  deps = [
-    ":tabs_api_proxy",
-    "//ui/webui/resources/js:custom_element",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-}
-
-js_library("tab_list") {
-  deps = [
-    ":drag_manager",
-    ":tab",
-    ":tab_group",
-    ":tabs_api_proxy",
-    "//ui/webui/resources/js:cr.m",
-    "//ui/webui/resources/js:custom_element",
-    "//ui/webui/resources/js:event_tracker.m",
-    "//ui/webui/resources/js:load_time_data.m",
-    "//ui/webui/resources/js:util.m",
-    "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
-  ]
-}
-
-js_library("tab_swiper") {
-}
-
 html_to_js("web_components") {
   js_files = [
-    "alert_indicator.js",
-    "alert_indicators.js",
-    "tab_group.js",
-    "tab_list.js",
-    "tab.js",
+    "alert_indicator.ts",
+    "alert_indicators.ts",
+    "tab_group.ts",
+    "tab_list.ts",
+    "tab.ts",
   ]
 }
 
@@ -205,22 +105,26 @@
   out_dir = "$target_gen_dir/tsc"
   tsconfig_base = "tsconfig_base.json"
   in_files = [
-    "alert_indicator.js",
-    "alert_indicators.js",
-    "drag_manager.js",
-    "tab_group.js",
-    "tab.js",
-    "tab_list.js",
-    "tabs_api_proxy.js",
+    "alert_indicator.ts",
+    "alert_indicators.ts",
+    "drag_manager.ts",
+    "tab_group.ts",
+    "tab.ts",
+    "tab_list.ts",
+    "tabs_api_proxy.ts",
     "tabs.mojom-webui.js",
-    "tab_strip_embedder_proxy.js",
     "tab_strip.mojom-webui.js",
-    "tab_swiper.js",
+    "tab_swiper.ts",
   ]
   deps = [
     "//third_party/polymer/v3_0:library",
     "//ui/webui/resources:library",
   ]
+  definitions = [
+    "//tools/typescript/definitions/chrome_send.d.ts",
+    "//tools/typescript/definitions/metrics_private.d.ts",
+    "//tools/typescript/definitions/tabs.d.ts",
+  ]
   extra_deps = [
     ":preprocess",
     ":preprocess_generated",
diff --git a/chrome/browser/resources/tab_strip/alert_indicator.js b/chrome/browser/resources/tab_strip/alert_indicator.ts
similarity index 88%
rename from chrome/browser/resources/tab_strip/alert_indicator.js
rename to chrome/browser/resources/tab_strip/alert_indicator.ts
index 3d59119..e122881 100644
--- a/chrome/browser/resources/tab_strip/alert_indicator.js
+++ b/chrome/browser/resources/tab_strip/alert_indicator.ts
@@ -9,14 +9,9 @@
 
 import {TabAlertState} from './tabs.mojom-webui.js';
 
-/** @const {string} */
-const MAX_WIDTH = '16px';
+const MAX_WIDTH: string = '16px';
 
-/**
- * @param {!TabAlertState} alertState
- * @return {string}
- */
-function getAriaLabel(alertState) {
+function getAriaLabel(alertState: TabAlertState): string {
   // The existing labels for alert states currently expects to format itself
   // using the title of the tab (eg. "Website - Audio is playing"). The WebUI
   // tab strip will provide the title of the tab elsewhere outside of this
@@ -51,8 +46,7 @@
   }
 }
 
-/** @type {!Map<!TabAlertState, string>} */
-const ALERT_STATE_MAP = new Map([
+const ALERT_STATE_MAP: Map<TabAlertState, string> = new Map([
   [TabAlertState.kMediaRecording, 'media-recording'],
   [TabAlertState.kTabCapturing, 'tab-capturing'],
   [TabAlertState.kAudioPlaying, 'audio-playing'],
@@ -68,10 +62,8 @@
 
 /**
  * Use for mapping to CSS attributes.
- * @param {!TabAlertState} alertState
- * @return {string}
  */
-function getAlertStateAttribute(alertState) {
+function getAlertStateAttribute(alertState: TabAlertState): string {
   return ALERT_STATE_MAP.get(alertState) || '';
 }
 
@@ -80,49 +72,43 @@
     return `{__html_template__}`;
   }
 
+  private alertState_: TabAlertState;
+  private fadeDurationMs_: number = 125;
+  private fadeInAnimation_: Animation|null;
+  private fadeOutAnimation_: Animation|null;
+  private fadeOutAnimationPromise_: Promise<void>|null;
+
   constructor() {
     super();
 
-    /** @private {!TabAlertState} */
-    this.alertState_;
-
-    /** @private {number} */
-    this.fadeDurationMs_ = 125;
-
     /**
      * An animation that is currently in-flight to fade the element in.
-     * @private {?Animation}
      */
     this.fadeInAnimation_ = null;
 
     /**
      * An animation that is currently in-flight to fade the element out.
-     * @private {?Animation}
      */
     this.fadeOutAnimation_ = null;
 
     /**
      * A promise that resolves when the fade out animation finishes or rejects
      * if a fade out animation is canceled.
-     * @private {?Promise}
      */
     this.fadeOutAnimationPromise_ = null;
   }
 
-  /** @return {!TabAlertState} */
-  get alertState() {
+  get alertState(): TabAlertState {
     return this.alertState_;
   }
 
-  /** @param {!TabAlertState} alertState */
-  set alertState(alertState) {
+  set alertState(alertState: TabAlertState) {
     this.setAttribute('alert-state_', getAlertStateAttribute(alertState));
     this.setAttribute('aria-label', getAriaLabel(alertState));
     this.alertState_ = alertState;
   }
 
-  /** @param {number} duration */
-  overrideFadeDurationForTesting(duration) {
+  overrideFadeDurationForTesting(duration: number) {
     this.fadeDurationMs_ = duration;
   }
 
@@ -174,8 +160,7 @@
     }
   }
 
-  /** @return {!Promise} */
-  hide() {
+  hide(): Promise<void> {
     if (this.fadeInAnimation_) {
       // Cancel any fade in animations to prevent the element from fading in. At
       // this point, the tab's alertStates have changed to a state in which this
diff --git a/chrome/browser/resources/tab_strip/alert_indicators.js b/chrome/browser/resources/tab_strip/alert_indicators.ts
similarity index 74%
rename from chrome/browser/resources/tab_strip/alert_indicators.js
rename to chrome/browser/resources/tab_strip/alert_indicators.ts
index 1bf0182..400e6b2 100644
--- a/chrome/browser/resources/tab_strip/alert_indicators.js
+++ b/chrome/browser/resources/tab_strip/alert_indicators.ts
@@ -14,16 +14,17 @@
     return `{__html_template__}`;
   }
 
+  private containerEl_: HTMLElement;
+  private alertIndicators_: Map<TabAlertState, AlertIndicatorElement>;
+
   constructor() {
     super();
 
-    /** @private {!HTMLElement} */
-    this.containerEl_ = /** @type {!HTMLElement} */ (this.$('#container'));
+    this.containerEl_ = this.$('#container') as HTMLElement;
 
     const audioIndicator = new AlertIndicatorElement();
     const recordingIndicator = new AlertIndicatorElement();
 
-    /** @private {!Map<!TabAlertState, !AlertIndicatorElement>} */
     this.alertIndicators_ = new Map([
       [TabAlertState.kMediaRecording, recordingIndicator],
       [TabAlertState.kTabCapturing, new AlertIndicatorElement()],
@@ -40,17 +41,16 @@
   }
 
   /**
-   * @param {!Array<!TabAlertState>} alertStates
-   * @return {!Promise<number>} A promise that resolves with the number of
-   *     AlertIndicatorElements that are currently visible.
+   * @return A promise that resolves with the number of AlertIndicatorElements
+   *     that are currently visible.
    */
-  updateAlertStates(alertStates) {
+  updateAlertStates(alertStates: TabAlertState[]): Promise<number> {
     const alertIndicators =
         alertStates.map(alertState => this.alertIndicators_.get(alertState));
 
     let alertIndicatorCount = 0;
     for (const [index, alertState] of alertStates.entries()) {
-      const alertIndicator = alertIndicators[/** @type {number} */ (index)];
+      const alertIndicator = alertIndicators[index];
 
       // Don't show unsupported indicators.
       if (!alertIndicator) {
@@ -68,14 +68,18 @@
       alertIndicator.alertState = alertState;
 
       this.containerEl_.insertBefore(
-          alertIndicator, this.containerEl_.children[alertIndicatorCount]);
+          alertIndicator,
+          this.containerEl_.children[alertIndicatorCount] as Node);
       // Only fade in if this is just being added to the DOM.
       alertIndicator.show();
 
       alertIndicatorCount++;
     }
 
-    const animationPromises = Array.from(this.containerEl_.children)
+    const animationPromises = Array
+                                  .from(
+                                      this.containerEl_.children as
+                                      HTMLCollectionOf<AlertIndicatorElement>)
                                   .slice(alertIndicatorCount)
                                   .map(indicator => indicator.hide());
     return Promise.all(animationPromises)
@@ -84,9 +88,10 @@
               return this.containerEl_.childElementCount;
             },
             () => {
-                // A failure in the animation promises means an animation was
-                // canceled and therefore there is a new set of alertStates
-                // being animated.
+              // A failure in the animation promises means an animation was
+              // canceled and therefore there is a new set of alertStates
+              // being animated.
+              return -1;
             });
   }
 }
diff --git a/chrome/browser/resources/tab_strip/drag_manager.js b/chrome/browser/resources/tab_strip/drag_manager.ts
similarity index 60%
rename from chrome/browser/resources/tab_strip/drag_manager.js
rename to chrome/browser/resources/tab_strip/drag_manager.ts
index 98dc51b..3692925 100644
--- a/chrome/browser/resources/tab_strip/drag_manager.js
+++ b/chrome/browser/resources/tab_strip/drag_manager.ts
@@ -12,36 +12,30 @@
 import {Tab, TabNetworkState} from './tab_strip.mojom-webui.js';
 import {TabsApiProxy, TabsApiProxyImpl} from './tabs_api_proxy.js';
 
-/** @const {number} */
-export const PLACEHOLDER_TAB_ID = -1;
+export const PLACEHOLDER_TAB_ID: number = -1;
 
-/** @const {string} */
-export const PLACEHOLDER_GROUP_ID = 'placeholder';
+export const PLACEHOLDER_GROUP_ID: string = 'placeholder';
 
 /**
  * The data type key for pinned state of a tab. Since drag events only expose
  * whether or not a data type exists (not the actual value), presence of this
  * data type means that the tab is pinned.
- * @const {string}
  */
-const PINNED_DATA_TYPE = 'pinned';
+const PINNED_DATA_TYPE: string = 'pinned';
 
 /**
  * Gets the data type of tab IDs on DataTransfer objects in drag events. This
  * is a function so that loadTimeData can get overridden by tests.
- * @return {string}
  */
-function getTabIdDataType() {
+function getTabIdDataType(): string {
   return loadTimeData.getString('tabIdDataType');
 }
 
-/** @return {string} */
-function getGroupIdDataType() {
+function getGroupIdDataType(): string {
   return loadTimeData.getString('tabGroupIdDataType');
 }
 
-/** @return {!Tab} */
-function getDefaultTabData() {
+function getDefaultTabData(): Tab {
   return {
     active: false,
     alertStates: [],
@@ -56,89 +50,65 @@
     showIcon: true,
     title: '',
     url: {url: ''},
+
+    // Remove once Mojo can produce proper TypeScript or TypeScript definitions,
+    // so that these properties are recognized as optional.
+    faviconUrl: undefined,
+    groupId: undefined,
   };
 }
 
-/**
- * @interface
- */
-export class DragManagerDelegate {
-  /**
-   * @param {!TabElement} tabElement
-   * @return {number}
-   */
-  getIndexOfTab(tabElement) {}
+export interface DragManagerDelegate {
+  getIndexOfTab(tabElement: TabElement): number;
 
-  /**
-   * @param {!TabElement} element
-   * @param {number} index
-   * @param {boolean} pinned
-   * @param {string=} groupId
-   */
-  placeTabElement(element, index, pinned, groupId) {}
+  placeTabElement(
+      element: TabElement, index: number, pinned: boolean,
+      groupId?: string): void;
 
-  /**
-   * @param {!TabGroupElement} element
-   * @param {number} index
-   */
-  placeTabGroupElement(element, index) {}
+  placeTabGroupElement(element: TabGroupElement, index: number): void;
 
-  /** @return {boolean} */
-  shouldPreventDrag() {}
+  shouldPreventDrag(): boolean;
 }
 
-/** @typedef {!DragManagerDelegate|!HTMLElement} */
-let DragManagerDelegateElement;
+type DragManagerDelegateElement = DragManagerDelegate&HTMLElement;
 
 class DragSession {
-  /**
-   * @param {!DragManagerDelegateElement} delegate
-   * @param {!TabElement|!TabGroupElement} element
-   * @param {number} srcIndex
-   * @param {string=} srcGroup
-   */
-  constructor(delegate, element, srcIndex, srcGroup) {
-    /** @const @private {!DragManagerDelegateElement} */
-    this.delegate_ = delegate;
+  private delegate_: DragManagerDelegateElement;
+  private element_: TabElement|TabGroupElement;
+  private hasMoved_: boolean;
+  private lastPoint_: {x: number, y: number} = {x: 0, y: 0};
 
-    /** @const {!TabElement|!TabGroupElement} */
+  srcIndex: number;
+  srcGroup?: string;
+
+  private tabsProxy_: TabsApiProxy = TabsApiProxyImpl.getInstance();
+
+  constructor(
+      delegate: DragManagerDelegateElement, element: TabElement|TabGroupElement,
+      srcIndex: number, srcGroup?: string) {
+    this.delegate_ = delegate;
     this.element_ = element;
 
     /**
      * Flag indicating if during the drag session, the element has at least
      * moved once.
-     * @private {boolean}
      */
     this.hasMoved_ = false;
 
-    /** @private {!Object<{x: number, y: number}>} */
-    this.lastPoint_ = {x: 0, y: 0};
-
-    /** @const {number} */
     this.srcIndex = srcIndex;
-
-    /** @const {string|undefined} */
     this.srcGroup = srcGroup;
-
-    /** @private @const {!TabsApiProxy} */
-    this.tabsProxy_ = TabsApiProxyImpl.getInstance();
   }
 
-  /**
-   * @param {!DragManagerDelegateElement} delegate
-   * @param {!TabElement|!TabGroupElement} element
-   * @return {!DragSession}
-   */
-  static createFromElement(delegate, element) {
+  static createFromElement(
+      delegate: DragManagerDelegateElement,
+      element: TabElement|TabGroupElement): DragSession {
     if (isTabGroupElement(element)) {
       return new DragSession(
           delegate, element,
-          delegate.getIndexOfTab(
-              /** @type {!TabElement} */ (element.firstElementChild)));
+          delegate.getIndexOfTab(element.firstElementChild as TabElement));
     }
 
-    const srcIndex = delegate.getIndexOfTab(
-        /** @type {!TabElement} */ (element));
+    const srcIndex = delegate.getIndexOfTab(element as TabElement);
     const srcGroup =
         (element.parentElement && isTabGroupElement(element.parentElement)) ?
         element.parentElement.dataset.groupId :
@@ -146,26 +116,22 @@
     return new DragSession(delegate, element, srcIndex, srcGroup);
   }
 
-  /**
-   * @param {!DragManagerDelegateElement} delegate
-   * @param {!DragEvent} event
-   * @return {?DragSession}
-   */
-  static createFromEvent(delegate, event) {
-    if (event.dataTransfer.types.includes(getTabIdDataType())) {
-      const isPinned = event.dataTransfer.types.includes('pinned');
-      const placeholderTabElement =
-          /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
-      placeholderTabElement.tab = /** @type {!Tab} */ (Object.assign(
-          getDefaultTabData(), {id: PLACEHOLDER_TAB_ID, pinned: isPinned}));
+  static createFromEvent(
+      delegate: DragManagerDelegateElement, event: DragEvent): DragSession
+      |null {
+    if (event.dataTransfer!.types.includes(getTabIdDataType())) {
+      const isPinned = event.dataTransfer!.types.includes('pinned');
+      const placeholderTabElement = document.createElement('tabstrip-tab');
+      placeholderTabElement.tab = Object.assign(
+          getDefaultTabData(), {id: PLACEHOLDER_TAB_ID, pinned: isPinned});
       placeholderTabElement.setDragging(true);
       delegate.placeTabElement(placeholderTabElement, -1, isPinned);
       return DragSession.createFromElement(delegate, placeholderTabElement);
     }
 
-    if (event.dataTransfer.types.includes(getGroupIdDataType())) {
-      const placeholderGroupElement = /** @type {!TabGroupElement} */
-          (document.createElement('tabstrip-tab-group'));
+    if (event.dataTransfer!.types.includes(getGroupIdDataType())) {
+      const placeholderGroupElement =
+          document.createElement('tabstrip-tab-group');
       placeholderGroupElement.dataset.groupId = PLACEHOLDER_GROUP_ID;
       placeholderGroupElement.setDragging(true);
       delegate.placeTabGroupElement(placeholderGroupElement, -1);
@@ -175,8 +141,7 @@
     return null;
   }
 
-  /** @return {string|undefined} */
-  get dstGroup() {
+  get dstGroup(): string|undefined {
     if (isTabElement(this.element_) && this.element_.parentElement &&
         isTabGroupElement(this.element_.parentElement)) {
       return this.element_.parentElement.dataset.groupId;
@@ -185,11 +150,9 @@
     return undefined;
   }
 
-  /** @return {number} */
-  get dstIndex() {
+  get dstIndex(): number {
     if (isTabElement(this.element_)) {
-      return this.delegate_.getIndexOfTab(
-          /** @type {!TabElement} */ (this.element_));
+      return this.delegate_.getIndexOfTab(this.element_ as TabElement);
     }
 
     if (this.element_.children.length === 0) {
@@ -201,14 +164,12 @@
         return 0;
       }
       if (isTabElement(previousElement)) {
-        return this.delegate_.getIndexOfTab(
-                   /** @private {!TabElement} */ (previousElement)) +
-            1;
+        return this.delegate_.getIndexOfTab(previousElement as TabElement) + 1;
       }
 
       assert(isTabGroupElement(previousElement));
-      return this.delegate_.getIndexOfTab(/** @private {!TabElement} */ (
-                 previousElement.lastElementChild)) +
+      return this.delegate_.getIndexOfTab(
+                 previousElement.lastElementChild as TabElement) +
           1;
     }
 
@@ -217,15 +178,14 @@
     // moving forwards (to the end of the tab strip), the new index is the index
     // of the last tab in that group.
     let dstIndex = this.delegate_.getIndexOfTab(
-        /** @type {!TabElement} */ (this.element_.firstElementChild));
+        this.element_.firstElementChild as TabElement);
     if (this.srcIndex <= dstIndex) {
       dstIndex += this.element_.childElementCount - 1;
     }
     return dstIndex;
   }
 
-  /** @param {!DragEvent} event */
-  cancel(event) {
+  cancel(event: DragEvent) {
     if (this.isDraggingPlaceholder()) {
       this.element_.remove();
       return;
@@ -233,15 +193,15 @@
 
     if (isTabGroupElement(this.element_)) {
       this.delegate_.placeTabGroupElement(
-          /** @type {!TabGroupElement} */ (this.element_), this.srcIndex);
+          this.element_ as TabGroupElement, this.srcIndex);
     } else if (isTabElement(this.element_)) {
+      const tabElement = this.element_ as TabElement;
       this.delegate_.placeTabElement(
-          /** @type {!TabElement} */ (this.element_), this.srcIndex,
-          this.element_.tab.pinned, this.srcGroup);
+          tabElement, this.srcIndex, tabElement.tab.pinned, this.srcGroup);
     }
 
     if (this.element_.isDraggedOut() &&
-        event.dataTransfer.dropEffect === 'move') {
+        event.dataTransfer!.dropEffect === 'move') {
       // The element was dragged out of the current tab strip and was dropped
       // into a new window. In this case, do not mark the element as no longer
       // being dragged out. The element needs to be kept hidden, and will be
@@ -253,64 +213,52 @@
     this.element_.setDraggedOut(false);
   }
 
-  /** @return {boolean} */
-  isDraggingPlaceholder() {
+  isDraggingPlaceholder(): boolean {
     return this.isDraggingPlaceholderTab_() ||
         this.isDraggingPlaceholderGroup_();
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  isDraggingPlaceholderTab_() {
+  private isDraggingPlaceholderTab_(): boolean {
     return isTabElement(this.element_) &&
-        this.element_.tab.id === PLACEHOLDER_TAB_ID;
+        (this.element_ as TabElement).tab.id === PLACEHOLDER_TAB_ID;
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  isDraggingPlaceholderGroup_() {
+  private isDraggingPlaceholderGroup_(): boolean {
     return isTabGroupElement(this.element_) &&
         this.element_.dataset.groupId === PLACEHOLDER_GROUP_ID;
   }
 
-  /** @param {!DragEvent} event */
-  finish(event) {
+  finish(event: DragEvent) {
     const wasDraggingPlaceholder = this.isDraggingPlaceholderTab_();
     if (wasDraggingPlaceholder) {
-      const id = Number(event.dataTransfer.getData(getTabIdDataType()));
-      this.element_.tab = Object.assign({}, this.element_.tab, {id});
+      const id = Number(event.dataTransfer!.getData(getTabIdDataType()));
+      (this.element_ as TabElement).tab =
+          Object.assign({}, (this.element_ as TabElement).tab, {id});
     } else if (this.isDraggingPlaceholderGroup_()) {
       this.element_.dataset.groupId =
-          event.dataTransfer.getData(getGroupIdDataType());
+          event.dataTransfer!.getData(getGroupIdDataType());
     }
 
     const dstIndex = this.dstIndex;
     if (isTabElement(this.element_)) {
-      this.tabsProxy_.moveTab(this.element_.tab.id, dstIndex);
+      this.tabsProxy_.moveTab((this.element_ as TabElement).tab.id, dstIndex);
     } else if (isTabGroupElement(this.element_)) {
-      this.tabsProxy_.moveGroup(this.element_.dataset.groupId, dstIndex);
+      this.tabsProxy_.moveGroup(this.element_.dataset.groupId!, dstIndex);
     }
 
     const dstGroup = this.dstGroup;
     if (dstGroup && dstGroup !== this.srcGroup) {
-      this.tabsProxy_.groupTab(this.element_.tab.id, dstGroup);
+      this.tabsProxy_.groupTab((this.element_ as TabElement).tab.id, dstGroup);
     } else if (!dstGroup && this.srcGroup) {
-      this.tabsProxy_.ungroupTab(this.element_.tab.id);
+      this.tabsProxy_.ungroupTab((this.element_ as TabElement).tab.id);
     }
 
     this.element_.setDragging(false);
     this.element_.setDraggedOut(false);
   }
 
-  /**
-   * @param {!TabElement|!TabGroupElement} dragOverElement
-   * @return {boolean}
-   */
-  shouldOffsetIndexForGroup_(dragOverElement) {
+  shouldOffsetIndexForGroup_(dragOverElement: TabElement|
+                             TabGroupElement): boolean {
     // Since TabGroupElements do not have any TabElements, they need to offset
     // the index for any elements that come after it as if there is at least
     // one element inside of it.
@@ -319,11 +267,11 @@
            Node.DOCUMENT_POSITION_PRECEDING);
   }
 
-  /** @param {!DragEvent} event */
-  start(event) {
+  start(event: DragEvent) {
     this.lastPoint_ = {x: event.clientX, y: event.clientY};
-    event.dataTransfer.effectAllowed = 'move';
-    const draggedItemRect = event.composedPath()[0].getBoundingClientRect();
+    event.dataTransfer!.effectAllowed = 'move';
+    const draggedItemRect =
+        (event.composedPath()[0] as HTMLElement).getBoundingClientRect();
     this.element_.setDragging(true);
 
     const dragImage = this.element_.getDragImage();
@@ -358,24 +306,23 @@
     yOffset += dragImageCenterRect.height * eventYPercentage;
     yOffset -= verticalOffset;
 
-    event.dataTransfer.setDragImage(dragImage, xOffset, yOffset);
+    event.dataTransfer!.setDragImage(dragImage, xOffset, yOffset);
 
     if (isTabElement(this.element_)) {
-      event.dataTransfer.setData(
-          getTabIdDataType(), this.element_.tab.id.toString());
+      const tabElement = this.element_ as TabElement;
+      event.dataTransfer!.setData(
+          getTabIdDataType(), tabElement.tab.id.toString());
 
-      if (this.element_.tab.pinned) {
-        event.dataTransfer.setData(
-            'pinned', this.element_.tab.pinned.toString());
+      if (tabElement.tab.pinned) {
+        event.dataTransfer!.setData('pinned', tabElement.tab.pinned.toString());
       }
     } else if (isTabGroupElement(this.element_)) {
-      event.dataTransfer.setData(
-          getGroupIdDataType(), this.element_.dataset.groupId);
+      event.dataTransfer!.setData(
+          getGroupIdDataType(), this.element_.dataset.groupId!);
     }
   }
 
-  /** @param {!DragEvent} event */
-  update(event) {
+  update(event: DragEvent) {
     this.lastPoint_ = {x: event.clientX, y: event.clientY};
 
     if (event.type === 'dragleave') {
@@ -384,7 +331,7 @@
       return;
     }
 
-    event.dataTransfer.dropEffect = 'move';
+    event.dataTransfer!.dropEffect = 'move';
     this.element_.setDraggedOut(false);
     if (isTabGroupElement(this.element_)) {
       this.updateForTabGroupElement_(event);
@@ -393,21 +340,16 @@
     }
   }
 
-  /**
-   * @param {!DragEvent} event
-   * @private
-   */
-  updateForTabGroupElement_(event) {
-    const tabGroupElement =
-        /** @type {!TabGroupElement} */ (this.element_);
-    const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
+  private updateForTabGroupElement_(event: DragEvent) {
+    const tabGroupElement = this.element_ as TabGroupElement;
+    const composedPath = event.composedPath() as Element[];
     if (composedPath.includes(assert(this.element_))) {
       // Dragging over itself or a child of itself.
       return;
     }
 
     const dragOverTabElement =
-        /** @type {!TabElement|undefined} */ (composedPath.find(isTabElement));
+        composedPath.find(isTabElement) as TabElement | undefined;
     if (dragOverTabElement && !dragOverTabElement.tab.pinned &&
         dragOverTabElement.isValidDragOverTarget) {
       let dragOverIndex = this.delegate_.getIndexOfTab(dragOverTabElement);
@@ -418,11 +360,11 @@
       return;
     }
 
-    const dragOverGroupElement = /** @type {!TabGroupElement|undefined} */ (
-        composedPath.find(isTabGroupElement));
+    const dragOverGroupElement =
+        composedPath.find(isTabGroupElement) as TabGroupElement | undefined;
     if (dragOverGroupElement && dragOverGroupElement.isValidDragOverTarget) {
       let dragOverIndex = this.delegate_.getIndexOfTab(
-          /** @type {!TabElement} */ (dragOverGroupElement.firstElementChild));
+          dragOverGroupElement.firstElementChild as TabElement);
       dragOverIndex +=
           this.shouldOffsetIndexForGroup_(dragOverGroupElement) ? 1 : 0;
       this.delegate_.placeTabGroupElement(tabGroupElement, dragOverIndex);
@@ -430,15 +372,11 @@
     }
   }
 
-  /**
-   * @param {!DragEvent} event
-   * @private
-   */
-  updateForTabElement_(event) {
-    const tabElement = /** @type {!TabElement} */ (this.element_);
-    const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
+  private updateForTabElement_(event: DragEvent) {
+    const tabElement = this.element_ as TabElement;
+    const composedPath = event.composedPath() as Element[];
     const dragOverTabElement =
-        /** @type {?TabElement} */ (composedPath.find(isTabElement));
+        composedPath.find(isTabElement) as TabElement | undefined;
     if (dragOverTabElement &&
         (dragOverTabElement.tab.pinned !== tabElement.tab.pinned ||
          !dragOverTabElement.isValidDragOverTarget)) {
@@ -452,7 +390,7 @@
         undefined;
 
     const dragOverTabGroup =
-        /** @type {?TabGroupElement} */ (composedPath.find(isTabGroupElement));
+        composedPath.find(isTabGroupElement) as TabGroupElement | undefined;
     if (dragOverTabGroup &&
         dragOverTabGroup.dataset.groupId !== previousGroupId &&
         dragOverTabGroup.isValidDragOverTarget) {
@@ -481,34 +419,25 @@
 }
 
 export class DragManager {
-  /** @param {!DragManagerDelegateElement} delegate */
-  constructor(delegate) {
-    /** @private {!DragManagerDelegateElement} */
+  private delegate_: DragManagerDelegateElement;
+  private dragSession_: DragSession|null = null;
+  private tabsProxy_: TabsApiProxy = TabsApiProxyImpl.getInstance();
+
+  constructor(delegate: DragManagerDelegateElement) {
     this.delegate_ = delegate;
-
-    /** @type {?DragSession} */
-    this.dragSession_ = null;
-
-    /** @private {!TabsApiProxy} */
-    this.tabsProxy_ = TabsApiProxyImpl.getInstance();
   }
 
-  /**
-   * @param {!DragEvent} event
-   * @private
-   */
-  onDragLeave_(event) {
+  private onDragLeave_(event: DragEvent) {
     if (this.dragSession_ && this.dragSession_.isDraggingPlaceholder()) {
       this.dragSession_.cancel(event);
       this.dragSession_ = null;
       return;
     }
 
-    this.dragSession_.update(event);
+    this.dragSession_!.update(event);
   }
 
-  /** @param {!DragEvent} event */
-  onDragOver_(event) {
+  private onDragOver_(event: DragEvent) {
     event.preventDefault();
     if (!this.dragSession_) {
       return;
@@ -517,9 +446,8 @@
     this.dragSession_.update(event);
   }
 
-  /** @param {!DragEvent} event */
-  onDragStart_(event) {
-    const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
+  private onDragStart_(event: DragEvent) {
+    const composedPath = event.composedPath() as Element[];
     const draggedItem = composedPath.find(item => {
       return isTabElement(item) || isTabGroupElement(item);
     });
@@ -531,8 +459,7 @@
     // state is reset to avoid any associated css effects making it onto the
     // drag image.
     if (isTabElement(draggedItem) || isTabGroupElement(draggedItem)) {
-      /** @private {!TabElement|!TabGroupElement} */ (draggedItem)
-          .setTouchPressed(false);
+      (draggedItem as TabElement | TabGroupElement).setTouchPressed(false);
     }
 
     // Make sure drag handle is under touch point when dragging a tab group.
@@ -546,13 +473,11 @@
     }
 
     this.dragSession_ = DragSession.createFromElement(
-        this.delegate_,
-        /** @type {!TabElement|!TabGroupElement} */ (draggedItem));
+        this.delegate_, draggedItem as TabElement | TabGroupElement);
     this.dragSession_.start(event);
   }
 
-  /** @param {!DragEvent} event */
-  onDragEnd_(event) {
+  private onDragEnd_(event: DragEvent) {
     if (!this.dragSession_) {
       return;
     }
@@ -561,8 +486,7 @@
     this.dragSession_ = null;
   }
 
-  /** @param {!DragEvent} event */
-  onDragEnter_(event) {
+  private onDragEnter_(event: DragEvent) {
     if (this.dragSession_) {
       // TODO(crbug.com/843556): Do not update the drag session on dragenter.
       // An incorrect event target on dragenter causes tabs to move around
@@ -573,10 +497,7 @@
     this.dragSession_ = DragSession.createFromEvent(this.delegate_, event);
   }
 
-  /**
-   * @param {!DragEvent} event
-   */
-  onDrop_(event) {
+  private onDrop_(event: DragEvent) {
     if (!this.dragSession_) {
       return;
     }
@@ -586,17 +507,11 @@
   }
 
   startObserving() {
-    this.delegate_.addEventListener(
-        'dragstart', e => this.onDragStart_(/** @type {!DragEvent} */ (e)));
-    this.delegate_.addEventListener(
-        'dragend', e => this.onDragEnd_(/** @type {!DragEvent} */ (e)));
-    this.delegate_.addEventListener(
-        'dragenter', e => this.onDragEnter_(/** @type {!DragEvent} */ (e)));
-    this.delegate_.addEventListener(
-        'dragleave', e => this.onDragLeave_(/** @type {!DragEvent} */ (e)));
-    this.delegate_.addEventListener(
-        'dragover', e => this.onDragOver_(/** @type {!DragEvent} */ (e)));
-    this.delegate_.addEventListener(
-        'drop', e => this.onDrop_(/** @type {!DragEvent} */ (e)));
+    this.delegate_.addEventListener('dragstart', e => this.onDragStart_(e));
+    this.delegate_.addEventListener('dragend', e => this.onDragEnd_(e));
+    this.delegate_.addEventListener('dragenter', e => this.onDragEnter_(e));
+    this.delegate_.addEventListener('dragleave', e => this.onDragLeave_(e));
+    this.delegate_.addEventListener('dragover', e => this.onDragOver_(e));
+    this.delegate_.addEventListener('drop', e => this.onDrop_(e));
   }
 }
diff --git a/chrome/browser/resources/tab_strip/tab.js b/chrome/browser/resources/tab_strip/tab.ts
similarity index 74%
rename from chrome/browser/resources/tab_strip/tab.js
rename to chrome/browser/resources/tab_strip/tab.ts
index 5a3d99a..7c31eb1 100644
--- a/chrome/browser/resources/tab_strip/tab.js
+++ b/chrome/browser/resources/tab_strip/tab.ts
@@ -17,13 +17,9 @@
 import {TabSwiper} from './tab_swiper.js';
 import {CloseTabAction, TabsApiProxy, TabsApiProxyImpl} from './tabs_api_proxy.js';
 
-const DEFAULT_ANIMATION_DURATION = 125;
+const DEFAULT_ANIMATION_DURATION: number = 125;
 
-/**
- * @param {!Tab} tab
- * @return {string}
- */
-function getAccessibleTitle(tab) {
+function getAccessibleTitle(tab: Tab): string {
   const tabTitle = tab.title;
 
   if (tab.crashed) {
@@ -39,9 +35,8 @@
 
 /**
  * TODO(crbug.com/1025390): padding-inline-end cannot be animated yet.
- * @return {string}
  */
-function getPaddingInlineEndProperty() {
+function getPaddingInlineEndProperty(): string {
   return isRTL() ? 'paddingLeft' : 'paddingRight';
 }
 
@@ -50,78 +45,73 @@
     return `{__html_template__}`;
   }
 
+  private alertIndicatorsEl_: AlertIndicatorsElement;
+  private closeButtonEl_: HTMLElement;
+  private dragImageEl_: HTMLElement;
+  private tabEl_: HTMLElement;
+  private faviconEl_: HTMLElement;
+  private thumbnailContainer_: HTMLElement;
+  private thumbnail_: HTMLImageElement;
+  private tab_: Tab;
+  private tabsApi_: TabsApiProxy;
+  private titleTextEl_: HTMLElement;
+  private isValidDragOverTarget_: boolean;
+  private tabSwiper_: TabSwiper;
+  private onTabActivating_: (tabId: number) => void;
+
   constructor() {
     super();
 
-    this.alertIndicatorsEl_ = /** @type {!AlertIndicatorsElement} */
-        (this.$('tabstrip-alert-indicators'));
+    this.alertIndicatorsEl_ =
+        this.$('tabstrip-alert-indicators') as AlertIndicatorsElement;
     // Normally, custom elements will get upgraded automatically once added to
     // the DOM, but TabElement may need to update properties on
     // AlertIndicatorElement before this happens, so upgrade it manually.
     customElements.upgrade(this.alertIndicatorsEl_);
 
-    /** @private {!HTMLElement} */
-    this.closeButtonEl_ = /** @type {!HTMLElement} */ (this.$('#close'));
+    this.closeButtonEl_ = this.$('#close') as HTMLElement;
     this.closeButtonEl_.setAttribute(
         'aria-label', loadTimeData.getString('closeTab'));
 
-    /** @private {!HTMLElement} */
-    this.dragImageEl_ = /** @type {!HTMLElement} */ (this.$('#dragImage'));
+    this.dragImageEl_ = this.$('#dragImage') as HTMLElement;
 
-    /** @private {!HTMLElement} */
-    this.tabEl_ = /** @type {!HTMLElement} */ (this.$('#tab'));
+    this.tabEl_ = this.$('#tab') as HTMLElement;
 
-    /** @private {!HTMLElement} */
-    this.faviconEl_ = /** @type {!HTMLElement} */ (this.$('#favicon'));
+    this.faviconEl_ = this.$('#favicon') as HTMLElement;
 
-    /** @private {!HTMLElement} */
-    this.thumbnailContainer_ =
-        /** @type {!HTMLElement} */ (this.$('#thumbnail'));
+    this.thumbnailContainer_ = this.$('#thumbnail') as HTMLElement;
 
-    /** @private {!Image} */
-    this.thumbnail_ = /** @type {!Image} */ (this.$('#thumbnailImg'));
+    this.thumbnail_ = this.$('#thumbnailImg') as HTMLImageElement;
 
-    /** @private {!Tab} */
-    this.tab_;
-
-    /** @private {!TabsApiProxy} */
     this.tabsApi_ = TabsApiProxyImpl.getInstance();
 
-    /** @private {!HTMLElement} */
-    this.titleTextEl_ = /** @type {!HTMLElement} */ (this.$('#titleText'));
+    this.titleTextEl_ = this.$('#titleText') as HTMLElement;
 
     /**
      * Flag indicating if this TabElement can accept dragover events. This
      * is used to pause dragover events while animating as animating causes
      * the elements below the pointer to shift.
-     * @private {boolean}
      */
     this.isValidDragOverTarget_ = true;
 
     this.tabEl_.addEventListener('click', () => this.onClick_());
     this.tabEl_.addEventListener('contextmenu', e => this.onContextMenu_(e));
-    this.tabEl_.addEventListener(
-        'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e)));
-    this.tabEl_.addEventListener(
-        'pointerup', e => this.onPointerUp_(/** @type {!PointerEvent} */ (e)));
+    this.tabEl_.addEventListener('keydown', e => this.onKeyDown_(e));
+    this.tabEl_.addEventListener('pointerup', e => this.onPointerUp_(e));
 
     this.closeButtonEl_.addEventListener('click', e => this.onClose_(e));
     this.addEventListener('swipe', () => this.onSwipe_());
 
-    /** @private @const {!TabSwiper} */
     this.tabSwiper_ = new TabSwiper(this);
 
-    /** @private {!Function} */
-    this.onTabActivating_ = (tabId) => {};
+    this.onTabActivating_ = (tabId: number) => {};
   }
 
-  /** @return {!Tab} */
-  get tab() {
+  get tab(): Tab {
     return this.tab_;
   }
 
-  /** @param {!Tab} tab */
-  set tab(tab) {
+  set tab(tab: Tab) {
     this.toggleAttribute('active', tab.active);
     this.tabEl_.setAttribute('aria-selected', tab.active.toString());
     this.toggleAttribute('hide-icon_', !tab.showIcon);
@@ -135,7 +125,7 @@
             tab.networkState === TabNetworkState.kLoading);
     this.toggleAttribute('pinned', tab.pinned);
     this.toggleAttribute('blocked_', tab.blocked);
-    this.setAttribute('draggable', true);
+    this.setAttribute('draggable', String(true));
     this.toggleAttribute('crashed_', tab.crashed);
 
     if (tab.title) {
@@ -161,7 +151,7 @@
     }
 
     // Expose the ID to an attribute to allow easy querySelector use
-    this.setAttribute('data-tab-id', tab.id);
+    this.setAttribute('data-tab-id', tab.id.toString());
 
     this.alertIndicatorsEl_.updateAlertStates(tab.alertStates)
         .then((alertIndicatorsCount) => {
@@ -177,18 +167,15 @@
     this.tab_ = Object.freeze(tab);
   }
 
-  /** @return {boolean} */
-  get isValidDragOverTarget() {
+  get isValidDragOverTarget(): boolean {
     return !this.hasAttribute('dragging_') && this.isValidDragOverTarget_;
   }
 
-  /** @param {boolean} isValid */
-  set isValidDragOverTarget(isValid) {
+  set isValidDragOverTarget(isValid: boolean) {
     this.isValidDragOverTarget_ = isValid;
   }
 
-  /** @param {!Function} callback */
-  set onTabActivating(callback) {
+  set onTabActivating(callback: (tabId: number) => void) {
     this.onTabActivating_ = callback;
   }
 
@@ -196,27 +183,21 @@
     this.tabEl_.focus();
   }
 
-  /** @return {!HTMLElement} */
-  getDragImage() {
+  getDragImage(): HTMLElement {
     return this.dragImageEl_;
   }
 
-  /** @return {!HTMLElement} */
-  getDragImageCenter() {
+  getDragImageCenter(): HTMLElement {
     // dragImageEl_ has padding, so the drag image should be centered relative
     // to tabEl_, the element within the padding.
     return this.tabEl_;
   }
 
-  /**
-   * @param {string} imgData
-   */
-  updateThumbnail(imgData) {
+  updateThumbnail(imgData: string) {
     this.thumbnail_.src = imgData;
   }
 
-  /** @private */
-  onClick_() {
+  private onClick_() {
     if (!this.tab_ || this.tabSwiper_.wasSwiping()) {
       return;
     }
@@ -228,46 +209,29 @@
     this.tabsApi_.closeContainer();
   }
 
-  /**
-   * @param {!Event} event
-   * @private
-   */
-  onContextMenu_(event) {
+  private onContextMenu_(event: Event) {
     event.preventDefault();
     event.stopPropagation();
   }
 
-  /**
-   * @param {!Event} event
-   * @private
-   */
-  onClose_(event) {
+  private onClose_(event: Event) {
     assert(this.tab_);
     event.stopPropagation();
     this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.CLOSE_BUTTON);
   }
 
-  /** @private */
-  onSwipe_() {
+  private onSwipe_() {
     assert(this.tab_);
     this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.SWIPED_TO_CLOSE);
   }
 
-  /**
-   * @param {!KeyboardEvent} event
-   * @private
-   */
-  onKeyDown_(event) {
+  private onKeyDown_(event: KeyboardEvent) {
     if (event.key === 'Enter' || event.key === ' ') {
       this.onClick_();
     }
   }
 
-  /**
-   * @param {!PointerEvent} event
-   * @private
-   */
-  onPointerUp_(event) {
+  private onPointerUp_(event: PointerEvent) {
     event.stopPropagation();
     if (event.pointerType !== 'touch' && event.button === 2) {
       this.tabsApi_.showTabContextMenu(
@@ -279,32 +243,23 @@
     this.tabSwiper_.reset();
   }
 
-  /**
-   * @param {boolean} isDragging
-   */
-  setDragging(isDragging) {
+  setDragging(isDragging: boolean) {
     this.toggleAttribute('dragging_', isDragging);
   }
 
-  /** @param {boolean} isDraggedOut */
-  setDraggedOut(isDraggedOut) {
+  setDraggedOut(isDraggedOut: boolean) {
     this.toggleAttribute('dragged-out_', isDraggedOut);
   }
 
-  /** @return {boolean} */
-  isDraggedOut() {
+  isDraggedOut(): boolean {
     return this.hasAttribute('dragged-out_');
   }
 
-  /** @param {boolean} isTouchPressed */
-  setTouchPressed(isTouchPressed) {
+  setTouchPressed(isTouchPressed: boolean) {
     this.toggleAttribute('touch_pressed_', isTouchPressed);
   }
 
-  /**
-   * @return {!Promise}
-   */
-  slideIn() {
+  slideIn(): Promise<void> {
     const paddingInlineEnd = getPaddingInlineEndProperty();
 
     // If this TabElement is the last tab, there needs to be enough space for
@@ -315,15 +270,14 @@
     const startState = {
       maxWidth: isLastChild ? 'var(--tabstrip-tab-width)' : 0,
       transform: `scale(0)`,
+      [paddingInlineEnd]: isLastChild ? 'var(--tabstrip-tab-spacing)' : 0,
     };
-    startState[paddingInlineEnd] =
-        isLastChild ? 'var(--tabstrip-tab-spacing)' : 0;
 
     const finishState = {
       maxWidth: `var(--tabstrip-tab-width)`,
       transform: `scale(1)`,
+      [paddingInlineEnd]: 'var(--tabstrip-tab-spacing)',
     };
-    finishState[paddingInlineEnd] = 'var(--tabstrip-tab-spacing)';
 
     return new Promise(resolve => {
       const animation = this.animate([startState, finishState], {
@@ -348,10 +302,7 @@
     });
   }
 
-  /**
-   * @return {!Promise}
-   */
-  slideOut() {
+  slideOut(): Promise<void> {
     if (!this.tabsApi_.isVisible() || this.tab_.pinned ||
         this.tabSwiper_.wasSwiping()) {
       this.remove();
@@ -385,10 +336,11 @@
 
       const widthAnimationKeyframes = {
         maxWidth: ['var(--tabstrip-tab-width)', 0],
+        [getPaddingInlineEndProperty()]: ['var(--tabstrip-tab-spacing)', 0],
       };
-      widthAnimationKeyframes[getPaddingInlineEndProperty()] =
-          ['var(--tabstrip-tab-spacing)', 0];
-      const widthAnimation = this.animate(widthAnimationKeyframes, {
+      // TODO(dpapad): Figure out why TypeScript compiler does not understand
+      // the alternative keyframe syntax. Seems to work in the TS playground.
+      const widthAnimation = this.animate(widthAnimationKeyframes as any, {
         delay: 97.5,
         duration: 300,
         easing: 'cubic-bezier(.4, 0, 0, 1)',
@@ -421,12 +373,14 @@
   }
 }
 
+declare global {
+  interface HTMLElementTagNameMap {
+    'tabstrip-tab': TabElement;
+  }
+}
+
 customElements.define('tabstrip-tab', TabElement);
 
-/**
- * @param {!Element} element
- * @return {boolean}
- */
-export function isTabElement(element) {
+export function isTabElement(element: Element): boolean {
   return element.tagName === 'TABSTRIP-TAB';
 }
diff --git a/chrome/browser/resources/tab_strip/tab_group.js b/chrome/browser/resources/tab_strip/tab_group.ts
similarity index 70%
rename from chrome/browser/resources/tab_strip/tab_group.js
rename to chrome/browser/resources/tab_strip/tab_group.ts
index 31a7355..bb0be405 100644
--- a/chrome/browser/resources/tab_strip/tab_group.js
+++ b/chrome/browser/resources/tab_strip/tab_group.ts
@@ -13,14 +13,16 @@
     return `{__html_template__}`;
   }
 
+  private tabsApi_: TabsApiProxy;
+  private chip_: HTMLElement;
+  private isValidDragOverTarget_: boolean;
+
   constructor() {
     super();
 
-    /** @private @const {!TabsApiProxy} */
     this.tabsApi_ = TabsApiProxyImpl.getInstance();
 
-    /** @private @const {!HTMLElement} */
-    this.chip_ = /** @type {!HTMLElement} */ (this.$('#chip'));
+    this.chip_ = this.$('#chip') as HTMLElement;
     this.chip_.addEventListener('click', () => this.onClickChip_());
     this.chip_.addEventListener(
         'keydown', e => this.onKeydownChip_(/** @type {!KeyboardEvent} */ (e)));
@@ -28,57 +30,46 @@
     /**
      * Flag indicating if this element can accept dragover events. This flag
      * is updated by TabListElement while animating.
-     * @private {boolean}
      */
     this.isValidDragOverTarget_ = true;
   }
 
-  /** @return {boolean} */
-  get isValidDragOverTarget() {
+  get isValidDragOverTarget(): boolean {
     return !this.hasAttribute('dragging_') && this.isValidDragOverTarget_;
   }
 
-  /** @param {boolean} isValid */
-  set isValidDragOverTarget(isValid) {
+  set isValidDragOverTarget(isValid: boolean) {
     this.isValidDragOverTarget_ = isValid;
   }
 
-  /** @return {!HTMLElement} */
-  getDragImage() {
-    return /** @type {!HTMLElement} */ (this.$('#dragImage'));
+  getDragImage(): HTMLElement {
+    return this.$('#dragImage') as HTMLElement;
   }
 
-  /** @return {!HTMLElement} */
-  getDragImageCenter() {
+  getDragImageCenter(): HTMLElement {
     // Since the drag handle is #dragHandle, the drag image should be
     // centered relatively to it.
-    return /** @type {!HTMLElement} */ (this.$('#dragHandle'));
+    return this.$('#dragHandle') as HTMLElement;
   }
 
-  /** @private */
-  onClickChip_() {
+  private onClickChip_() {
     if (!this.dataset.groupId) {
       return;
     }
 
-    const boundingBox = this.$('#chip').getBoundingClientRect();
+    const boundingBox = this.$('#chip')!.getBoundingClientRect();
     this.tabsApi_.showEditDialogForGroup(
         this.dataset.groupId, boundingBox.left, boundingBox.top,
         boundingBox.width, boundingBox.height);
   }
 
-  /**
-   * @param {!KeyboardEvent} event
-   * @private
-   */
-  onKeydownChip_(event) {
+  private onKeydownChip_(event: KeyboardEvent) {
     if (event.key === 'Enter' || event.key === ' ') {
       this.onClickChip_();
     }
   }
 
-  /** @param {boolean} enabled */
-  setDragging(enabled) {
+  setDragging(enabled: boolean) {
     // Since the draggable target is the #chip, if the #chip moves and is no
     // longer under the pointer while the dragstart event is happening, the drag
     // will get canceled. This is unfortunately the behavior of the native drag
@@ -92,26 +83,20 @@
     });
   }
 
-  /** @param {boolean} isDraggedOut */
-  setDraggedOut(isDraggedOut) {
+  setDraggedOut(isDraggedOut: boolean) {
     this.toggleAttribute('dragged-out_', isDraggedOut);
   }
 
-  /** @return {boolean} */
-  isDraggedOut() {
+  isDraggedOut(): boolean {
     return this.hasAttribute('dragged-out_');
   }
 
-  /** @param {boolean} isTouchPressed */
-  setTouchPressed(isTouchPressed) {
+  setTouchPressed(isTouchPressed: boolean) {
     this.toggleAttribute('touch_pressed_', isTouchPressed);
   }
 
-  /**
-   * @param {!TabGroupVisualData} visualData
-   */
-  updateVisuals(visualData) {
-    this.$('#title').innerText = visualData.title;
+  updateVisuals(visualData: TabGroupVisualData) {
+    (this.$('#title') as HTMLElement).innerText = visualData.title;
     this.style.setProperty('--tabstrip-tab-group-color-rgb', visualData.color);
     this.style.setProperty(
         '--tabstrip-tab-group-text-color-rgb', visualData.textColor);
@@ -129,20 +114,18 @@
   }
 }
 
+declare global {
+  interface HTMLElementTagNameMap {
+    'tabstrip-tab-group': TabGroupElement;
+  }
+}
+
 customElements.define('tabstrip-tab-group', TabGroupElement);
 
-/**
- * @param {!Element} element
- * @return {boolean}
- */
-export function isTabGroupElement(element) {
+export function isTabGroupElement(element: Element): boolean {
   return element.tagName === 'TABSTRIP-TAB-GROUP';
 }
 
-/**
- * @param {!Element} element
- * @return {boolean}
- */
-export function isDragHandle(element) {
+export function isDragHandle(element: Element): boolean {
   return element.id === 'dragHandle';
 }
diff --git a/chrome/browser/resources/tab_strip/tab_list.js b/chrome/browser/resources/tab_strip/tab_list.ts
similarity index 70%
rename from chrome/browser/resources/tab_strip/tab_list.js
rename to chrome/browser/resources/tab_strip/tab_list.ts
index 9adab5b..863196e8 100644
--- a/chrome/browser/resources/tab_strip/tab_list.js
+++ b/chrome/browser/resources/tab_strip/tab_list.ts
@@ -23,25 +23,19 @@
  * The amount of padding to leave between the edge of the screen and the active
  * tab when auto-scrolling. This should leave some room to show the previous or
  * next tab to afford to users that there more tabs if the user scrolls.
- * @const {number}
  */
-const SCROLL_PADDING = 32;
+const SCROLL_PADDING: number = 32;
 
-/** @type {boolean} */
-let scrollAnimationEnabled = true;
+let scrollAnimationEnabled: boolean = true;
 
-/** @const {number} */
-const TOUCH_CONTEXT_MENU_OFFSET_X = 8;
+const TOUCH_CONTEXT_MENU_OFFSET_X: number = 8;
 
-/** @const {number} */
-const TOUCH_CONTEXT_MENU_OFFSET_Y = -40;
+const TOUCH_CONTEXT_MENU_OFFSET_Y: number = -40;
 
 /**
  * Context menu should position below the element for touch.
- * @param {!Element} element
- * @return {!Object<{x: number, y: number}>}
  */
-function getContextMenuPosition(element) {
+function getContextMenuPosition(element: Element): {x: number, y: number} {
   const rect = element.getBoundingClientRect();
   return {
     x: rect.left + TOUCH_CONTEXT_MENU_OFFSET_X,
@@ -49,26 +43,20 @@
   };
 }
 
-/** @param {boolean} enabled */
-export function setScrollAnimationEnabledForTesting(enabled) {
+export function setScrollAnimationEnabledForTesting(enabled: boolean) {
   scrollAnimationEnabled = enabled;
 }
 
-/**
- * @enum {string}
- */
-const LayoutVariable = {
-  VIEWPORT_WIDTH: '--tabstrip-viewport-width',
-  TAB_WIDTH: '--tabstrip-tab-thumbnail-width',
-};
+enum LayoutVariable {
+  VIEWPORT_WIDTH = '--tabstrip-viewport-width',
+  TAB_WIDTH = '--tabstrip-tab-thumbnail-width',
+}
 
 /**
  * Animates a series of elements to indicate that tabs have moved position.
- * @param {!Element} movedElement
- * @param {number} prevIndex
- * @param {number} newIndex
  */
-function animateElementMoved(movedElement, prevIndex, newIndex) {
+function animateElementMoved(
+    movedElement: Element, prevIndex: number, newIndex: number) {
   // Direction is -1 for moving towards a lower index, +1 for moving
   // towards a higher index. If moving towards a lower index, the TabList needs
   // to animate everything from the movedElement's current index to its prev
@@ -78,11 +66,7 @@
   // traverse the previousElementSiblings.
   const direction = Math.sign(newIndex - prevIndex);
 
-  /**
-   * @param {!Element} element
-   * @return {?Element}
-   */
-  function getSiblingToAnimate(element) {
+  function getSiblingToAnimate(element: Element): Element|null {
     return direction === -1 ? element.nextElementSibling :
                               element.previousElementSibling;
   }
@@ -101,15 +85,12 @@
 /**
  * Animates the slide of an element across the tab strip (both vertically and
  * horizontally for pinned tabs, and horizontally for other tabs and groups).
- * @param {!Element} element
- * @param {number} prevIndex
- * @param {number} newIndex
  */
-function slideElement(element, prevIndex, newIndex) {
+function slideElement(element: Element, prevIndex: number, newIndex: number) {
   let horizontalMovement = newIndex - prevIndex;
   let verticalMovement = 0;
 
-  if (isTabElement(element) && element.tab.pinned) {
+  if (isTabElement(element) && (element as TabElement).tab.pinned) {
     const pinnedTabsPerColumn = 3;
     const columnChange = Math.floor(newIndex / pinnedTabsPerColumn) -
         Math.floor(prevIndex / pinnedTabsPerColumn);
@@ -125,7 +106,7 @@
   const translateY = `calc(${verticalMovement * -1} * ` +
       '(var(--tabstrip-tab-height) + var(--tabstrip-tab-spacing)))';
 
-  element.isValidDragOverTarget = false;
+  (element as TabElement | TabGroupElement).isValidDragOverTarget = false;
   const animation = element.animate(
       [
         {transform: `translate(${translateX}, ${translateY})`},
@@ -136,14 +117,36 @@
         easing: 'ease-out',
       });
   function onComplete() {
-    element.isValidDragOverTarget = true;
+    (element as TabElement | TabGroupElement).isValidDragOverTarget = true;
   }
   animation.oncancel = onComplete;
   animation.onfinish = onComplete;
 }
 
-/** @implements {DragManagerDelegate} */
-export class TabListElement extends CustomElement {
+export class TabListElement extends CustomElement implements
+    DragManagerDelegate {
+  animationPromises: Promise<void>;
+  private currentScrollUpdateFrame_: number|null;
+  private documentVisibilityChangeListener_: () => void;
+  private draggedItem_?: TabElement|TabGroupElement;
+  private dropPlaceholder_: HTMLElement;
+  private focusOutlineManager_: FocusOutlineManager;
+  private thumbnailTracker_: Map<number, boolean>;
+  private intersectionObserver_: IntersectionObserver;
+
+  private activatingTabId_?: number;
+  private activatingTabIdTimestamp_?: number;  // In ms.
+  private eventTracker_: EventTracker;
+  private lastTargetedItem_: TabElement|TabGroupElement|null = null;
+  private lastTouchPoint_?: {clientX: number, clientY: number};
+  private pinnedTabsElement_: Element;
+  private tabsApi_: TabsApiProxy;
+  private unpinnedTabsElement_: Element;
+  private webUIListeners_: WebUIListener[];
+  private windowBlurListener_: () => void;
+  private scrollingTimeoutId_: number;
+  private scrollListener_: (e: Event) => void;
+
   static get template() {
     return `{__html_template__}`;
   }
@@ -156,37 +159,30 @@
      * is useful in cases when the list needs to wait for all animations to
      * finish in order to get accurate pixels (such as getting the position of a
      * tab) or accurate element counts.
-     * @type {!Promise}
      */
     this.animationPromises = Promise.resolve();
 
     /**
      * The ID of the current animation frame that is in queue to update the
      * scroll position.
-     * @private {?number}
      */
     this.currentScrollUpdateFrame_ = null;
 
-    /** @private {!Function} */
     this.documentVisibilityChangeListener_ = () =>
         this.onDocumentVisibilityChange_();
 
     /**
      * The element that is currently being dragged.
-     * @private {!TabElement|!TabGroupElement|undefined}
      */
     this.draggedItem_;
 
-    /** @private {!Element} */
     this.dropPlaceholder_ = document.createElement('div');
     this.dropPlaceholder_.id = 'dropPlaceholder';
 
-    /** @private @const {!FocusOutlineManager} */
     this.focusOutlineManager_ = FocusOutlineManager.forDocument(document);
 
     /**
      * Map of tab IDs to whether or not the tab's thumbnail should be tracked.
-     * @private {!Map<number, boolean>}
      */
     this.thumbnailTracker_ = new Map();
 
@@ -195,11 +191,11 @@
      * currently in view or close to being in view, which will help determine
      * which thumbnails need to be tracked to stay fresh and which can be
      * untracked until they become visible.
-     * @private {!IntersectionObserver}
      */
     this.intersectionObserver_ = new IntersectionObserver(entries => {
       for (const entry of entries) {
-        this.thumbnailTracker_.set(entry.target.tab.id, entry.isIntersecting);
+        this.thumbnailTracker_.set(
+            (entry.target as TabElement).tab.id, entry.isIntersecting);
       }
 
       if (this.scrollingTimeoutId_ === -1) {
@@ -214,46 +210,25 @@
       rootMargin: '0% 100%',
     });
 
-    /** @private {number|undefined} */
-    this.activatingTabId_;
-
-    /** @private {number|undefined} Timestamp in ms */
-    this.activatingTabIdTimestamp_;
-
-    /** @private @const {!EventTracker} */
     this.eventTracker_ = new EventTracker();
 
-    /** @private {!TabElement|!TabGroupElement|null} */
-    this.lastTargetedItem_;
+    this.pinnedTabsElement_ = this.$('#pinnedTabs')!;
 
-    /** @private {!Object<{x: number, y: number}>|undefined} */
-    this.lastTouchPoint_;
-
-    /** @private {!Element} */
-    this.pinnedTabsElement_ = /** @type {!Element} */ (this.$('#pinnedTabs'));
-
-    /** @private {!TabsApiProxy} */
     this.tabsApi_ = TabsApiProxyImpl.getInstance();
 
-    /** @private {!Element} */
-    this.unpinnedTabsElement_ =
-        /** @type {!Element} */ (this.$('#unpinnedTabs'));
+    this.unpinnedTabsElement_ = this.$('#unpinnedTabs')!;
 
-    /** @private {!Array<!WebUIListener>} */
     this.webUIListeners_ = [];
 
-    /** @private {!Function} */
     this.windowBlurListener_ = () => this.onWindowBlur_();
 
     /**
      * Timeout that is created at every scroll event and is either canceled at
      * each subsequent scroll event or resolves after a few milliseconds after
      * the last scroll event.
-     * @private {number}
      */
     this.scrollingTimeoutId_ = -1;
 
-    /** @private {!Function} */
     this.scrollListener_ = (e) => this.onScroll_(e);
 
     this.addWebUIListener_('theme-changed', () => {
@@ -266,7 +241,7 @@
 
     const callbackRouter = this.tabsApi_.getCallbackRouter();
     callbackRouter.layoutChanged.addListener(
-        layout => this.applyCSSDictionary_(layout));
+        this.applyCSSDictionary_.bind(this));
 
     callbackRouter.tabThumbnailUpdated.addListener(
         this.tabThumbnailUpdated_.bind(this));
@@ -282,14 +257,13 @@
     this.eventTracker_.add(
         document, 'contextmenu', e => this.onContextMenu_(e));
     this.eventTracker_.add(
-        document, 'pointerup',
-        e => this.onPointerUp_(/** @type {!PointerEvent} */ (e)));
+        document, 'pointerup', e => this.onPointerUp_(e as PointerEvent));
     this.eventTracker_.add(
         document, 'visibilitychange', () => this.onDocumentVisibilityChange_());
     this.eventTracker_.add(window, 'blur', () => this.onWindowBlur_());
     this.eventTracker_.add(this, 'scroll', e => this.onScroll_(e));
     this.eventTracker_.add(
-        document, 'touchstart', (e) => this.onTouchStart_(e));
+        document, 'touchstart', e => this.onTouchStart_(e as TouchEvent));
     // Touchmove events happen when a user has started a touch gesture sequence
     // and proceeded to move their touch pointer across the screen. Ensure that
     // we clear the `last_targeted_item_` in these cases to ensure the pressed
@@ -301,28 +275,15 @@
     dragManager.startObserving();
   }
 
-  /**
-   * @param {!Promise} promise
-   * @private
-   */
-  addAnimationPromise_(promise) {
+  private addAnimationPromise_(promise: Promise<void>) {
     this.animationPromises = this.animationPromises.then(() => promise);
   }
 
-  /**
-   * @param {string} eventName
-   * @param {!Function} callback
-   * @private
-   */
-  addWebUIListener_(eventName, callback) {
+  private addWebUIListener_(eventName: string, callback: Function) {
     this.webUIListeners_.push(addWebUIListener(eventName, callback));
   }
 
-  /**
-   * @param {number} scrollBy
-   * @private
-   */
-  animateScrollPosition_(scrollBy) {
+  private animateScrollPosition_(scrollBy: number) {
     if (this.currentScrollUpdateFrame_) {
       cancelAnimationFrame(this.currentScrollUpdateFrame_);
       this.currentScrollUpdateFrame_ = null;
@@ -336,9 +297,9 @@
     }
 
     const duration = 350;
-    let startTime;
+    let startTime: number;
 
-    const onAnimationFrame = (currentTime) => {
+    const onAnimationFrame = (currentTime: number) => {
       const startScroll = this.scrollLeft;
       if (!startTime) {
         startTime = currentTime;
@@ -362,18 +323,13 @@
     this.currentScrollUpdateFrame_ = requestAnimationFrame(onAnimationFrame);
   }
 
-  /**
-   * @param {!Object<string, string>} dictionary
-   * @private
-   */
-  applyCSSDictionary_(dictionary) {
+  private applyCSSDictionary_(dictionary: {[key: string]: string}) {
     for (const [cssVariable, value] of Object.entries(dictionary)) {
       this.style.setProperty(cssVariable, value);
     }
   }
 
-  /** @private */
-  clearScrollTimeout_() {
+  private clearScrollTimeout_() {
     clearTimeout(this.scrollingTimeoutId_);
     this.scrollingTimeoutId_ = -1;
   }
@@ -397,28 +353,23 @@
       const callbackRouter = this.tabsApi_.getCallbackRouter();
       callbackRouter.showContextMenu.addListener(
           () => this.onShowContextMenu_());
-      callbackRouter.tabCreated.addListener(tab => this.onTabCreated_(tab));
-      callbackRouter.tabMoved.addListener(
-          (tabId, newIndex, pinned) =>
-              this.onTabMoved_(tabId, newIndex, pinned));
-      callbackRouter.tabRemoved.addListener(tabId => this.onTabRemoved_(tabId));
-      callbackRouter.tabReplaced.addListener(
-          (oldId, newId) => this.onTabReplaced_(oldId, newId));
-      callbackRouter.tabUpdated.addListener(tab => this.onTabUpdated_(tab));
+      callbackRouter.tabCreated.addListener(this.onTabCreated_.bind(this));
+      callbackRouter.tabMoved.addListener(this.onTabMoved_.bind(this));
+      callbackRouter.tabRemoved.addListener(this.onTabRemoved_.bind(this));
+      callbackRouter.tabReplaced.addListener(this.onTabReplaced_.bind(this));
+      callbackRouter.tabUpdated.addListener(this.onTabUpdated_.bind(this));
       callbackRouter.tabActiveChanged.addListener(
-          tabId => this.onTabActivated_(tabId));
+          this.onTabActivated_.bind(this));
       callbackRouter.tabCloseCancelled.addListener(
-          tabId => this.onTabCloseCancelled_(tabId));
+          this.onTabCloseCancelled_.bind(this));
       callbackRouter.tabGroupStateChanged.addListener(
-          (tabId, index, groupId) =>
-              this.onTabGroupStateChanged_(tabId, index, groupId));
+          this.onTabGroupStateChanged_.bind(this));
       callbackRouter.tabGroupClosed.addListener(
-          groupId => this.onTabGroupClosed_(groupId));
+          this.onTabGroupClosed_.bind(this));
       callbackRouter.tabGroupMoved.addListener(
-          (groupId, index) => this.onTabGroupMoved_(groupId, index));
+          this.onTabGroupMoved_.bind(this));
       callbackRouter.tabGroupVisualsChanged.addListener(
-          (groupId, visualData) =>
-              this.onTabGroupVisualsChanged_(groupId, visualData));
+          this.onTabGroupVisualsChanged_.bind(this));
     });
   }
 
@@ -427,12 +378,7 @@
     this.eventTracker_.removeAll();
   }
 
-  /**
-   * @param {!Tab} tab
-   * @return {!TabElement}
-   * @private
-   */
-  createTabElement_(tab) {
+  private createTabElement_(tab: Tab): TabElement {
     const tabElement = new TabElement();
     tabElement.tab = tab;
     tabElement.onTabActivating = (id) => {
@@ -441,95 +387,63 @@
     return tabElement;
   }
 
-  /**
-   * @param {number} tabId
-   * @return {?TabElement}
-   * @private
-   */
-  findTabElement_(tabId) {
-    return /** @type {?TabElement} */ (
-        this.$(`tabstrip-tab[data-tab-id="${tabId}"]`));
+  private findTabElement_(tabId: number): TabElement|null {
+    return this.$(`tabstrip-tab[data-tab-id="${tabId}"]`) as TabElement | null;
   }
 
-  /**
-   * @param {string} groupId
-   * @return {?TabGroupElement}
-   * @private
-   */
-  findTabGroupElement_(groupId) {
-    return /** @type {?TabGroupElement} */ (
-        this.$(`tabstrip-tab-group[data-group-id="${groupId}"]`));
+  private findTabGroupElement_(groupId: string): TabGroupElement|null {
+    return this.$(`tabstrip-tab-group[data-group-id="${groupId}"]`) as
+        TabGroupElement |
+        null;
   }
 
-  /** @private */
-  fetchAndUpdateColors_() {
+  private fetchAndUpdateColors_() {
     this.tabsApi_.getColors().then(
         ({colors}) => this.applyCSSDictionary_(colors));
   }
 
-  /** @private */
-  fetchAndUpdateGroupData_() {
-    const tabGroupElements = this.$all('tabstrip-tab-group');
+  private fetchAndUpdateGroupData_() {
+    const tabGroupElements =
+        this.$all('tabstrip-tab-group') as NodeListOf<TabGroupElement>;
     this.tabsApi_.getGroupVisualData().then(({data}) => {
       tabGroupElements.forEach(tabGroupElement => {
         tabGroupElement.updateVisuals(
-            assert(data[tabGroupElement.dataset.groupId]));
+            assert(data[tabGroupElement.dataset.groupId!])!);
       });
     });
   }
 
-  /** @private */
-  fetchAndUpdateTabs_() {
+  private fetchAndUpdateTabs_() {
     this.tabsApi_.getTabs().then(({tabs}) => {
       tabs.forEach(tab => this.onTabUpdated_(tab));
     });
   }
 
-  /**
-   * @return {?TabElement}
-   * @private
-   */
-  getActiveTab_() {
-    return /** @type {?TabElement} */ (this.$('tabstrip-tab[active]'));
+  private getActiveTab_(): TabElement|null {
+    return this.$('tabstrip-tab[active]') as TabElement | null;
   }
 
-  /**
-   * @param {!TabElement} tabElement
-   * @return {number}
-   */
-  getIndexOfTab(tabElement) {
+  getIndexOfTab(tabElement: TabElement): number {
     return Array.prototype.indexOf.call(this.$all('tabstrip-tab'), tabElement);
   }
 
-  /**
-   * @param {!LayoutVariable} variable
-   * @return {number} in pixels
-   */
-  getLayoutVariable_(variable) {
+  /** @return in pixels */
+  private getLayoutVariable_(variable: LayoutVariable): number {
     return parseInt(this.style.getPropertyValue(variable), 10);
   }
 
-  /** @private */
-  handleLongPress_() {
+  private handleLongPress_() {
     if (this.lastTargetedItem_) {
       this.lastTargetedItem_.setTouchPressed(true);
     }
   }
 
-  /**
-   * @param {!Event} event
-   * @private
-   */
-  onContextMenu_(event) {
+  private onContextMenu_(event: Event) {
     // Prevent the default context menu from triggering.
     event.preventDefault();
   }
 
-  /**
-   * @param {!PointerEvent} event
-   * @private
-   */
-  onPointerUp_(event) {
+  private onPointerUp_(event: PointerEvent) {
     event.stopPropagation();
     if (event.pointerType !== 'touch' && event.button === 2) {
       // If processing an uncaught right click event show the background context
@@ -538,41 +452,34 @@
     }
   }
 
-  /** @private */
-  onDocumentVisibilityChange_() {
+  private onDocumentVisibilityChange_() {
     if (!this.tabsApi_.isVisible()) {
       this.scrollToActiveTab_();
     }
 
     this.unpinnedTabsElement_.childNodes.forEach(element => {
-      if (isTabGroupElement(/** @type {!Element} */ (element))) {
+      if (isTabGroupElement(element as Element)) {
         element.childNodes.forEach(
-            tabElement => this.updateThumbnailTrackStatus_(
-                /** @type {!TabElement} */ (tabElement)));
+            tabElement =>
+                this.updateThumbnailTrackStatus_(tabElement as TabElement));
       } else {
-        this.updateThumbnailTrackStatus_(
-            /** @type {!TabElement} */ (element));
+        this.updateThumbnailTrackStatus_(element as TabElement);
       }
     });
   }
 
-  /** @private */
-  onReceivedKeyboardFocus_() {
+  private onReceivedKeyboardFocus_() {
     // FocusOutlineManager relies on the most recent event fired on the
     // document. When the tab strip first gains keyboard focus, no such event
     // exists yet, so the outline needs to be explicitly set to visible.
     this.focusOutlineManager_.visible = true;
-    this.$('tabstrip-tab').focus();
+    (this.$('tabstrip-tab') as HTMLElement).focus();
   }
 
-  /**
-   * @param {number} tabId
-   * @private
-   */
-  onTabActivated_(tabId) {
+  private onTabActivated_(tabId: number) {
     if (this.activatingTabId_ === tabId) {
       this.tabsApi_.reportTabActivationDuration(
-          Date.now() - this.activatingTabIdTimestamp_);
+          Date.now() - this.activatingTabIdTimestamp_!);
     }
     this.activatingTabId_ = undefined;
     this.activatingTabIdTimestamp_ = undefined;
@@ -581,28 +488,25 @@
     // have updated a Tab to have an active state. For example, if a
     // tab is created with an already active state, there may be 2 active
     // TabElements: the newly created tab and the previously active tab.
-    this.$all('tabstrip-tab[active]').forEach((previouslyActiveTab) => {
-      if (previouslyActiveTab.tab.id !== tabId) {
-        previouslyActiveTab.tab = /** @type {!Tab} */ (
-            Object.assign({}, previouslyActiveTab.tab, {active: false}));
-      }
-    });
+    (this.$all('tabstrip-tab[active]') as NodeListOf<TabElement>)
+        .forEach((previouslyActiveTab) => {
+          if (previouslyActiveTab.tab.id !== tabId) {
+            previouslyActiveTab.tab = /** @type {!Tab} */ (
+                Object.assign({}, previouslyActiveTab.tab, {active: false}));
+          }
+        });
 
     const newlyActiveTab = this.findTabElement_(tabId);
     if (newlyActiveTab) {
-      newlyActiveTab.tab = /** @type {!Tab} */ (
-          Object.assign({}, newlyActiveTab.tab, {active: true}));
+      newlyActiveTab.tab =
+          Object.assign({}, newlyActiveTab.tab, {active: true});
       if (!this.tabsApi_.isVisible()) {
         this.scrollToTab_(newlyActiveTab);
       }
     }
   }
 
-  /**
-   * @param {number} id The tab ID
-   * @private
-   */
-  onTabActivating_(id) {
+  private onTabActivating_(id: number) {
     assert(this.activatingTabId_ === undefined);
     const activeTab = this.getActiveTab_();
     if (activeTab && activeTab.tab.id === id) {
@@ -612,11 +516,7 @@
     this.activatingTabIdTimestamp_ = Date.now();
   }
 
-  /**
-   * @param {number} id
-   * @private
-   */
-  onTabCloseCancelled_(id) {
+  private onTabCloseCancelled_(id: number) {
     const tabElement = this.findTabElement_(id);
     if (!tabElement) {
       return;
@@ -624,8 +524,7 @@
     tabElement.resetSwipe();
   }
 
-  /** @private */
-  onShowContextMenu_() {
+  private onShowContextMenu_() {
     // If we do not have a touch point don't show the context menu.
     if (!this.lastTouchPoint_) {
       return;
@@ -634,18 +533,15 @@
     if (this.lastTargetedItem_ && isTabElement(this.lastTargetedItem_)) {
       const position = getContextMenuPosition(this.lastTargetedItem_);
       this.tabsApi_.showTabContextMenu(
-          this.lastTargetedItem_.tab.id, position.x, position.y);
+          (this.lastTargetedItem_ as TabElement).tab.id, position.x,
+          position.y);
     } else {
       this.tabsApi_.showBackgroundContextMenu(
           this.lastTouchPoint_.clientX, this.lastTouchPoint_.clientY);
     }
   }
 
-  /**
-   * @param {!Tab} tab
-   * @private
-   */
-  onTabCreated_(tab) {
+  private onTabCreated_(tab: Tab) {
     const droppedTabElement = this.findTabElement_(tab.id);
     if (droppedTabElement) {
       droppedTabElement.tab = tab;
@@ -662,11 +558,7 @@
     }
   }
 
-  /**
-   * @param {string} groupId
-   * @private
-   */
-  onTabGroupClosed_(groupId) {
+  private onTabGroupClosed_(groupId: string) {
     const tabGroupElement = this.findTabGroupElement_(groupId);
     if (!tabGroupElement) {
       return;
@@ -674,12 +566,7 @@
     tabGroupElement.remove();
   }
 
-  /**
-   * @param {string} groupId
-   * @param {number} index
-   * @private
-   */
-  onTabGroupMoved_(groupId, index) {
+  private onTabGroupMoved_(groupId: string, index: number) {
     const tabGroupElement = this.findTabGroupElement_(groupId);
     if (!tabGroupElement) {
       return;
@@ -687,36 +574,20 @@
     this.placeTabGroupElement(tabGroupElement, index);
   }
 
-  /**
-   * @param {number} tabId
-   * @param {number} index
-   * @param {string} groupId
-   * @private
-   */
-  onTabGroupStateChanged_(tabId, index, groupId) {
-    const tabElement = this.findTabElement_(tabId);
-    tabElement.tab = /** @type {!Tab} */ (
-        Object.assign({}, tabElement.tab, {groupId: groupId}));
+  private onTabGroupStateChanged_(
+      tabId: number, index: number, groupId: string) {
+    const tabElement = this.findTabElement_(tabId)!;
+    tabElement.tab = Object.assign({}, tabElement.tab, {groupId: groupId});
     this.placeTabElement(tabElement, index, false, groupId);
   }
 
-  /**
-   * @param {string} groupId
-   * @param {!TabGroupVisualData} visualData
-   * @private
-   */
-  onTabGroupVisualsChanged_(groupId, visualData) {
-    const tabGroupElement = this.findTabGroupElement_(groupId);
+  private onTabGroupVisualsChanged_(
+      groupId: string, visualData: TabGroupVisualData) {
+    const tabGroupElement = this.findTabGroupElement_(groupId)!;
     tabGroupElement.updateVisuals(visualData);
   }
 
-  /**
-   * @param {number} tabId
-   * @param {number} newIndex
-   * @param {boolean} pinned
-   * @private
-   */
-  onTabMoved_(tabId, newIndex, pinned) {
+  private onTabMoved_(tabId: number, newIndex: number, pinned: boolean) {
     const movedTab = this.findTabElement_(tabId);
     if (movedTab) {
       this.placeTabElement(movedTab, newIndex, pinned, movedTab.tab.groupId);
@@ -726,37 +597,23 @@
     }
   }
 
-  /**
-   * @param {number} tabId
-   * @private
-   */
-  onTabRemoved_(tabId) {
+  private onTabRemoved_(tabId: number) {
     const tabElement = this.findTabElement_(tabId);
     if (tabElement) {
       this.addAnimationPromise_(tabElement.slideOut());
     }
   }
 
-  /**
-   * @param {number} oldId
-   * @param {number} newId
-   * @private
-   */
-  onTabReplaced_(oldId, newId) {
+  private onTabReplaced_(oldId: number, newId: number) {
     const tabElement = this.findTabElement_(oldId);
     if (!tabElement) {
       return;
     }
 
-    tabElement.tab =
-        /** @type {!Tab} */ (Object.assign({}, tabElement.tab, {id: newId}));
+    tabElement.tab = Object.assign({}, tabElement.tab, {id: newId});
   }
 
-  /**
-   * @param {!Tab} tab
-   * @private
-   */
-  onTabUpdated_(tab) {
+  private onTabUpdated_(tab: Tab) {
     const tabElement = this.findTabElement_(tab.id);
     if (!tabElement) {
       return;
@@ -776,21 +633,16 @@
     }
   }
 
-  /** @private */
-  onWindowBlur_() {
-    if (this.shadowRoot.activeElement) {
+  private onWindowBlur_() {
+    if (this.shadowRoot!.activeElement) {
       // Blur the currently focused element when the window is blurred. This
       // prevents the screen reader from momentarily reading out the
       // previously focused element when the focus returns to this window.
-      this.shadowRoot.activeElement.blur();
+      (this.shadowRoot!.activeElement as HTMLElement).blur();
     }
   }
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onScroll_(e) {
+  private onScroll_(e: Event) {
     this.clearScrollTimeout_();
     this.scrollingTimeoutId_ = setTimeout(() => {
       this.flushThumbnailTracker_();
@@ -798,16 +650,12 @@
     }, 100);
   }
 
-  /**
-   * @param {!Event} event
-   * @private
-   */
-  onTouchStart_(event) {
-    const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
+  private onTouchStart_(event: TouchEvent) {
+    const composedPath = event.composedPath() as Element[];
     const dragOverTabElement =
-        /** @type {!TabElement|!TabGroupElement|null} */ (
-            composedPath.find(isTabElement) ||
-            composedPath.find(isTabGroupElement));
+        (composedPath.find(isTabElement) ||
+         composedPath.find(isTabGroupElement) || null) as TabElement |
+        TabGroupElement | null;
 
     // Make sure drag handle is under touch point when dragging a tab group.
     if (dragOverTabElement && isTabGroupElement(dragOverTabElement) &&
@@ -816,12 +664,11 @@
     }
 
     this.lastTargetedItem_ = dragOverTabElement;
-    const touch = event.changedTouches[0];
+    const touch = event.changedTouches[0]!;
     this.lastTouchPoint_ = {clientX: touch.clientX, clientY: touch.clientY};
   }
 
-  /** @private */
-  clearLastTargetedItem_() {
+  private clearLastTargetedItem_() {
     if (this.lastTargetedItem_) {
       this.lastTargetedItem_.setTouchPressed(false);
     }
@@ -829,13 +676,8 @@
     this.lastTouchPoint_ = undefined;
   }
 
-  /**
-   * @param {!TabElement} element
-   * @param {number} index
-   * @param {boolean} pinned
-   * @param {string=} groupId
-   */
-  placeTabElement(element, index, pinned, groupId) {
+  placeTabElement(
+      element: TabElement, index: number, pinned: boolean, groupId?: string) {
     const isInserting = !element.isConnected;
 
     const previousIndex = isInserting ? -1 : this.getIndexOfTab(element);
@@ -853,16 +695,11 @@
     }
   }
 
-  /**
-   * @param {!TabGroupElement} element
-   * @param {number} index
-   */
-  placeTabGroupElement(element, index) {
+  placeTabGroupElement(element: TabGroupElement, index: number) {
     const previousDomIndex =
         Array.from(this.unpinnedTabsElement_.children).indexOf(element);
     if (element.isConnected && element.childElementCount &&
-        this.getIndexOfTab(
-            /** @type {!TabElement} */ (element.firstElementChild)) < index) {
+        this.getIndexOfTab(element.firstElementChild as TabElement) < index) {
       // If moving after its original position, the index value needs to be
       // offset by 1 to consider itself already attached to the DOM.
       index++;
@@ -885,16 +722,14 @@
         Array.from(this.unpinnedTabsElement_.children).indexOf(element));
   }
 
-  /** @private */
-  flushThumbnailTracker_() {
+  private flushThumbnailTracker_() {
     this.thumbnailTracker_.forEach((shouldTrack, tabId) => {
       this.tabsApi_.setThumbnailTracked(tabId, shouldTrack);
     });
     this.thumbnailTracker_.clear();
   }
 
-  /** @private */
-  scrollToActiveTab_() {
+  private scrollToActiveTab_() {
     const activeTab = this.getActiveTab_();
     if (!activeTab) {
       return;
@@ -903,11 +738,7 @@
     this.scrollToTab_(activeTab);
   }
 
-  /**
-   * @param {!TabElement} tabElement
-   * @private
-   */
-  scrollToTab_(tabElement) {
+  private scrollToTab_(tabElement: TabElement) {
     const tabElementWidth = this.getLayoutVariable_(LayoutVariable.TAB_WIDTH);
     const tabElementRect = tabElement.getBoundingClientRect();
     // In RTL languages, the TabElement's scale animation scales from right to
@@ -942,31 +773,19 @@
     this.animateScrollPosition_(scrollBy);
   }
 
-  /** @return {boolean} */
-  shouldPreventDrag() {
+  shouldPreventDrag(): boolean {
     return this.$all('tabstrip-tab').length === 1;
   }
 
-  /**
-   * @param {number} tabId
-   * @param {string} imgData
-   * @private
-   */
-  tabThumbnailUpdated_(tabId, imgData) {
+  private tabThumbnailUpdated_(tabId: number, imgData: string) {
     const tab = this.findTabElement_(tabId);
     if (tab) {
       tab.updateThumbnail(imgData);
     }
   }
 
-  /**
-   * @param {!TabElement} element
-   * @param {number} index
-   * @param {boolean} pinned
-   * @param {string=} groupId
-   * @private
-   */
-  updateTabElementDomPosition_(element, index, pinned, groupId) {
+  private updateTabElementDomPosition_(
+      element: TabElement, index: number, pinned: boolean, groupId?: string) {
     // Remove the element if it already exists in the DOM. This simplifies
     // the way indices work as it does not have to count its old index in
     // the initial layout of the DOM.
@@ -974,9 +793,9 @@
 
     if (pinned) {
       this.pinnedTabsElement_.insertBefore(
-          element, this.pinnedTabsElement_.childNodes[index]);
+          element, this.pinnedTabsElement_.childNodes[index]!);
     } else {
-      let elementToInsert = element;
+      let elementToInsert: TabElement|TabGroupElement = element;
       let elementAtIndex = this.$all('tabstrip-tab').item(index);
       let parentElement = this.unpinnedTabsElement_;
 
@@ -1016,11 +835,7 @@
     }
   }
 
-  /**
-   * @param {!TabElement} tabElement
-   * @private
-   */
-  updateThumbnailTrackStatus_(tabElement) {
+  private updateThumbnailTrackStatus_(tabElement: TabElement) {
     if (!tabElement.tab) {
       return;
     }
diff --git a/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js b/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js
deleted file mode 100644
index 3bfcc59f..0000000
--- a/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js
+++ /dev/null
@@ -1,126 +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 {addSingletonGetter, addWebUIListener, sendWithPromise} from 'chrome://resources/js/cr.m.js';
-
-/** @interface */
-export class TabStripEmbedderProxy {
-  /** @return {boolean} */
-  isVisible() {}
-
-  /**
-   * @return {!Promise<!Object<string, string>>} Object with CSS variables
-   *     as keys and rgba strings as values
-   */
-  getColors() {}
-
-  /**
-   * @return {!Promise<!Object<string, string>>} Object with CSS variables
-   *     as keys and pixel lengths as values
-   */
-  getLayout() {}
-
-  observeThemeChanges() {}
-
-  /**
-   * @param {string} groupId
-   * @param {number} locationX
-   * @param {number} locationY
-   * @param {number} width
-   * @param {number} height
-   */
-  showEditDialogForGroup(groupId, locationX, locationY, width, height) {}
-
-  /**
-   * @param {number} tabId
-   * @param {number} locationX
-   * @param {number} locationY
-   */
-  showTabContextMenu(tabId, locationX, locationY) {}
-
-  /**
-   * @param {number} locationX
-   * @param {number} locationY
-   */
-  showBackgroundContextMenu(locationX, locationY) {}
-
-  closeContainer() {}
-
-  /** @param {number} durationMs Activation duration time in ms. */
-  reportTabActivationDuration(durationMs) {}
-
-  /**
-   * @param {number} tabCount Number of tabs.
-   * @param {number} durationMs Activation duration time in ms.
-   */
-  reportTabDataReceivedDuration(tabCount, durationMs) {}
-
-  /**
-   * @param {number} tabCount Number of tabs.
-   * @param {number} durationMs Creation duration time in ms.
-   */
-  reportTabCreationDuration(tabCount, durationMs) {}
-}
-
-/** @implements {TabStripEmbedderProxy} */
-export class TabStripEmbedderProxyImpl {
-  /** @override */
-  isVisible() {
-    return document.visibilityState === 'visible';
-  }
-
-  /** @override */
-  getColors() {
-    return sendWithPromise('getThemeColors');
-  }
-
-  /** @override */
-  getLayout() {
-    return sendWithPromise('getLayout');
-  }
-
-  /** @override */
-  observeThemeChanges() {
-    chrome.send('observeThemeChanges');
-  }
-
-  /** @override */
-  showEditDialogForGroup(groupId, locationX, locationY, width, height) {
-    chrome.send(
-        'showEditDialogForGroup',
-        [groupId, locationX, locationY, width, height]);
-  }
-
-  /** @override */
-  showTabContextMenu(tabId, locationX, locationY) {
-    chrome.send('showTabContextMenu', [tabId, locationX, locationY]);
-  }
-
-  /** @override */
-  showBackgroundContextMenu(locationX, locationY) {
-    chrome.send('showBackgroundContextMenu', [locationX, locationY]);
-  }
-
-  /** @override */
-  closeContainer() {
-    chrome.send('closeContainer');
-  }
-
-  /** @override */
-  reportTabActivationDuration(durationMs) {
-    chrome.send('reportTabActivationDuration', [durationMs]);
-  }
-
-  /** @override */
-  reportTabDataReceivedDuration(tabCount, durationMs) {
-    chrome.send('reportTabDataReceivedDuration', [tabCount, durationMs]);
-  }
-
-  /** @override */
-  reportTabCreationDuration(tabCount, durationMs) {
-    chrome.send('reportTabCreationDuration', [tabCount, durationMs]);
-  }
-}
-
-addSingletonGetter(TabStripEmbedderProxyImpl);
diff --git a/chrome/browser/resources/tab_strip/tab_swiper.js b/chrome/browser/resources/tab_strip/tab_swiper.ts
similarity index 71%
rename from chrome/browser/resources/tab_strip/tab_swiper.js
rename to chrome/browser/resources/tab_strip/tab_swiper.ts
index 3f51808..b267fe7 100644
--- a/chrome/browser/resources/tab_strip/tab_swiper.js
+++ b/chrome/browser/resources/tab_strip/tab_swiper.ts
@@ -7,17 +7,15 @@
 /**
  * The minimum amount of pixels needed for the user to swipe for the position
  * (controlled by transform property) to start animating to 0.
- * @const {number}
  */
-export const TRANSLATE_ANIMATION_THRESHOLD_PX = 30;
+export const TRANSLATE_ANIMATION_THRESHOLD_PX: number = 30;
 
 /**
  * The minimum amount of pixels needed for the user to swipe to actually close
  * the tab. This also triggers animating other properties to suggest more that
  * the tab will close, such as animating the max-width.
- * @const {number}
  */
-export const SWIPE_START_THRESHOLD_PX = 100;
+export const SWIPE_START_THRESHOLD_PX: number = 100;
 
 /**
  * The maximum amount of pixels needed to swipe a tab away. This is how many
@@ -25,55 +23,47 @@
  * animation to complete such that the tab is gone from the screen.
  * TODO(johntlee): Make this relative to the height of the tab, not a
  * hard-coded value.
- * @const {number}
  */
-export const SWIPE_FINISH_THRESHOLD_PX = 200;
+export const SWIPE_FINISH_THRESHOLD_PX: number = 200;
 
 /**
  * The minimum velocity of pixels per milliseconds required for the tab to
  * register the set of pointer events as an intended swipe.
- * @const {number}
  */
-const SWIPE_VELOCITY_THRESHOLD = 0.2;
+const SWIPE_VELOCITY_THRESHOLD: number = 0.2;
 
 export class TabSwiper {
-  /** @param {!HTMLElement} element */
-  constructor(element) {
-    /** @private @const {!HTMLElement} */
+  private element_: HTMLElement;
+  private animation_: Animation;
+  private animationInitiated_: boolean;
+  private currentPointerDownEvent_: PointerEvent|null = null;
+
+  private pointerDownListener_: (e: PointerEvent) => void;
+  private pointerMoveListener_: (e: PointerEvent) => void;
+  private pointerLeaveListener_: (e: PointerEvent) => void;
+  private pointerUpListener_: (e: PointerEvent) => void;
+
+  constructor(element: HTMLElement) {
     this.element_ = element;
 
-    /** @private @const {!Animation} */
     this.animation_ = this.createAnimation_();
 
     /**
      * Whether any part of the animation that updates properties has begun since
      * the last pointerdown event.
-     * @private {boolean}
      */
     this.animationInitiated_ = false;
 
-    /** @private {?PointerEvent} */
-    this.currentPointerDownEvent_ = null;
+    this.pointerDownListener_ = e => this.onPointerDown_(e);
 
-    /** @private @const {!Function} */
-    this.pointerDownListener_ = e =>
-        this.onPointerDown_(/** @type {!PointerEvent} */ (e));
+    this.pointerMoveListener_ = e => this.onPointerMove_(e);
 
-    /** @private @const {!Function} */
-    this.pointerMoveListener_ = e =>
-        this.onPointerMove_(/** @type {!PointerEvent} */ (e));
+    this.pointerLeaveListener_ = e => this.onPointerLeave_(e);
 
-    /** @private @const {!Function} */
-    this.pointerLeaveListener_ = e =>
-        this.onPointerLeave_(/** @type {!PointerEvent} */ (e));
-
-    /** @private @const {!Function} */
-    this.pointerUpListener_ = e =>
-        this.onPointerUp_(/** @type {!PointerEvent} */ (e));
+    this.pointerUpListener_ = e => this.onPointerUp_(e);
   }
 
-  /** @private */
-  clearPointerEvents_() {
+  private clearPointerEvents_() {
     this.currentPointerDownEvent_ = null;
     this.element_.removeEventListener(
         'pointerleave', this.pointerLeaveListener_);
@@ -81,8 +71,7 @@
     this.element_.removeEventListener('pointerup', this.pointerUpListener_);
   }
 
-  /** @private */
-  createAnimation_() {
+  private createAnimation_() {
     // TODO(crbug.com/1025390): padding-inline-end does not work with
     // animations built using JS.
     const paddingInlineEnd = isRTL() ? 'paddingLeft' : 'paddingRight';
@@ -128,11 +117,7 @@
     return animation;
   }
 
-  /**
-   * @param {!PointerEvent} event
-   * @private
-   */
-  onPointerDown_(event) {
+  private onPointerDown_(event: PointerEvent) {
     if (this.currentPointerDownEvent_ || event.pointerType !== 'touch') {
       return;
     }
@@ -146,29 +131,21 @@
     this.element_.addEventListener('pointerup', this.pointerUpListener_);
   }
 
-  /**
-   * @param {!PointerEvent} event
-   * @private
-   */
-  onPointerLeave_(event) {
-    if (this.currentPointerDownEvent_.pointerId !== event.pointerId) {
+  private onPointerLeave_(event: PointerEvent) {
+    if (this.currentPointerDownEvent_!.pointerId !== event.pointerId) {
       return;
     }
 
     this.clearPointerEvents_();
   }
 
-  /**
-   * @param {!PointerEvent} event
-   * @private
-   */
-  onPointerMove_(event) {
-    if (this.currentPointerDownEvent_.pointerId !== event.pointerId ||
+  private onPointerMove_(event: PointerEvent) {
+    if (this.currentPointerDownEvent_!.pointerId !== event.pointerId ||
         event.movementY === 0) {
       return;
     }
 
-    const yDiff = this.currentPointerDownEvent_.clientY - event.clientY;
+    const yDiff = this.currentPointerDownEvent_!.clientY - event.clientY;
     const animationTime = yDiff;
     this.animation_.currentTime =
         Math.max(0, Math.min(SWIPE_FINISH_THRESHOLD_PX, animationTime));
@@ -180,19 +157,15 @@
     }
   }
 
-  /**
-   * @param {!PointerEvent} event
-   * @private
-   */
-  onPointerUp_(event) {
-    if (this.currentPointerDownEvent_.pointerId !== event.pointerId) {
+  private onPointerUp_(event: PointerEvent) {
+    if (this.currentPointerDownEvent_!.pointerId !== event.pointerId) {
       return;
     }
 
-    const pixelsSwiped = this.animation_.currentTime;
+    const pixelsSwiped = this.animation_.currentTime!;
     const swipedEnoughToClose = pixelsSwiped > SWIPE_START_THRESHOLD_PX;
     const wasHighVelocity = pixelsSwiped /
-            (event.timeStamp - this.currentPointerDownEvent_.timeStamp) >
+            (event.timeStamp - this.currentPointerDownEvent_!.timeStamp) >
         SWIPE_VELOCITY_THRESHOLD;
 
     if (pixelsSwiped === SWIPE_FINISH_THRESHOLD_PX) {
@@ -222,8 +195,7 @@
     this.element_.removeEventListener('pointerdown', this.pointerDownListener_);
   }
 
-  /** @return {boolean} */
-  wasSwiping() {
+  wasSwiping(): boolean {
     return this.animationInitiated_;
   }
 }
diff --git a/chrome/browser/resources/tab_strip/tabs_api_proxy.js b/chrome/browser/resources/tab_strip/tabs_api_proxy.js
deleted file mode 100644
index 8f2ed98c..0000000
--- a/chrome/browser/resources/tab_strip/tabs_api_proxy.js
+++ /dev/null
@@ -1,265 +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 {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
-import {PageCallbackRouter, PageHandlerFactory, PageHandlerRemote, Tab, TabGroupVisualData} from './tab_strip.mojom-webui.js';
-
-/**
- * These values are persisted to logs and should not be renumbered or re-used.
- * See tools/metrics/histograms/enums.xml.
- * @enum {number}
- */
-export const CloseTabAction = {
-  CLOSE_BUTTON: 0,
-  SWIPED_TO_CLOSE: 1,
-};
-
-/** @typedef {!Tab} */
-export let ExtensionsApiTab;
-
-/** @interface */
-export class TabsApiProxy {
-  /**
-   * @param {number} tabId
-   * @return {!Promise<!ExtensionsApiTab>}
-   */
-  activateTab(tabId) {}
-
-  /**
-   * @return {!Promise<{data: !Object<!TabGroupVisualData>}>} Object of group
-   *     IDs as strings mapped to their visual data.
-   */
-  getGroupVisualData() {}
-
-  /**
-   * @return {!Promise<{tabs: !Array<!Tab>}>}
-   */
-  getTabs() {}
-
-  /**
-   * @param {number} tabId
-   * @param {!CloseTabAction} closeTabAction
-   */
-  closeTab(tabId, closeTabAction) {}
-
-  /**
-   * @param {number} tabId
-   * @param {string} groupId
-   */
-  groupTab(tabId, groupId) {}
-
-  /**
-   * @param {string} groupId
-   * @param {number} newIndex
-   */
-  moveGroup(groupId, newIndex) {}
-
-  /**
-   * @param {number} tabId
-   * @param {number} newIndex
-   */
-  moveTab(tabId, newIndex) {}
-
-  /**
-   * @param {number} tabId
-   * @param {boolean} thumbnailTracked
-   */
-  setThumbnailTracked(tabId, thumbnailTracked) {}
-
-  /** @param {number} tabId */
-  ungroupTab(tabId) {}
-
-
-  /** @return {boolean} */
-  isVisible() {}
-
-  /**
-   * @return {!Promise<{colors: !Object<string, string>}>} Object with CSS
-   *     variables as keys and rgba strings as values
-   */
-  getColors() {}
-
-  /**
-   * @return {!Promise<{layout: !Object<string, string>}>} Object with CSS
-   *     variables as keys and pixel lengths as values
-   */
-  getLayout() {}
-
-  observeThemeChanges() {}
-
-  /**
-   * @param {string} groupId
-   * @param {number} locationX
-   * @param {number} locationY
-   * @param {number} width
-   * @param {number} height
-   */
-  showEditDialogForGroup(groupId, locationX, locationY, width, height) {}
-
-  /**
-   * @param {number} tabId
-   * @param {number} locationX
-   * @param {number} locationY
-   */
-  showTabContextMenu(tabId, locationX, locationY) {}
-
-  /**
-   * @param {number} locationX
-   * @param {number} locationY
-   */
-  showBackgroundContextMenu(locationX, locationY) {}
-
-  closeContainer() {}
-
-  /** @param {number} durationMs Activation duration time in ms. */
-  reportTabActivationDuration(durationMs) {}
-
-  /**
-   * @param {number} tabCount Number of tabs.
-   * @param {number} durationMs Activation duration time in ms.
-   */
-  reportTabDataReceivedDuration(tabCount, durationMs) {}
-
-  /**
-   * @param {number} tabCount Number of tabs.
-   * @param {number} durationMs Creation duration time in ms.
-   */
-  reportTabCreationDuration(tabCount, durationMs) {}
-
-  /** @return {!PageCallbackRouter} */
-  getCallbackRouter() {}
-}
-
-/** @implements {TabsApiProxy} */
-export class TabsApiProxyImpl {
-  constructor() {
-    /** @type {!PageCallbackRouter} */
-    this.callbackRouter = new PageCallbackRouter();
-
-    /** @type {!PageHandlerRemote} */
-    this.handler = new PageHandlerRemote();
-
-    const factory = PageHandlerFactory.getRemote();
-    factory.createPageHandler(
-        this.callbackRouter.$.bindNewPipeAndPassRemote(),
-        this.handler.$.bindNewPipeAndPassReceiver());
-  }
-
-  /** @override */
-  activateTab(tabId) {
-    return new Promise(resolve => {
-      chrome.tabs.update(tabId, {active: true}, resolve);
-    });
-  }
-
-  /** @override */
-  getGroupVisualData() {
-    return this.handler.getGroupVisualData();
-  }
-
-  /** @override */
-  getTabs() {
-    return this.handler.getTabs();
-  }
-
-  /** @override */
-  closeTab(tabId, closeTabAction) {
-    this.handler.closeTab(
-        tabId, closeTabAction === CloseTabAction.SWIPED_TO_CLOSE);
-    chrome.metricsPrivate.recordEnumerationValue(
-        'WebUITabStrip.CloseTabAction', closeTabAction,
-        Object.keys(CloseTabAction).length);
-  }
-
-  /** @override */
-  groupTab(tabId, groupId) {
-    this.handler.groupTab(tabId, groupId);
-  }
-
-  /** @override */
-  moveGroup(groupId, newIndex) {
-    this.handler.moveGroup(groupId, newIndex);
-  }
-
-  /** @override */
-  moveTab(tabId, newIndex) {
-    this.handler.moveTab(tabId, newIndex);
-  }
-
-  /** @override */
-  setThumbnailTracked(tabId, thumbnailTracked) {
-    this.handler.setThumbnailTracked(tabId, thumbnailTracked);
-  }
-
-  /** @override */
-  ungroupTab(tabId) {
-    this.handler.ungroupTab(tabId);
-  }
-
-  /** @override */
-  isVisible() {
-    // TODO(crbug.com/1234500): Move this call out of tabs_api_proxy
-    // since it's not related to tabs API.
-    return document.visibilityState === 'visible';
-  }
-
-  /** @override */
-  getColors() {
-    return this.handler.getThemeColors();
-  }
-
-  /** @override */
-  getLayout() {
-    return this.handler.getLayout();
-  }
-
-  /** @override */
-  observeThemeChanges() {
-    // TODO(crbug.com/1234500): Migrate to mojo as well.
-    chrome.send('observeThemeChanges');
-  }
-
-  /** @override */
-  showEditDialogForGroup(groupId, locationX, locationY, width, height) {
-    this.handler.showEditDialogForGroup(
-        groupId, locationX, locationY, width, height);
-  }
-
-  /** @override */
-  showTabContextMenu(tabId, locationX, locationY) {
-    this.handler.showTabContextMenu(tabId, locationX, locationY);
-  }
-
-  /** @override */
-  showBackgroundContextMenu(locationX, locationY) {
-    this.handler.showBackgroundContextMenu(locationX, locationY);
-  }
-
-  /** @override */
-  closeContainer() {
-    this.handler.closeContainer();
-  }
-
-  /** @override */
-  reportTabActivationDuration(durationMs) {
-    this.handler.reportTabActivationDuration(durationMs);
-  }
-
-  /** @override */
-  reportTabDataReceivedDuration(tabCount, durationMs) {
-    this.handler.reportTabDataReceivedDuration(tabCount, durationMs);
-  }
-
-  /** @override */
-  reportTabCreationDuration(tabCount, durationMs) {
-    this.handler.reportTabCreationDuration(tabCount, durationMs);
-  }
-
-  /** @override */
-  getCallbackRouter() {
-    return this.callbackRouter;
-  }
-}
-
-addSingletonGetter(TabsApiProxyImpl);
diff --git a/chrome/browser/resources/tab_strip/tabs_api_proxy.ts b/chrome/browser/resources/tab_strip/tabs_api_proxy.ts
new file mode 100644
index 0000000..aead1f8
--- /dev/null
+++ b/chrome/browser/resources/tab_strip/tabs_api_proxy.ts
@@ -0,0 +1,196 @@
+// 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 {PageCallbackRouter, PageHandlerFactory, PageHandlerRemote, Tab, TabGroupVisualData} from './tab_strip.mojom-webui.js';
+
+/**
+ * These values are persisted to logs and should not be renumbered or re-used.
+ * See tools/metrics/histograms/enums.xml.
+ */
+export enum CloseTabAction {
+  CLOSE_BUTTON = 0,
+  SWIPED_TO_CLOSE = 1,
+}
+
+export interface TabsApiProxy {
+  activateTab(tabId: number): Promise<chrome.tabs.Tab>;
+
+  /**
+   * @return Object of group IDs as strings mapped to their visual data.
+   */
+  getGroupVisualData(): Promise<{data: {[id: string]: TabGroupVisualData}}>;
+
+  getTabs(): Promise<{tabs: Tab[]}>;
+
+  closeTab(tabId: number, closeTabAction: CloseTabAction): void;
+
+  groupTab(tabId: number, groupId: string): void;
+
+  moveGroup(groupId: string, newIndex: number): void;
+
+  moveTab(tabId: number, newIndex: number): void;
+
+  setThumbnailTracked(tabId: number, thumbnailTracked: boolean): void;
+
+  ungroupTab(tabId: number): void;
+
+  isVisible(): boolean;
+
+  /**
+   * @return Object with CSS variables as keys and rgba strings as values
+   */
+  getColors(): Promise<{colors: {[key: string]: string}}>;
+
+  /**
+   * @return Object with CSS variables as keys and pixel lengths as values
+   */
+  getLayout(): Promise<{layout: {[key: string]: string}}>;
+
+  observeThemeChanges(): void;
+
+  showEditDialogForGroup(
+      groupId: string, locationX: number, locationY: number, width: number,
+      height: number): void;
+
+  showTabContextMenu(tabId: number, locationX: number, locationY: number): void;
+
+  showBackgroundContextMenu(locationX: number, locationY: number): void;
+
+  closeContainer(): void;
+
+  /** @param durationMs Activation duration time in ms. */
+  reportTabActivationDuration(durationMs: number): void;
+
+  /**
+   * @param tabCount Number of tabs.
+   * @param durationMs Activation duration time in ms.
+   */
+  reportTabDataReceivedDuration(tabCount: number, durationMs: number): void;
+
+  /**
+   * @param tabCount Number of tabs.
+   * @param durationMs Creation duration time in ms.
+   */
+  reportTabCreationDuration(tabCount: number, durationMs: number): void;
+
+  getCallbackRouter(): PageCallbackRouter;
+}
+
+export class TabsApiProxyImpl implements TabsApiProxy {
+  callbackRouter: PageCallbackRouter = new PageCallbackRouter();
+  handler: PageHandlerRemote = new PageHandlerRemote();
+
+  constructor() {
+    const factory = PageHandlerFactory.getRemote();
+    factory.createPageHandler(
+        this.callbackRouter.$.bindNewPipeAndPassRemote(),
+        this.handler.$.bindNewPipeAndPassReceiver());
+  }
+
+  activateTab(tabId: number) {
+    return new Promise<chrome.tabs.Tab>(resolve => {
+      chrome.tabs.update(tabId, {active: true}, tab => resolve(tab!));
+    });
+  }
+
+  getGroupVisualData() {
+    return this.handler.getGroupVisualData();
+  }
+
+  getTabs() {
+    return this.handler.getTabs();
+  }
+
+  closeTab(tabId: number, closeTabAction: CloseTabAction) {
+    this.handler.closeTab(
+        tabId, closeTabAction === CloseTabAction.SWIPED_TO_CLOSE);
+    chrome.metricsPrivate.recordEnumerationValue(
+        'WebUITabStrip.CloseTabAction', closeTabAction,
+        Object.keys(CloseTabAction).length);
+  }
+
+  groupTab(tabId: number, groupId: string) {
+    this.handler.groupTab(tabId, groupId);
+  }
+
+  moveGroup(groupId: string, newIndex: number) {
+    this.handler.moveGroup(groupId, newIndex);
+  }
+
+  moveTab(tabId: number, newIndex: number) {
+    this.handler.moveTab(tabId, newIndex);
+  }
+
+  setThumbnailTracked(tabId: number, thumbnailTracked: boolean) {
+    this.handler.setThumbnailTracked(tabId, thumbnailTracked);
+  }
+
+  ungroupTab(tabId: number) {
+    this.handler.ungroupTab(tabId);
+  }
+
+  isVisible() {
+    // TODO(crbug.com/1234500): Move this call out of tabs_api_proxy
+    // since it's not related to tabs API.
+    return document.visibilityState === 'visible';
+  }
+
+  getColors() {
+    return this.handler.getThemeColors();
+  }
+
+  getLayout() {
+    return this.handler.getLayout();
+  }
+
+  observeThemeChanges() {
+    // TODO(crbug.com/1234500): Migrate to mojo as well.
+    chrome.send('observeThemeChanges');
+  }
+
+  showEditDialogForGroup(
+      groupId: string, locationX: number, locationY: number, width: number,
+      height: number) {
+    this.handler.showEditDialogForGroup(
+        groupId, locationX, locationY, width, height);
+  }
+
+  showTabContextMenu(tabId: number, locationX: number, locationY: number) {
+    this.handler.showTabContextMenu(tabId, locationX, locationY);
+  }
+
+  showBackgroundContextMenu(locationX: number, locationY: number) {
+    this.handler.showBackgroundContextMenu(locationX, locationY);
+  }
+
+  closeContainer() {
+    this.handler.closeContainer();
+  }
+
+  reportTabActivationDuration(durationMs: number) {
+    this.handler.reportTabActivationDuration(durationMs);
+  }
+
+  reportTabDataReceivedDuration(tabCount: number, durationMs: number) {
+    this.handler.reportTabDataReceivedDuration(tabCount, durationMs);
+  }
+
+  reportTabCreationDuration(tabCount: number, durationMs: number) {
+    this.handler.reportTabCreationDuration(tabCount, durationMs);
+  }
+
+  getCallbackRouter() {
+    return this.callbackRouter;
+  }
+
+  static getInstance(): TabsApiProxy {
+    return instance || (instance = new TabsApiProxyImpl());
+  }
+
+  static setInstance(obj: TabsApiProxy) {
+    instance = obj;
+  }
+}
+
+let instance: TabsApiProxy|null = null;
diff --git a/chrome/browser/resources/whats_new/BUILD.gn b/chrome/browser/resources/whats_new/BUILD.gn
index 6e6260d..fc689c3b 100644
--- a/chrome/browser/resources/whats_new/BUILD.gn
+++ b/chrome/browser/resources/whats_new/BUILD.gn
@@ -37,10 +37,7 @@
 }
 
 html_to_js("web_components") {
-  js_files = [
-    "whats_new_app.ts",
-    "whats_new_error_page.ts",
-  ]
+  js_files = [ "whats_new_app.ts" ]
 }
 
 copy("copy_proxy") {
@@ -54,7 +51,6 @@
   tsconfig_base = "tsconfig_base.json"
   in_files = [
     "whats_new_app.ts",
-    "whats_new_error_page.ts",
     "whats_new_proxy.ts",
   ]
   deps = [
diff --git a/chrome/browser/resources/whats_new/whats_new_app.html b/chrome/browser/resources/whats_new/whats_new_app.html
index cf5aa33..6be42ef 100644
--- a/chrome/browser/resources/whats_new/whats_new_app.html
+++ b/chrome/browser/resources/whats_new/whats_new_app.html
@@ -5,7 +5,6 @@
     width: 100%;
   }
 </style>
-<template is="dom-if" if="[[showErrorPage_]]">
-  <whats-new-error-page></whats-new-error-page>
+<template is="dom-if" if="[[url_]]">
+  <iframe id="content" src="[[url_]]"></iframe>
 </template>
-<iframe id="content" hidden$="[[!canHandleMessages_]]" src="[[url_]]"></iframe>
diff --git a/chrome/browser/resources/whats_new/whats_new_app.ts b/chrome/browser/resources/whats_new/whats_new_app.ts
index 740d342..3383faa 100644
--- a/chrome/browser/resources/whats_new/whats_new_app.ts
+++ b/chrome/browser/resources/whats_new/whats_new_app.ts
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/cr_elements/hidden_style_css.m.js';
-import './whats_new_error_page.js';
 import './strings.m.js';
 
 import {ClickInfo, Command} from 'chrome://resources/js/browser_command/browser_command.mojom-webui.js';
@@ -11,7 +10,6 @@
 import {isChromeOS} from 'chrome://resources/js/cr.m.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js';
 import {html, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {WhatsNewProxyImpl} from './whats_new_proxy.js';
@@ -27,31 +25,13 @@
   data: CommandData,
 };
 
-const WhatsNewAppElementBase = WebUIListenerMixin(PolymerElement);
-
-export class WhatsNewAppElement extends WhatsNewAppElementBase {
+export class WhatsNewAppElement extends PolymerElement {
   static get is() {
     return 'whats-new-app';
   }
 
   static get properties() {
     return {
-      showErrorPage_: {
-        type: Boolean,
-        value: false,
-      },
-
-      showFeedbackButton_: {
-        type: Boolean,
-        value: () => loadTimeData.getBoolean('showFeedbackButton'),
-      },
-
-      // Whether the page should show the iframe and handle messages from it.
-      canHandleMessages_: {
-        type: Boolean,
-        value: false,
-      },
-
       url_: {
         type: String,
         value: '',
@@ -59,9 +39,6 @@
     };
   }
 
-  private canHandleMessages_: boolean;
-  private showErrorPage_: boolean;
-  private showFeedbackButton_: boolean;
   private url_: string;
 
   private isAutoOpen_: boolean = false;
@@ -70,13 +47,10 @@
   connectedCallback() {
     super.connectedCallback();
 
-    this.addWebUIListener(
-        'preload-url', (url: string) => this.handleUrlResult_(url, false));
     const queryParams = new URLSearchParams(window.location.search);
-    this.isAutoOpen_ = queryParams.has('auto') && !isChromeOS;
-    WhatsNewProxyImpl.getInstance()
-        .initialize(this.isAutoOpen_)
-        .then(url => this.handleUrlResult_(url, true));
+    this.isAutoOpen_ = queryParams.has('auto');
+    WhatsNewProxyImpl.getInstance().initialize().then(
+        url => this.handleUrlResult_(url));
   }
 
   disconnectedCallback() {
@@ -85,36 +59,28 @@
   }
 
   /**
-   * Handles the URL result of sending the initialize WebUI message. An initial
-   * URL will be sent back via the preload-url event, and the final URL is
-   * sent when the callback resolves.
+   * Handles the URL result of sending the initialize WebUI message.
    * @param url The What's New URL to use in the iframe.
-   * @param canHandleMessages Whether the page should begin handling messages
-   *     from the iframe. True only if |url| is the final URL to load.
    */
-  private handleUrlResult_(url: string|null, canHandleMessages: boolean) {
+  private handleUrlResult_(url: string|null) {
     if (!url) {
-      this.url_ = '';
-      this.showErrorPage_ = true;
+      // This occurs in the special case of tests where we don't want to load
+      // remote content.
       return;
     }
 
-    const latest = this.isAutoOpen_ ? 'true' : 'false';
-    const feedback = this.showFeedbackButton_ ? 'true' : 'false';
+    const latest = this.isAutoOpen_ && !isChromeOS ? 'true' : 'false';
+    const feedback =
+        loadTimeData.getBoolean('showFeedbackButton') ? 'true' : 'false';
     url += url.includes('?') ? '&' : '?';
     this.url_ = url.concat(`latest=${latest}&feedback=${feedback}`);
 
-    this.canHandleMessages_ = canHandleMessages;
-
-    if (canHandleMessages) {
-      this.eventTracker_.add(
-          window, 'message',
-          event => this.handleMessage_(event as MessageEvent));
-    }
+    this.eventTracker_.add(
+        window, 'message', event => this.handleMessage_(event as MessageEvent));
   }
 
   private handleMessage_(event: MessageEvent) {
-    if (!this.canHandleMessages_) {
+    if (!this.url_) {
       return;
     }
 
@@ -125,6 +91,9 @@
     }
 
     const commandData = (data as BrowserCommandMessageData).data;
+    if (!commandData) {
+      return;
+    }
 
     const commandId = Object.values(Command).includes(commandData.commandId) ?
         commandData.commandId :
diff --git a/chrome/browser/resources/whats_new/whats_new_error_page.html b/chrome/browser/resources/whats_new/whats_new_error_page.html
deleted file mode 100644
index d0e9858..0000000
--- a/chrome/browser/resources/whats_new/whats_new_error_page.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<style include="cr-shared-style">
-  :host {
-    align-items: center;
-    display: flex;
-    flex-direction: column;
-  }
-
-  h1 {
-    font-size: 24px;
-    font-weight: 500;
-    line-height: 16px;
-    margin: 0 0 20px;
-  }
-
-  h2 {
-    font-size: 16px;
-    font-weight: 400;
-    line-height: 16px;
-    margin: 0;
-  }
-
-  #crashedIcon {
-    -webkit-mask:
-      url(chrome://theme/IDR_ERROR_NETWORK_GENERIC)
-      center/contain no-repeat;
-    background-color: currentColor;
-    height: 100%;
-    width: 100%;
-  }
-
-  #faviconContainer {
-    height: 72px;
-    margin-bottom: 50px;
-    margin-top: 50px;
-    width: 72px;
-  }
-
-  #wrapper {
-    align-items: flex-start;
-    display: flex;
-    flex-direction: column;
-  }
-
-  cr-button {
-    margin-top: 18px;
-  }
-</style>
-<div id="wrapper">
-  <div id="faviconContainer" aria-hidden="true">
-    <div id="crashedIcon"></div>
-  </div>
-  <h1>$i18n{pageCantBeReached}</h1>
-  <h2>$i18n{reloadOrTryAgain}</h2>
-  <cr-button class="action-button">$i18n{reloadButton}</cr-button>
-</div>
diff --git a/chrome/browser/resources/whats_new/whats_new_error_page.ts b/chrome/browser/resources/whats_new/whats_new_error_page.ts
deleted file mode 100644
index 13421f8..0000000
--- a/chrome/browser/resources/whats_new/whats_new_error_page.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import './strings.m.js';
-
-import 'chrome://resources/cr_elements/shared_style_css.m.js';
-import 'chrome://resources/cr_elements/shared_vars_css.m.js';
-import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-export class WhatsNewErrorPageElement extends PolymerElement {
-  static get is() {
-    return 'whats-new-error-page';
-  }
-
-  static get template() {
-    return html`{__html_template__}`;
-  }
-}
-customElements.define(WhatsNewErrorPageElement.is, WhatsNewErrorPageElement);
diff --git a/chrome/browser/resources/whats_new/whats_new_proxy.ts b/chrome/browser/resources/whats_new/whats_new_proxy.ts
index 1e245f3a5..612e87c2 100644
--- a/chrome/browser/resources/whats_new/whats_new_proxy.ts
+++ b/chrome/browser/resources/whats_new/whats_new_proxy.ts
@@ -5,12 +5,12 @@
 import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
 
 export interface WhatsNewProxy {
-  initialize(isAutoOpen: boolean): Promise<string>;
+  initialize(): Promise<string>;
 }
 
 export class WhatsNewProxyImpl implements WhatsNewProxy {
-  initialize(isAutoOpen: boolean): Promise<string> {
-    return sendWithPromise('initialize', isAutoOpen);
+  initialize(): Promise<string> {
+    return sendWithPromise('initialize');
   }
 
   static getInstance(): WhatsNewProxy {
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index e518222..368de41 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -367,6 +367,8 @@
         sources += [
           "android/services_delegate_android.cc",
           "android/services_delegate_android.h",
+          "tailored_security/consented_message_android.cc",
+          "tailored_security/consented_message_android.h",
           "tailored_security/unconsented_message_android.cc",
           "tailored_security/unconsented_message_android.h",
           "telemetry/android/android_telemetry_service.cc",
diff --git a/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc b/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc
new file mode 100644
index 0000000..85173a0
--- /dev/null
+++ b/chrome/browser/safe_browsing/tailored_security/consented_message_android.cc
@@ -0,0 +1,80 @@
+// 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/safe_browsing/tailored_security/consented_message_android.h"
+
+#include "chrome/browser/android/android_theme_resources.h"
+#include "chrome/browser/android/resource_mapper.h"
+#include "chrome/browser/safe_browsing/android/safe_browsing_settings_launcher_android.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/messages/android/message_dispatcher_bridge.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#include "base/logging.h"
+#include "content/public/browser/web_contents.h"
+
+namespace safe_browsing {
+
+TailoredSecurityConsentedModalAndroid::TailoredSecurityConsentedModalAndroid() =
+    default;
+
+TailoredSecurityConsentedModalAndroid::
+    ~TailoredSecurityConsentedModalAndroid() {
+  DismissMessage(messages::DismissReason::UNKNOWN);
+}
+
+void TailoredSecurityConsentedModalAndroid::DisplayMessage(
+    content::WebContents* web_contents) {
+  if (message_) {
+    return;
+  }
+  web_contents_ = web_contents;
+  message_ = std::make_unique<messages::MessageWrapper>(
+      messages::MessageIdentifier::TAILORED_SECURITY_ENABLED,
+      base::NullCallback(),
+      base::BindOnce(
+          &TailoredSecurityConsentedModalAndroid::HandleMessageDismissed,
+          base::Unretained(this)));
+  message_->SetTitle(
+      l10n_util::GetStringUTF16(IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_TITLE));
+  message_->SetDescription(l10n_util::GetStringUTF16(
+      IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_DESCRIPTION));
+  message_->SetPrimaryButtonText(l10n_util::GetStringUTF16(
+      IDS_TAILORED_SECURITY_CONSENTED_MESSAGE_OK_BUTTON));
+  message_->SetIconResourceId(
+      ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_MESSAGE_SAFETY_CHECK));
+  message_->SetSecondaryIconResourceId(
+      ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_MESSAGE_SETTINGS));
+  message_->SetSecondaryActionCallback(base::BindOnce(
+      &TailoredSecurityConsentedModalAndroid::HandleSettingsClicked,
+      base::Unretained(this)));
+
+  messages::MessageDispatcherBridge::Get()->EnqueueWindowScopedMessage(
+      message_.get(), web_contents_->GetTopLevelNativeWindow(),
+      messages::MessagePriority::kNormal);
+}
+
+void TailoredSecurityConsentedModalAndroid::DismissMessage(
+    messages::DismissReason dismiss_reason) {
+  if (message_) {
+    messages::MessageDispatcherBridge::Get()->DismissMessage(message_.get(),
+                                                             dismiss_reason);
+  }
+}
+
+void TailoredSecurityConsentedModalAndroid::HandleSettingsClicked() {
+  // TODO(crbug.com/1257628): Update pref about user action.
+  // TODO(crbug.com/1257621): Add histogram to calculate conversion rate.
+  ShowSafeBrowsingSettings(web_contents_);
+  DismissMessage(messages::DismissReason::DISMISSED_BY_FEATURE);
+}
+
+void TailoredSecurityConsentedModalAndroid::HandleMessageDismissed(
+    messages::DismissReason dismiss_reason) {
+  // TODO(crbug.com/1257628): Update pref about user action.
+  message_.reset();
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/tailored_security/consented_message_android.h b/chrome/browser/safe_browsing/tailored_security/consented_message_android.h
new file mode 100644
index 0000000..c1e10ca
--- /dev/null
+++ b/chrome/browser/safe_browsing/tailored_security/consented_message_android.h
@@ -0,0 +1,37 @@
+// 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_SAFE_BROWSING_TAILORED_SECURITY_CONSENTED_MESSAGE_ANDROID_H_
+#define CHROME_BROWSER_SAFE_BROWSING_TAILORED_SECURITY_CONSENTED_MESSAGE_ANDROID_H_
+
+#include <memory>
+
+#include "components/messages/android/message_enums.h"
+#include "components/messages/android/message_wrapper.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace safe_browsing {
+
+class TailoredSecurityConsentedModalAndroid {
+ public:
+  TailoredSecurityConsentedModalAndroid();
+  ~TailoredSecurityConsentedModalAndroid();
+
+  void DisplayMessage(content::WebContents* web_contents);
+  void DismissMessage(messages::DismissReason dismiss_reason);
+
+ private:
+  void HandleSettingsClicked();
+  void HandleMessageDismissed(messages::DismissReason dismiss_reason);
+
+  std::unique_ptr<messages::MessageWrapper> message_;
+  content::WebContents* web_contents_ = nullptr;
+};
+
+}  // namespace safe_browsing
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_TAILORED_SECURITY_CONSENTED_MESSAGE_ANDROID_H_
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index e16dc6d..33945d7d 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -57,6 +57,7 @@
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/tab_group.h"
 #include "chrome/browser/ui/tabs/tab_group_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -1048,7 +1049,8 @@
   if (HasSingleNewTabPage(browser))
     tab_to_clobber = browser->tab_strip_model()->GetActiveWebContents();
 
-  StartupBrowserCreator::OpenStartupPages(browser, true);
+  StartupBrowserCreator::OpenStartupPages(
+      browser, chrome::startup::IsProcessStartup::kYes);
   if (tab_to_clobber && browser->tab_strip_model()->count() > 1)
     chrome::CloseWebContents(browser, tab_to_clobber, true);
 }
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 57a517c..763904a 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -2144,8 +2144,8 @@
   Profile* second_profile = CreateSecondaryProfile(1);
   base::FilePath second_profile_path = second_profile->GetPath();
   profiles::FindOrCreateNewWindowForProfile(
-      second_profile, chrome::startup::IS_NOT_PROCESS_STARTUP,
-      chrome::startup::IS_NOT_FIRST_RUN, false);
+      second_profile, chrome::startup::IsProcessStartup::kNo,
+      chrome::startup::IsFirstRun::kNo, false);
   Browser* second_profile_browser_one = ui_test_utils::WaitForBrowserToOpen();
   chrome::NewWindow(second_profile_browser_one);
   Browser* second_profile_browser_two =
diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc
index 5e9ad2d..39e1418 100644
--- a/chrome/browser/sessions/session_service.cc
+++ b/chrome/browser/sessions/session_service.cc
@@ -506,8 +506,8 @@
       StartupBrowserCreator browser_creator;
       browser_creator.LaunchBrowser(*base::CommandLine::ForCurrentProcess(),
                                     profile(), base::FilePath(),
-                                    chrome::startup::IS_PROCESS_STARTUP,
-                                    chrome::startup::IS_NOT_FIRST_RUN,
+                                    chrome::startup::IsProcessStartup::kYes,
+                                    chrome::startup::IsFirstRun::kNo,
                                     std::make_unique<LaunchModeRecorder>());
       return true;
     } else {
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java
index eb4e11d6..e28a45a 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java
@@ -173,7 +173,12 @@
         int firstPartyIndex = layout.indexOfChild(firstPartyRow);
         int thirdPartyIndex = layout.indexOfChild(thirdPartyRow);
 
-        assert thirdPartyIndex < firstPartyIndex;
+        if (thirdPartyIndex > firstPartyIndex) {
+            // If the rows are already swapped, we're updating an existing sheet;
+            // don't swap them again.
+            return;
+        }
+
         layout.removeViewAt(firstPartyIndex);
         layout.removeViewAt(thirdPartyIndex);
         layout.addView(firstPartyRow, thirdPartyIndex);
diff --git a/chrome/browser/speech/tts_chromeos.cc b/chrome/browser/speech/tts_chromeos.cc
index 055c9bc..bb04b106 100644
--- a/chrome/browser/speech/tts_chromeos.cc
+++ b/chrome/browser/speech/tts_chromeos.cc
@@ -7,10 +7,10 @@
 #include <algorithm>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/arc/mojom/tts.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/tts_platform.h"
 
diff --git a/chrome/browser/ssl/chrome_security_blocking_page_factory.cc b/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
index d02c0c7..9954ef8e 100644
--- a/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
+++ b/chrome/browser/ssl/chrome_security_blocking_page_factory.cc
@@ -239,30 +239,6 @@
   return page;
 }
 
-std::unique_ptr<LegacyTLSBlockingPage>
-ChromeSecurityBlockingPageFactory::CreateLegacyTLSBlockingPage(
-    content::WebContents* web_contents,
-    int cert_error,
-    const GURL& request_url,
-    std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    const net::SSLInfo& ssl_info) {
-  LogSafeBrowsingSecuritySensitiveAction(
-      safe_browsing::SafeBrowsingMetricsCollectorFactory::GetForProfile(
-          Profile::FromBrowserContext(web_contents->GetBrowserContext())));
-
-  auto page = std::make_unique<LegacyTLSBlockingPage>(
-      web_contents, cert_error, request_url, std::move(ssl_cert_reporter),
-      /*can_show_enhanced_protection_message=*/true, ssl_info,
-      std::make_unique<SSLErrorControllerClient>(
-          web_contents, ssl_info, cert_error, request_url,
-          CreateMetricsHelperAndStartRecording(web_contents, request_url,
-                                               "legacy_tls", false),
-          CreateSettingsPageHelper()));
-
-  DoChromeSpecificSetup(page.get());
-  return page;
-}
-
 std::unique_ptr<MITMSoftwareBlockingPage>
 ChromeSecurityBlockingPageFactory::CreateMITMSoftwareBlockingPage(
     content::WebContents* web_contents,
diff --git a/chrome/browser/ssl/chrome_security_blocking_page_factory.h b/chrome/browser/ssl/chrome_security_blocking_page_factory.h
index b76e74b..70c3c59 100644
--- a/chrome/browser/ssl/chrome_security_blocking_page_factory.h
+++ b/chrome/browser/ssl/chrome_security_blocking_page_factory.h
@@ -12,7 +12,6 @@
 #include "components/security_interstitials/content/captive_portal_blocking_page.h"
 #include "components/security_interstitials/content/https_only_mode_blocking_page.h"
 #include "components/security_interstitials/content/insecure_form_blocking_page.h"
-#include "components/security_interstitials/content/legacy_tls_blocking_page.h"
 #include "components/security_interstitials/content/mitm_software_blocking_page.h"
 #include "components/security_interstitials/content/security_blocking_page_factory.h"
 #include "components/security_interstitials/content/ssl_blocking_page.h"
@@ -53,12 +52,6 @@
       const base::Time& time_triggered,
       ssl_errors::ClockState clock_state,
       std::unique_ptr<SSLCertReporter> ssl_cert_reporter) override;
-  std::unique_ptr<LegacyTLSBlockingPage> CreateLegacyTLSBlockingPage(
-      content::WebContents* web_contents,
-      int cert_error,
-      const GURL& request_url,
-      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-      const net::SSLInfo& ssl_info) override;
   std::unique_ptr<MITMSoftwareBlockingPage> CreateMITMSoftwareBlockingPage(
       content::WebContents* web_contents,
       int cert_error,
diff --git a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
index da646c50..ecd8708 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
@@ -31,7 +31,6 @@
 #include "chrome/browser/reputation/reputation_web_contents_observer.h"
 #include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
 #include "chrome/browser/ssl/cert_verifier_browser_test.h"
-#include "chrome/browser/ssl/tls_deprecation_test_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -1365,48 +1364,6 @@
             observer.latest_security_level());
 }
 
-// Tests that legacy TLS pages show the correct security descriptions.
-class BrowserTestNonsecureURLRequestWithLegacyTLSWarnings
-    : public InProcessBrowserTest {
- public:
-  BrowserTestNonsecureURLRequestWithLegacyTLSWarnings() {}
-
-  BrowserTestNonsecureURLRequestWithLegacyTLSWarnings(
-      const BrowserTestNonsecureURLRequestWithLegacyTLSWarnings&) = delete;
-  BrowserTestNonsecureURLRequestWithLegacyTLSWarnings& operator=(
-      const BrowserTestNonsecureURLRequestWithLegacyTLSWarnings&) = delete;
-
-  void SetUpOnMainThread() override {
-    net::SSLServerConfig config;
-    config.version_max = net::SSL_PROTOCOL_VERSION_TLS1_1;
-    config.version_min = net::SSL_PROTOCOL_VERSION_TLS1_1;
-    https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_OK, config);
-    ASSERT_TRUE(https_server()->Start());
-  }
-
- protected:
-  net::EmbeddedTestServer* https_server() { return &https_server_; }
-
- private:
-  net::EmbeddedTestServer https_server_{
-      net::test_server::EmbeddedTestServer::TYPE_HTTPS};
-};
-
-// Tests that a connection with legacy TLS versions (TLS 1.0/1.1) gets
-// downgraded to SecurityLevel WARNING and |connection_used_legacy_tls| is set.
-IN_PROC_BROWSER_TEST_F(BrowserTestNonsecureURLRequestWithLegacyTLSWarnings,
-                       LegacyTLSDowngradesSecurityLevel) {
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  auto* helper = SecurityStateTabHelper::FromWebContents(tab);
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/ssl/google.html")));
-  WaitForInterstitial(tab);
-  ProceedThroughInterstitial(tab);
-
-  EXPECT_EQ(security_state::DANGEROUS, helper->GetSecurityLevel());
-}
-
 // Tests that the Not Secure chip does not show for error pages on http:// URLs.
 // Regression test for https://crbug.com/760647.
 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperIncognitoTest, HttpErrorPage) {
diff --git a/chrome/browser/ssl/security_state_tab_helper_unittest.cc b/chrome/browser/ssl/security_state_tab_helper_unittest.cc
index 8a6046c..037b1ef 100644
--- a/chrome/browser/ssl/security_state_tab_helper_unittest.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/command_line.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "chrome/browser/ssl/tls_deprecation_test_utils.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/test/mock_navigation_handle.h"
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index a471466..b1aaab35 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -56,7 +56,6 @@
 #include "chrome/browser/ssl/security_state_tab_helper.h"
 #include "chrome/browser/ssl/ssl_browsertest_util.h"
 #include "chrome/browser/ssl/ssl_error_controller_client.h"
-#include "chrome/browser/ssl/tls_deprecation_test_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -7409,330 +7408,6 @@
   TestNoMITMSoftwareInterstitial();
 }
 
-class TLSLegacyVersionSSLUITest : public SSLUITest {
- public:
-  TLSLegacyVersionSSLUITest() = default;
-
-  TLSLegacyVersionSSLUITest(const TLSLegacyVersionSSLUITest&) = delete;
-  TLSLegacyVersionSSLUITest& operator=(const TLSLegacyVersionSSLUITest&) =
-      delete;
-
-  ~TLSLegacyVersionSSLUITest() override = default;
-
-  void SetUpOnMainThread() override {
-    SSLUITest::SetUpOnMainThread();
-    mock_cert_verifier()->set_default_result(net::OK);
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    mock_cert_verifier_.SetUpCommandLine(command_line);
-  }
-
-  void SetUpInProcessBrowserTestFixture() override {
-    mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
-  }
-
-  void TearDownInProcessBrowserTestFixture() override {
-    mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
-  }
-
-  content::ContentMockCertVerifier::CertVerifier* mock_cert_verifier() {
-    return mock_cert_verifier_.mock_cert_verifier();
-  }
-
- protected:
-  net::EmbeddedTestServer* https_server() { return &https_server_; }
-
-  void SetTLSVersion(uint16_t version) {
-    net::SSLServerConfig config;
-    config.version_max = version;
-    config.version_min = version;
-    https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_OK, config);
-  }
-
- private:
-  content::ContentMockCertVerifier mock_cert_verifier_;
-};
-
-// TLS 1.2 should not trigger a warning.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, NoWarningTLS12) {
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1_2);
-  ASSERT_TRUE(https_server()->Start());
-
-  GURL url(https_server()->GetURL("/ssl/google.html"));
-  content::WebContentsConsoleObserver console_observer(
-      browser()->tab_strip_model()->GetActiveWebContents());
-  console_observer.SetPattern(base::StringPrintf(
-      "*The connection used to load resources from https://%s:%s*",
-      url.host().c_str(), url.port().c_str()));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-  EXPECT_EQ(0u, console_observer.messages().size());
-}
-
-// TLS 1.1 should trigger a warning.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, WarningTLS11) {
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1_1);
-  ASSERT_TRUE(https_server()->Start());
-
-  GURL url(https_server()->GetURL("/ssl/google.html"));
-  content::WebContentsConsoleObserver console_observer(
-      browser()->tab_strip_model()->GetActiveWebContents());
-  console_observer.SetPattern(base::StringPrintf(
-      "*The connection used to load resources from https://%s:%s*",
-      url.host().c_str(), url.port().c_str()));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-
-  // Click through the interstitial (the console warning is only shown on the
-  // affected page, not the interstitial).
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab);
-  ProceedThroughInterstitial(tab);
-
-  console_observer.Wait();
-  EXPECT_TRUE(base::MatchPattern(console_observer.GetMessageAt(0u),
-                                 "*will be disabled in the future*"));
-  EXPECT_TRUE(base::MatchPattern(console_observer.GetMessageAt(0u),
-                                 "*should enable TLS 1.2 or later*"));
-}
-
-// TLS 1.0 should trigger a warning.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, WarningTLS1) {
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1);
-  ASSERT_TRUE(https_server()->Start());
-
-  GURL url(https_server()->GetURL("/ssl/google.html"));
-  content::WebContentsConsoleObserver console_observer(
-      browser()->tab_strip_model()->GetActiveWebContents());
-  console_observer.SetPattern(base::StringPrintf(
-      "*The connection used to load resources from https://%s:%s*",
-      url.host().c_str(), url.port().c_str()));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-
-  // Click through the interstitial (the console warning is only shown on the
-  // affected page, not the interstitial).
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab);
-  ProceedThroughInterstitial(tab);
-
-  console_observer.Wait();
-  EXPECT_TRUE(base::MatchPattern(console_observer.GetMessageAt(0u),
-                                 "*will be disabled in the future*"));
-  EXPECT_TRUE(base::MatchPattern(console_observer.GetMessageAt(0u),
-                                 "*should enable TLS 1.2 or later*"));
-}
-
-// Visiting a legacy TLS page should show the legacy TLS specific interstitial.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, ShowsInterstitial) {
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1);
-  ASSERT_TRUE(https_server()->Start());
-  base::HistogramTester histograms;
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/ssl/google.html")));
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab);
-  ASSERT_TRUE(
-      chrome_browser_interstitials::IsShowingLegacyTLSInterstitial(tab));
-
-  // Check that the histogram for the legacy TLS interstitial was recorded.
-  histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
-  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
-                               SSLErrorHandler::HANDLE_ALL, 1);
-  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
-                               SSLErrorHandler::SHOW_LEGACY_TLS_INTERSTITIAL,
-                               1);
-
-  // Click through the interstitial.
-  ProceedThroughInterstitial(tab);
-
-  // Navigating to the same page now shouldn't cause an interstitial.
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/ssl/google.html")));
-  tab = browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_FALSE(
-      chrome_browser_interstitials::IsShowingLegacyTLSInterstitial(tab));
-
-  // Check that no new interstitial metrics were recorded from this navigation.
-  histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
-  histograms.ExpectBucketCount("interstitial.legacy_tls.decision",
-                               security_interstitials::MetricsHelper::PROCEED,
-                               1);
-}
-
-// Test that attempting to set the SSLVersionMin enterprise policy to "tls1"
-// (which is no longer supported) does not prevent the legacy TLS interstitial
-// from being shown.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest,
-                       PolicyDoesNotOverrideInterstitial) {
-  // Attempt to set the SSLVersionMin policy.
-  base::Value policy_value("tls1");  // TLS 1.0
-  SetPolicy(policy::key::kSSLVersionMin, std::move(policy_value));
-
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1);
-  ASSERT_TRUE(https_server()->Start());
-
-  base::HistogramTester histograms;
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/ssl/google.html")));
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(
-      chrome_browser_interstitials::IsShowingLegacyTLSInterstitial(tab));
-}
-
-// Check that if we have bypassed the legacy TLS error previously and then the
-// server responded with TLS 1.2, we drop the error exception.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, FixedServerDropsBypass) {
-  GURL kSiteWithLegacyTLS("https://example.test/legacy-tls");
-  GURL kSiteWithModernTLS("https://example.test/modern-tls");
-
-  // EmbeddedTestServer can be flakey if forcing a specific port (as the port
-  // may no longer be available on the system). URLLoaderInterceptor can mock
-  // out the responses as needed instead, reusing the same port across variants.
-  auto url_loader_interceptor = std::make_unique<content::URLLoaderInterceptor>(
-      base::BindLambdaForTesting(
-          [=](content::URLLoaderInterceptor::RequestParams* params) {
-            network::URLLoaderCompletionStatus status;
-            status.ssl_info = net::SSLInfo();
-            status.ssl_info->cert = net::ImportCertFromFile(
-                net::GetTestCertsDirectory(), "ok_cert.pem");
-            status.ssl_info->unverified_cert = status.ssl_info->cert;
-
-            if (params->url_request.url == GURL(kSiteWithLegacyTLS)) {
-              status.error_code = net::ERR_SSL_OBSOLETE_VERSION;
-              status.ssl_info->cert_status = net::CERT_STATUS_LEGACY_TLS;
-              params->client->OnComplete(status);
-              return true;
-            }
-
-            status.error_code = net::OK;
-            std::string headers =
-                "HTTP/1.1 200 OK\nContent-Type: text/html; charset=utf-8\n";
-            std::string body = "<html><title>Success</title>Hello world</html>";
-            content::URLLoaderInterceptor::WriteResponse(headers, body,
-                                                         params->client.get());
-            return true;
-          }));
-
-  // Connect over TLS 1.0 and proceed through the interstitial to set an error
-  // bypass.
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kSiteWithLegacyTLS));
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab);
-  ProceedThroughInterstitial(tab);
-
-  // Connect over a "fixed" TLS 1.2 connection.
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kSiteWithModernTLS));
-  EXPECT_FALSE(
-      chrome_browser_interstitials::IsShowingLegacyTLSInterstitial(tab));
-
-  // Go back to connecting over TLS 1.0. Visiting should once again show the
-  // legacy TLS interstitial
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kSiteWithLegacyTLS));
-  WaitForInterstitial(tab);
-  EXPECT_TRUE(
-      chrome_browser_interstitials::IsShowingLegacyTLSInterstitial(tab));
-}
-
-// Check that cliking the "back to safety" button works for the legacy TLS
-// interstitial.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, BackToSafety) {
-  base::HistogramTester histograms;
-
-  // Connect over TLS 1.0 and don't proceed through the interstitial.
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1);
-  ASSERT_TRUE(https_server()->Start());
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/ssl/google.html")));
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab);
-  DontProceedThroughInterstitial(tab);
-  EXPECT_NE(tab->GetVisibleURL(), https_server()->GetURL("/ssl/google.html"));
-
-  // Check that the histogram for the legacy TLS interstitial was recorded.
-  histograms.ExpectBucketCount(
-      "interstitial.legacy_tls.decision",
-      security_interstitials::MetricsHelper::DONT_PROCEED, 1);
-}
-
-// A WebContentsObserver that allows the user to wait for a navigation, and
-// check whether the resource for the navigation was loaded from cache or not.
-class CacheNavigationObserver : public content::WebContentsObserver {
- public:
-  explicit CacheNavigationObserver(WebContents* web_contents,
-                                   bool expect_cached)
-      : WebContentsObserver(web_contents), expect_cached_(expect_cached) {}
-  ~CacheNavigationObserver() override = default;
-
-  void WaitForNavigation() { run_loop_.Run(); }
-
-  // WebContentsObserver:
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override {
-    ASSERT_EQ(expect_cached_, navigation_handle->WasResponseCached());
-    run_loop_.Quit();
-  }
-
- private:
-  bool expect_cached_;
-  base::RunLoop run_loop_;
-};
-
-// Tests that resources loaded over legacy TLS should not be cached.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, LegacyTLSPagesNotCached) {
-  // Connect over TLS 1.0 and proceed through the interstitial to set an error
-  // bypass.
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1);
-  ASSERT_TRUE(https_server()->Start());
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/cachetime")));
-  auto* tab1 = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab1);
-  ProceedThroughInterstitial(tab1);
-
-  // Open a new tab and navigate so that resources are fetched via the disk
-  // cache. Navigating to the same URL in the same tab triggers a refresh which
-  // will not check the disk cache.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), GURL("about:blank"), WindowOpenDisposition::NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
-          ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
-  auto* tab2 = browser()->tab_strip_model()->GetActiveWebContents();
-
-  CacheNavigationObserver observer(tab2, false);
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), https_server()->GetURL("/cachetime")));
-  observer.WaitForNavigation();  // Will fail if resource is loaded from cache.
-}
-
-// Tests that a page with legacy TLS and HSTS shows a bypassable interstitial
-// rather than a hard non-bypassable HSTS warning.
-IN_PROC_BROWSER_TEST_F(TLSLegacyVersionSSLUITest, LegacyTLSNotFatal) {
-  // Set HSTS for the test page.
-  ssl_test_util::SetHSTSForHostName(browser()->profile(), kHstsTestHostName);
-
-  // Connect over TLS 1.0 and proceed through the interstitial.
-  SetTLSVersion(net::SSL_PROTOCOL_VERSION_TLS1);
-  ASSERT_TRUE(https_server()->Start());
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(),
-      https_server()->GetURL(kHstsTestHostName, "/ssl/google.html")));
-  auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  WaitForInterstitial(tab);
-
-  // Verify that there is a proceed link in the interstitial.
-  int result = security_interstitials::CMD_ERROR;
-  const std::string javascript = base::StringPrintf(
-      "domAutomationController.send("
-      "(document.querySelector(\"#proceed-link\") === null) "
-      "? (%d) : (%d))",
-      security_interstitials::CMD_TEXT_NOT_FOUND,
-      security_interstitials::CMD_TEXT_FOUND);
-  ASSERT_TRUE(content::ExecuteScriptAndExtractInt(tab->GetMainFrame(),
-                                                  javascript, &result));
-  EXPECT_EQ(security_interstitials::CMD_TEXT_FOUND, result);
-}
-
 // Checks that SimpleURLLoader, which uses services/network/url_loader.cc, goes
 // through the new NetworkServiceClient interface to deliver cert error
 // notifications to the browser which then overrides the certificate error.
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref.cc b/chrome/browser/ssl/ssl_config_service_manager_pref.cc
index afff3bd..213860dc 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref.cc
@@ -290,9 +290,6 @@
   network::mojom::SSLVersion version_min;
   if (SSLProtocolVersionFromString(version_min_str, &version_min)) {
     config->version_min = version_min;
-    // If the ssl_version_min policy is set, we override the minimum warning
-    // version to that value, so that the policy also controls the interstitial.
-    config->version_min_warn = version_min;
   }
 
   network::mojom::SSLVersion version_max;
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
index a4ff279..9fe31111 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
@@ -211,9 +211,7 @@
       SetUpConfigServiceManager(&local_state);
 
   // The command-line option must not have been honored.
-  EXPECT_LE(network::mojom::SSLVersion::kTLS1, initial_config_->version_min);
-  EXPECT_LE(network::mojom::SSLVersion::kTLS12,
-            initial_config_->version_min_warn);
+  EXPECT_LE(network::mojom::SSLVersion::kTLS12, initial_config_->version_min);
 }
 
 // Tests that "tls1.1" is not treated as a valid minimum version.
@@ -229,9 +227,7 @@
       SetUpConfigServiceManager(&local_state);
 
   // The command-line option must not have been honored.
-  EXPECT_LE(network::mojom::SSLVersion::kTLS1, initial_config_->version_min);
-  EXPECT_LE(network::mojom::SSLVersion::kTLS12,
-            initial_config_->version_min_warn);
+  EXPECT_LE(network::mojom::SSLVersion::kTLS12, initial_config_->version_min);
 }
 
 // Tests that SSLVersionMin correctly sets the minimum version.
diff --git a/chrome/browser/ssl/tls_deprecation_test_utils.cc b/chrome/browser/ssl/tls_deprecation_test_utils.cc
deleted file mode 100644
index c53a4ec..0000000
--- a/chrome/browser/ssl/tls_deprecation_test_utils.cc
+++ /dev/null
@@ -1,48 +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 "chrome/browser/ssl/tls_deprecation_test_utils.h"
-
-#include "content/public/test/navigation_simulator.h"
-#include "net/cert/x509_certificate.h"
-#include "net/ssl/ssl_config.h"
-#include "net/ssl/ssl_connection_status_flags.h"
-#include "net/ssl/ssl_info.h"
-#include "net/test/cert_test_util.h"
-#include "net/test/test_data_directory.h"
-#include "url/gurl.h"
-
-std::unique_ptr<content::NavigationSimulator> CreateTLSNavigation(
-    const GURL& url,
-    content::WebContents* web_contents,
-    uint16_t ssl_protocol_version) {
-  auto navigation_simulator =
-      content::NavigationSimulator::CreateBrowserInitiated(url, web_contents);
-  navigation_simulator->Start();
-
-  // Setup the SSLInfo to specify the TLS version used.
-  auto cert =
-      net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
-  net::SSLInfo ssl_info = net::SSLInfo();
-  net::SSLConnectionStatusSetVersion(ssl_protocol_version,
-                                     &ssl_info.connection_status);
-  ssl_info.cert = cert;
-  navigation_simulator->SetSSLInfo(ssl_info);
-
-  return navigation_simulator;
-}
-
-std::unique_ptr<content::NavigationSimulator> CreateLegacyTLSNavigation(
-    const GURL& url,
-    content::WebContents* web_contents) {
-  return CreateTLSNavigation(url, web_contents,
-                             net::SSL_CONNECTION_VERSION_TLS1);
-}
-
-std::unique_ptr<content::NavigationSimulator> CreateNonlegacyTLSNavigation(
-    const GURL& url,
-    content::WebContents* web_contents) {
-  return CreateTLSNavigation(url, web_contents,
-                             net::SSL_CONNECTION_VERSION_TLS1_2);
-}
diff --git a/chrome/browser/ssl/tls_deprecation_test_utils.h b/chrome/browser/ssl/tls_deprecation_test_utils.h
deleted file mode 100644
index 7fbed48..0000000
--- a/chrome/browser/ssl/tls_deprecation_test_utils.h
+++ /dev/null
@@ -1,37 +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 CHROME_BROWSER_SSL_TLS_DEPRECATION_TEST_UTILS_H_
-#define CHROME_BROWSER_SSL_TLS_DEPRECATION_TEST_UTILS_H_
-
-#include <memory>
-
-namespace content {
-class NavigationSimulator;
-class WebContents;
-}  // namespace content
-
-class GURL;
-
-const char kLegacyTLSHost[] = "example-nonsecure.test";
-const char kLegacyTLSURL[] = "https://example-nonsecure.test";
-
-// Creates and starts a simulated navigation using the specified SSL protocol
-// version (e.g., net::SSL_CONNECTION_VERSION_TLS1_2).
-std::unique_ptr<content::NavigationSimulator> CreateTLSNavigation(
-    const GURL& url,
-    content::WebContents* web_contents,
-    uint16_t ssl_protocol_version);
-
-// Creates and starts a simulated navigation using TLS 1.0.
-std::unique_ptr<content::NavigationSimulator> CreateLegacyTLSNavigation(
-    const GURL& url,
-    content::WebContents* web_contents);
-
-// Creates and starts a simulated navigation using TLS 1.2.
-std::unique_ptr<content::NavigationSimulator> CreateNonlegacyTLSNavigation(
-    const GURL& url,
-    content::WebContents* web_contents);
-
-#endif  // CHROME_BROWSER_SSL_TLS_DEPRECATION_TEST_UTILS_H_
diff --git a/chrome/browser/sync/test/integration/sync_arc_package_helper.cc b/chrome/browser/sync/test/integration/sync_arc_package_helper.cc
index 92f17942..8991f483 100644
--- a/chrome/browser/sync/test/integration/sync_arc_package_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_arc_package_helper.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "base/command_line.h"
@@ -18,7 +19,6 @@
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/sync/protocol/arc_package_specifics.pb.h"
 #include "components/sync/protocol/entity_specifics.pb.h"
 
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index 2c8a65b..8900107 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -89,6 +89,7 @@
     "//components/strings:components_strings_grd",
     "//content/public/android:content_java",
     "//net/android:net_java",
+    "//third_party/android_deps:guava_android_java",
     "//third_party/android_deps:protobuf_lite_runtime_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_core_core_java",
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
index 21565b92..ed2493ea8 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
@@ -8,6 +8,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.google.common.primitives.UnsignedLongs;
 import com.google.protobuf.InvalidProtocolBufferException;
 
 import org.chromium.base.Callback;
@@ -618,14 +619,16 @@
             setPreviousPriceMicros(productUpdate.getOldPrice().getAmountMicros());
             setCurrencyCode(productUpdate.getOldPrice().getCurrencyCode());
             setLastUpdatedMs(System.currentTimeMillis());
-            setMainOfferId(String.valueOf(buyableProduct.getOfferId()));
+            // Use UnsignedLongs to convert OfferId to avoid overflow.
+            setMainOfferId(UnsignedLongs.toString(buyableProduct.getOfferId()));
             setPriceDropGurl(tab.getUrl());
             foundBuyableProduct = FoundBuyableProduct.FOUND_WITH_PRICE_UPDATE;
         } else if (hasPrice(priceTrackingData)) {
             setPriceMicros(buyableProduct.getCurrentPrice().getAmountMicros(), previousPricingData);
             setCurrencyCode(buyableProduct.getCurrentPrice().getCurrencyCode());
             setLastUpdatedMs(System.currentTimeMillis());
-            setMainOfferId(String.valueOf(buyableProduct.getOfferId()));
+            // Use UnsignedLongs to convert OfferId to avoid overflow.
+            setMainOfferId(UnsignedLongs.toString(buyableProduct.getOfferId()));
             setPriceDropGurl(tab.getUrl());
             foundBuyableProduct = FoundBuyableProduct.FOUND;
         }
diff --git a/chrome/browser/task_manager/providers/arc/arc_process_task.cc b/chrome/browser/task_manager/providers/arc/arc_process_task.cc
index 7d5fa3e..bfd0ed7 100644
--- a/chrome/browser/task_manager/providers/arc/arc_process_task.cc
+++ b/chrome/browser/task_manager/providers/arc/arc_process_task.cc
@@ -7,6 +7,8 @@
 #include <utility>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/i18n/rtl.h"
 #include "base/strings/string_number_conversions.h"
@@ -14,8 +16,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/process.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/child_process_host.h"
diff --git a/chrome/browser/task_manager/providers/arc/arc_process_task.h b/chrome/browser/task_manager/providers/arc/arc_process_task.h
index 6475756..9a4aac9 100644
--- a/chrome/browser/task_manager/providers/arc/arc_process_task.h
+++ b/chrome/browser/task_manager/providers/arc/arc_process_task.h
@@ -8,13 +8,13 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/arc/process/arc_process.h"
 #include "chrome/browser/task_manager/providers/task.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/intent_helper.mojom-forward.h"
 #include "components/arc/mojom/process.mojom-forward.h"
-#include "components/arc/session/connection_observer.h"
 
 namespace task_manager {
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 2987967e..b3ab56b 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2057,8 +2057,6 @@
       "ash/chrome_accessibility_delegate.h",
       "ash/chrome_browser_main_extra_parts_ash.cc",
       "ash/chrome_browser_main_extra_parts_ash.h",
-      "ash/chrome_desks_templates_delegate.cc",
-      "ash/chrome_desks_templates_delegate.h",
       "ash/chrome_new_window_client.cc",
       "ash/chrome_new_window_client.h",
       "ash/chrome_new_window_delegate_provider.cc",
@@ -2075,10 +2073,12 @@
       "ash/crosapi_new_window_delegate.h",
       "ash/default_pinned_apps.cc",
       "ash/default_pinned_apps.h",
-      "ash/desk_template_app_launch_handler.cc",
-      "ash/desk_template_app_launch_handler.h",
-      "ash/desks_client.cc",
-      "ash/desks_client.h",
+      "ash/desks_templates/chrome_desks_templates_delegate.cc",
+      "ash/desks_templates/chrome_desks_templates_delegate.h",
+      "ash/desks_templates/desks_templates_app_launch_handler.cc",
+      "ash/desks_templates/desks_templates_app_launch_handler.h",
+      "ash/desks_templates/desks_templates_client.cc",
+      "ash/desks_templates/desks_templates_client.h",
       "ash/holding_space/holding_space_client_impl.cc",
       "ash/holding_space/holding_space_client_impl.h",
       "ash/holding_space/holding_space_downloads_delegate.cc",
@@ -4037,8 +4037,8 @@
       "views/extensions/extensions_menu_item_view.h",
       "views/extensions/extensions_menu_view.cc",
       "views/extensions/extensions_menu_view.h",
-      "views/extensions/extensions_side_panel_controller.cc",
-      "views/extensions/extensions_side_panel_controller.h",
+      "views/extensions/extensions_tabbed_menu_view.cc",
+      "views/extensions/extensions_tabbed_menu_view.h",
       "views/extensions/extensions_toolbar_button.cc",
       "views/extensions/extensions_toolbar_button.h",
       "views/extensions/extensions_toolbar_container.cc",
@@ -4464,6 +4464,8 @@
       "views/sharing_hub/sharing_hub_bubble_view_impl.h",
       "views/sharing_hub/sharing_hub_icon_view.cc",
       "views/sharing_hub/sharing_hub_icon_view.h",
+      "views/side_panel/read_later_side_panel_web_view.cc",
+      "views/side_panel/read_later_side_panel_web_view.h",
       "views/side_panel/side_panel.cc",
       "views/side_panel/side_panel.h",
       "views/ssl_client_certificate_selector.cc",
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
index eff96a6..be5de17 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -29,6 +29,8 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.supplier.BooleanSupplier;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.LocationBar;
 import org.chromium.chrome.browser.omnibox.LocationBarCoordinator;
 import org.chromium.chrome.browser.omnibox.NewTabPageDelegate;
@@ -848,6 +850,9 @@
      * @param toolbarColor The toolbar color to base the hairline color on.
      */
     protected void setToolbarHairlineColor(@ColorInt int toolbarColor) {
+        // The refactor replaces the shadow with a hairline.
+        if (!CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID)) return;
+
         final ImageView shadow = getRootView().findViewById(R.id.toolbar_shadow);
         final int hairlineColor =
                 ThemeUtils.getToolbarHairlineColor(getContext(), toolbarColor, isIncognito());
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index cc75ca0..e7dacd84 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -11,6 +11,7 @@
 
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
+#include "ash/public/cpp/app_list/app_list_config.h"
 #include "base/bind.h"
 #include "base/check.h"
 #include "base/command_line.h"
@@ -955,8 +956,6 @@
 
   // Delete all the page breakers so that empty spaces are removed on the
   // devices with the old OS version.
-  // TODO(https://crbug.com/1242649): add page breaks to avoid page overflow
-  // on devices that expect at most 20 items per page.
   std::vector<std::string> page_breaker_ids;
   for (const auto& id_item_pair : sync_items_) {
     if (id_item_pair.second->item_type ==
@@ -966,6 +965,33 @@
   }
   for (const auto& page_break_id : page_breaker_ids)
     DeleteSyncItem(page_break_id);
+
+  // Launcher pre kProductivityLauncher launch (early 2022), had restriction on
+  // the app list page size - update the page structure among sync items to
+  // respect the lagacy page size (as items may get synced to devices that do
+  // not have kProductivityLauncher feature disabled). The page breaks are
+  // ignored with kProductivityLauncher feature enabled.
+  std::vector<SyncItem*> items = GetSortedTopLevelSyncItems();
+  const size_t kLegacyItemsPerPage =
+      ash::SharedAppListConfig::instance().GetMaxNumOfItemsPerPage();
+  std::vector<syncer::StringOrdinal> required_page_breaks;
+  for (size_t i = kLegacyItemsPerPage; i < items.size();
+       i += kLegacyItemsPerPage) {
+    const SyncItem* item_after_page_break = items[i];
+    const SyncItem* item_before_page_break = items[i - 1];
+    required_page_breaks.push_back(
+        item_before_page_break->item_ordinal.CreateBetween(
+            item_after_page_break->item_ordinal));
+  }
+
+  for (const auto& page_break_position : required_page_breaks) {
+    SyncItem* page_break_item = CreateSyncItem(
+        base::GenerateGUID(), sync_pb::AppListSpecifics::TYPE_PAGE_BREAK);
+    page_break_item->item_ordinal = page_break_position;
+    ProcessNewSyncItem(page_break_item);
+    UpdateSyncItemInLocalStorage(profile_, page_break_item);
+    SendSyncChange(page_break_item, SyncChange::ACTION_ADD);
+  }
 }
 
 void AppListSyncableService::RemoveItem(const std::string& id) {
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
index bffab6a..ead603cb 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -2082,3 +2082,219 @@
   EXPECT_EQ(GetNamesOfSortedItemsFromSyncableService(),
             std::vector<std::string>({"A", "B", "C", "D", "E", "F"}));
 }
+
+TEST_F(AppListSortUnitTest, RemovePageBreaksIfAppsDontFillUpAPage) {
+  RemoveAllExistingItems();
+  syncer::SyncDataList sync_list;
+  const std::string kItemId1 = CreateNextAppId(extensions::kWebStoreAppId);
+  sync_list.push_back(
+      CreateAppRemoteData(kItemId1, "B", "", GetLastPositionString(), kUnset));
+  const std::string kItemId2 = CreateNextAppId(kItemId1);
+  sync_list.push_back(
+      CreateAppRemoteData(kItemId2, "A", "", GetLastPositionString(), kUnset));
+  sync_list.push_back(CreateAppRemoteData(
+      app_list::kDefaultPageBreak1, "page_break_1", "", GetLastPositionString(),
+      kUnset, sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+  const std::string kItemId3 = CreateNextAppId(kItemId2);
+  sync_list.push_back(
+      CreateAppRemoteData(kItemId3, "C", "", GetLastPositionString(), kUnset));
+  sync_list.push_back(CreateAppRemoteData(
+      app_list::kDefaultPageBreak1, "page_break_2", "", GetLastPositionString(),
+      kUnset, sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+  const std::string kItemId4 = CreateNextAppId(kItemId3);
+  sync_list.push_back(
+      CreateAppRemoteData(kItemId4, "D", "", GetLastPositionString(), kUnset));
+
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  scoped_refptr<extensions::Extension> app1 =
+      MakeApp("B", kItemId1, extensions::Extension::NO_FLAGS);
+  InstallExtension(app1.get());
+
+  scoped_refptr<extensions::Extension> app3 =
+      MakeApp("C", kItemId3, extensions::Extension::NO_FLAGS);
+  InstallExtension(app1.get());
+
+  app_list_syncable_service()->SetSyncItemOrder(
+      ash::AppListSortOrder::kNameAlphabetical);
+  EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs());
+  EXPECT_EQ(GetNamesOfSortedItemsFromSyncableService(),
+            std::vector<std::string>({"A", "B", "C", "D"}));
+}
+
+TEST_F(AppListSortUnitTest, RemovePageBreaksIfAppCountMatchesLegacyPageSize) {
+  RemoveAllExistingItems();
+  syncer::SyncDataList sync_list;
+  std::string last_item_id = extensions::kWebStoreAppId;
+  for (int i = 0; i < 20; ++i) {
+    if (i == 10) {
+      sync_list.push_back(CreateAppRemoteData(
+          "page_break_1", "page_break_1", "", GetLastPositionString(), kUnset,
+          sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+    }
+
+    last_item_id = CreateNextAppId(last_item_id);
+    const std::string item_name = base::StringPrintf("Item %d", i);
+    sync_list.push_back(CreateAppRemoteData(last_item_id, item_name, "",
+                                            GetLastPositionString(), kUnset));
+    if (i % 2) {
+      scoped_refptr<extensions::Extension> app =
+          MakeApp(item_name, last_item_id, extensions::Extension::NO_FLAGS);
+      InstallExtension(app.get());
+    }
+  }
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  app_list_syncable_service()->SetSyncItemOrder(
+      ash::AppListSortOrder::kNameAlphabetical);
+  EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs());
+  EXPECT_EQ(GetNamesOfSortedItemsPerPageFromSyncableService(),
+            std::vector<std::vector<std::string>>(
+                {{"Item 0",  "Item 1",  "Item 10", "Item 11", "Item 12",
+                  "Item 13", "Item 14", "Item 15", "Item 16", "Item 17",
+                  "Item 18", "Item 19", "Item 2",  "Item 3",  "Item 4",
+                  "Item 5",  "Item 6",  "Item 7",  "Item 8",  "Item 9"}}));
+}
+
+TEST_F(AppListSortUnitTest, PageBreaksAfterSortWithTwoPagesInSync) {
+  RemoveAllExistingItems();
+  syncer::SyncDataList sync_list;
+  std::string last_item_id = extensions::kWebStoreAppId;
+  for (int i = 24; i >= 0; --i) {
+    if (i == 10) {
+      sync_list.push_back(CreateAppRemoteData(
+          "page_break_1", "page_break_1", "", GetLastPositionString(), kUnset,
+          sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+    }
+
+    last_item_id = CreateNextAppId(last_item_id);
+    const std::string item_name = base::StringPrintf("Item %d", i);
+    sync_list.push_back(CreateAppRemoteData(last_item_id, item_name, "",
+                                            GetLastPositionString(), kUnset));
+    if (i % 2) {
+      scoped_refptr<extensions::Extension> app =
+          MakeApp(item_name, last_item_id, extensions::Extension::NO_FLAGS);
+      InstallExtension(app.get());
+    }
+  }
+
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  app_list_syncable_service()->SetSyncItemOrder(
+      ash::AppListSortOrder::kNameAlphabetical);
+  EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs());
+  EXPECT_EQ(GetNamesOfSortedItemsPerPageFromSyncableService(),
+            std::vector<std::vector<std::string>>(
+                {{"Item 0",  "Item 1",  "Item 10", "Item 11", "Item 12",
+                  "Item 13", "Item 14", "Item 15", "Item 16", "Item 17",
+                  "Item 18", "Item 19", "Item 2",  "Item 20", "Item 21",
+                  "Item 22", "Item 23", "Item 24", "Item 3",  "Item 4"},
+                 {"Item 5", "Item 6", "Item 7", "Item 8", "Item 9"}}));
+}
+
+TEST_F(AppListSortUnitTest, PageBreaksAfterSortWithTwoPagesAndAFolderInSync) {
+  RemoveAllExistingItems();
+
+  const std::string kFolderId = GenerateId("folder_id");
+
+  syncer::SyncDataList sync_list;
+  std::string last_item_id = extensions::kWebStoreAppId;
+  for (int i = 24; i >= 0; --i) {
+    if (i == 10) {
+      sync_list.push_back(CreateAppRemoteData(
+          "page_break_1", "page_break_1", "", GetLastPositionString(), kUnset,
+          sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+    }
+
+    if (i == 15) {
+      sync_list.push_back(CreateAppRemoteData(
+          kFolderId, "Folder", "", GetLastPositionString(), "",
+          sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER));
+    }
+
+    last_item_id = CreateNextAppId(last_item_id);
+    const std::string item_name = base::StringPrintf("Item %d", i);
+    sync_list.push_back(CreateAppRemoteData(last_item_id, item_name,
+                                            i >= 15 && i < 20 ? kFolderId : "",
+                                            GetLastPositionString(), kUnset));
+    scoped_refptr<extensions::Extension> app =
+        MakeApp(item_name, last_item_id, extensions::Extension::NO_FLAGS);
+    InstallExtension(app.get());
+  }
+
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  app_list_syncable_service()->SetSyncItemOrder(
+      ash::AppListSortOrder::kNameAlphabetical);
+  EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs());
+  // Note that items Item 15 - Item 19 are in the folder.
+  EXPECT_EQ(GetNamesOfSortedItemsPerPageFromSyncableService(),
+            std::vector<std::vector<std::string>>(
+                {{"Folder",  "Item 0",  "Item 1",  "Item 10", "Item 11",
+                  "Item 12", "Item 13", "Item 14", "Item 2",  "Item 20",
+                  "Item 21", "Item 22", "Item 23", "Item 24", "Item 3",
+                  "Item 4",  "Item 5",  "Item 6",  "Item 7",  "Item 8"},
+                 {"Item 9"}}));
+}
+
+TEST_F(AppListSortUnitTest, PageBreaksAfterSortWithTwoFullPagesInSync) {
+  RemoveAllExistingItems();
+  syncer::SyncDataList sync_list;
+  std::string last_item_id = extensions::kWebStoreAppId;
+  for (int i = 39; i >= 0; --i) {
+    if (i == 10) {
+      sync_list.push_back(CreateAppRemoteData(
+          "page_break_1", "page_break_1", "", GetLastPositionString(), kUnset,
+          sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+    }
+    if (i == 25) {
+      sync_list.push_back(CreateAppRemoteData(
+          "page_break_2", "page_break_2", "", GetLastPositionString(), kUnset,
+          sync_pb::AppListSpecifics_AppListItemType_TYPE_PAGE_BREAK));
+    }
+
+    last_item_id = CreateNextAppId(last_item_id);
+    const std::string item_name = base::StringPrintf("Item %d", i);
+    sync_list.push_back(CreateAppRemoteData(last_item_id, item_name, "",
+                                            GetLastPositionString(), kUnset));
+    scoped_refptr<extensions::Extension> app =
+        MakeApp(item_name, last_item_id, extensions::Extension::NO_FLAGS);
+    InstallExtension(app.get());
+  }
+
+  app_list_syncable_service()->MergeDataAndStartSyncing(
+      syncer::APP_LIST, sync_list,
+      std::make_unique<syncer::FakeSyncChangeProcessor>(),
+      std::make_unique<syncer::SyncErrorFactoryMock>());
+  content::RunAllTasksUntilIdle();
+
+  app_list_syncable_service()->SetSyncItemOrder(
+      ash::AppListSortOrder::kNameAlphabetical);
+  EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs());
+  EXPECT_EQ(GetNamesOfSortedItemsPerPageFromSyncableService(),
+            std::vector<std::vector<std::string>>(
+                {{"Item 0",  "Item 1",  "Item 10", "Item 11", "Item 12",
+                  "Item 13", "Item 14", "Item 15", "Item 16", "Item 17",
+                  "Item 18", "Item 19", "Item 2",  "Item 20", "Item 21",
+                  "Item 22", "Item 23", "Item 24", "Item 25", "Item 26"},
+                 {"Item 27", "Item 28", "Item 29", "Item 3",  "Item 30",
+                  "Item 31", "Item 32", "Item 33", "Item 34", "Item 35",
+                  "Item 36", "Item 37", "Item 38", "Item 39", "Item 4",
+                  "Item 5",  "Item 6",  "Item 7",  "Item 8",  "Item 9"}}));
+}
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 f9759ad..248e602 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
@@ -12,6 +12,9 @@
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
 #include "ash/components/arc/compat_mode/arc_resize_lock_manager.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/bind.h"
@@ -43,9 +46,6 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/arc/mojom/compatibility_mode.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/crx_file/id_util.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/scoped_user_pref_update.h"
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 2eaeda80..c3cb394 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
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include "ash/components/arc/compat_mode/arc_resize_lock_pref_delegate.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
@@ -28,7 +29,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_icon_descriptor.h"
 #include "components/arc/mojom/app.mojom.h"
 #include "components/arc/mojom/compatibility_mode.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/layout.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc
index 2cf5c92..7e347d1 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h
index cb194bc1..7582213a 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h
@@ -8,9 +8,9 @@
 #include <memory>
 #include <unordered_map>
 
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/memory/singleton.h"
 #include "components/arc/mojom/app.mojom-forward.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 class ArcAppListPrefs;
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 f8d4104..6c2bf5026 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_test.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -5,6 +5,9 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
+#include "ash/components/arc/session/arc_session_runner.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
@@ -28,9 +31,6 @@
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
-#include "components/arc/session/arc_session_runner.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
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 2f224939..37f9cbb 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -15,6 +15,7 @@
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "ash/constants/ash_switches.h"
@@ -77,7 +78,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/mojom/app.mojom.h"
 #include "components/arc/mojom/compatibility_mode.mojom.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
index 360adcd..90306a5 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -14,6 +14,8 @@
 #include "ash/components/arc/arc_util.h"
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/check.h"
 #include "base/containers/contains.h"
 #include "base/json/json_writer.h"
@@ -52,8 +54,6 @@
 #include "components/app_restore/app_restore_utils.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc b/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc
index d505146..5c466644 100644
--- a/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc
+++ b/chrome/browser/ui/app_list/arc/arc_package_syncable_service.cc
@@ -9,12 +9,12 @@
 #include <vector>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/connection_holder.h"
 #include "base/containers/contains.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_package_syncable_service_factory.h"
 #include "chrome/common/pref_names.h"
-#include "components/arc/session/connection_holder.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/sync/model/sync_change_processor.h"
 #include "components/sync/model/sync_data.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_pai_starter.cc b/chrome/browser/ui/app_list/arc/arc_pai_starter.cc
index 5281236..a6b9b0a 100644
--- a/chrome/browser/ui/app_list/arc/arc_pai_starter.cc
+++ b/chrome/browser/ui/app_list/arc/arc_pai_starter.cc
@@ -11,12 +11,12 @@
 
 #include "ash/components/arc/arc_prefs.h"
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/pref_service.h"
 #include "ui/events/event_constants.h"
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
index d60544b..b21092f 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
@@ -8,6 +8,8 @@
 #include <unordered_set>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/public/cpp/app_list/app_list_config.h"
@@ -23,8 +25,6 @@
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/common/url_icon_source.h"
 #include "chrome/common/pref_names.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
index 32b1de9..89f2326a 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
@@ -8,13 +8,13 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
index 4191b0cd..9b94652 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
@@ -8,6 +8,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
@@ -17,8 +19,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h"
 #include "components/arc/app/arc_playstore_search_request_state.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace {
 constexpr int kHistogramBuckets = 13;
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
index 334be7e3..65e10b7 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
@@ -6,6 +6,8 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "ash/public/cpp/app_list/vector_icons/vector_icons.h"
 #include "base/bind.h"
@@ -18,8 +20,6 @@
 #include "chrome/browser/ui/app_list/arc/arc_playstore_app_context_menu.h"
 #include "chrome/browser/ui/app_list/search/search_tags_util.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/crx_file/id_util.h"
 #include "ui/base/models/image_model.h"
 #include "ui/gfx/canvas.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.cc b/chrome/browser/ui/app_list/search/omnibox_result.cc
index 6f64e46..c43445a9 100644
--- a/chrome/browser/ui/app_list/search/omnibox_result.cc
+++ b/chrome/browser/ui/app_list/search/omnibox_result.cc
@@ -515,11 +515,9 @@
 void OmniboxResult::SetZeroSuggestionActions() {
   Actions zero_suggestion_actions;
 
-  constexpr int kMaxButtons =
-      ash::SearchResultActionType::kSearchResultActionTypeMax;
-  for (int i = 0; i < kMaxButtons; ++i) {
-    ash::SearchResultActionType button_action =
-        ash::GetSearchResultActionType(i);
+  for (ash::SearchResultActionType button_action :
+       {ash::SearchResultActionType::kRemove,
+        ash::SearchResultActionType::kAppend}) {
     gfx::ImageSkia button_image;
     std::u16string button_tooltip;
     bool visible_on_hover = false;
@@ -544,7 +542,8 @@
       default:
         NOTREACHED();
     }
-    Action search_action(button_image, button_tooltip, visible_on_hover);
+    Action search_action(button_action, button_image, button_tooltip,
+                         visible_on_hover);
     zero_suggestion_actions.emplace_back(search_action);
   }
 
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc b/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc
index 950709d..95fd0a8 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc
+++ b/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc
@@ -9,11 +9,6 @@
 
 namespace app_list {
 
-// static
-bool RemovedResultsRanker::ShouldDelegateToResult(ProviderType provider) {
-  return provider == ash::AppListSearchResultType::kOmnibox;
-}
-
 RemovedResultsRanker::RemovedResultsRanker(const base::FilePath& path,
                                            const base::TimeDelta write_delay)
     : write_delay_(write_delay) {
@@ -25,9 +20,7 @@
 void RemovedResultsRanker::Rank(ResultsMap& results,
                                 CategoriesMap& categories,
                                 ProviderType provider) {
-  // Results with delegated removal are handled in
-  // SearchController::InvokeResultAction().
-  if (!initialized() || ShouldDelegateToResult(provider))
+  if (!initialized())
     return;
 
   const auto it = results.find(provider);
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h b/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h
index 9a55b37..681d118 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h
+++ b/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h
@@ -34,14 +34,6 @@
 
   void Remove(ChromeSearchResult* result) override;
 
-  // Returns whether result removal requests for results from type |provider|
-  // should be delegated to the result, as opposed to handled by this class.
-  // Currently this returns true in one case:
-  //   1) Omnibox results, whose removal requests are handled by the omnibox
-  //      autocomplete controller. The Omnibox is unique amongst our search
-  //      providers in that it has a backend which supports result removal.
-  static bool ShouldDelegateToResult(ProviderType provider);
-
  private:
   friend class RemovedResultsRankerTest;
 
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc b/chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc
index 06e10bb..b72926c7 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc
+++ b/chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc
@@ -129,6 +129,7 @@
   // Request to remove some results.
   ranker.Remove(make_result("A").get());
   ranker.Remove(make_result("C").get());
+  ranker.Remove(make_result("E").get());
   Wait();
 
   CategoriesMap categories;
@@ -147,18 +148,22 @@
   EXPECT_TRUE(results_map[ResultType::kInternalApp][0]->scoring().filter);
   EXPECT_FALSE(results_map[ResultType::kInternalApp][1]->scoring().filter);
 
-  // Omnibox: Ranking has no effect on omnibox results.
+  // Omnibox: The 0th result ("C") is marked to be filtered.
+  //
+  // TODO(crbug.com/1272361): Ranking here should not affect Omnibox results,
+  // after support is added to the autocomplete controller for removal of
+  // non-zero state Omnibox results.
   ranker.Rank(results_map, categories, ResultType::kOmnibox);
-  EXPECT_FALSE(results_map[ResultType::kOmnibox][0]->scoring().filter);
+  EXPECT_TRUE(results_map[ResultType::kOmnibox][0]->scoring().filter);
 
   // Check proto for record of removed results.
   RemovedResultsProto proto = ReadFromDisk();
-  EXPECT_EQ(proto.removed_ids_size(), 2);
+  EXPECT_EQ(proto.removed_ids_size(), 3);
 
   std::vector<std::string> recorded_ids;
   for (const auto& result : proto.removed_ids())
     recorded_ids.push_back(result.first);
-  EXPECT_THAT(recorded_ids, UnorderedElementsAre("A", "C"));
+  EXPECT_THAT(recorded_ids, UnorderedElementsAre("A", "C", "E"));
 }
 
 TEST_F(RemovedResultsRankerTest, RankEmptyResults) {
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
index cdd549a0..88ed4db 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
@@ -122,18 +122,25 @@
   if (!result)
     return;
 
-  // In the special case, actions are delegated to the result itself. This is
-  // when, for example, actions are handled by a provider backend, as is the
-  // case with Omnibox results.
-  //
   // In the general case, actions are forwarded to the RemovedResultsRanker.
   // Currently only "remove" actions are supported (and not e.g. "append"
   // actions).
-  if (RemovedResultsRanker::ShouldDelegateToResult(result->result_type())) {
-    result->InvokeAction(action);
-  } else if (action == ash::SearchResultActionType::kRemove) {
-    // All other result removals are handled by the ranking system.
+  //
+  // In the special case, actions are delegated to the result itself. This is
+  // when, for example, supported actions can be handled by a provider backend,
+  // as is the case with some actions for some Omnibox results. At the moment we
+  // are temporarily handling Omnibox result removal requests in the general
+  // case, using RemovedResultsRanker, because the omnibox autocomplete
+  // controller supports removal of zero-state results but not of non-zero state
+  // results.
+  //
+  // TODO(crbug.com/1272361): Call result->InvokeAction(action) for all Omnibox
+  // action requests, once the autocomplete controller supports removal of
+  // non-zero state results.
+  if (action == ash::SearchResultActionType::kRemove) {
     ranker_->Remove(result);
+  } else if (result->result_type() == ash::AppListSearchResultType::kOmnibox) {
+    result->InvokeAction(action);
   }
 }
 
diff --git a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc b/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc
index 7f4933f4..fa8955fc 100644
--- a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc
+++ b/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc
@@ -107,6 +107,27 @@
   return names;
 }
 
+std::vector<std::vector<std::string>> AppListSyncableServiceTestBase::
+    GetNamesOfSortedItemsPerPageFromSyncableService() {
+  std::vector<std::vector<std::string>> pages;
+  pages.emplace_back();
+
+  const std::vector<std::string> ids = GetOrderedItemIdsFromSyncableService();
+  for (const auto& id : ids) {
+    const app_list::AppListSyncableService::SyncItem* item =
+        app_list_syncable_service()->GetSyncItem(id);
+    if (!item->parent_id.empty())
+      continue;
+    if (item->item_type == sync_pb::AppListSpecifics::TYPE_PAGE_BREAK) {
+      pages.emplace_back();
+      continue;
+    }
+    pages.back().push_back(
+        app_list_syncable_service()->GetSyncItem(id)->item_name);
+  }
+  return pages;
+}
+
 syncer::StringOrdinal AppListSyncableServiceTestBase::GetPositionFromSyncData(
     const std::string& id) const {
   return app_list_syncable_service_->GetSyncItem(id)->item_ordinal;
diff --git a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h b/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h
index b1a5d95..181bdf2f 100644
--- a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h
+++ b/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h
@@ -48,6 +48,12 @@
   // Gets the names of the items ordered by the positions stored in sync data.
   std::vector<std::string> GetNamesOfSortedItemsFromSyncableService();
 
+  // Gets the names of items ordered by the positions stored in sync data,
+  // grouped in pages (as defined by page break items). Lists themselves will
+  // not contain page breaks.
+  std::vector<std::vector<std::string>>
+  GetNamesOfSortedItemsPerPageFromSyncableService();
+
   // Gets the specified item's position from sync data.
   syncer::StringOrdinal GetPositionFromSyncData(const std::string& id) const;
 
diff --git a/chrome/browser/ui/ash/assistant/assistant_context_util.cc b/chrome/browser/ui/ash/assistant/assistant_context_util.cc
index 9a93b224..c715bfc 100644
--- a/chrome/browser/ui/ash/assistant/assistant_context_util.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_context_util.cc
@@ -6,6 +6,8 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ui/browser.h"
@@ -14,8 +16,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "components/arc/mojom/app.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/accessibility/ax_assistant_structure.h"
diff --git a/chrome/browser/ui/ash/assistant/device_actions.cc b/chrome/browser/ui/ash/assistant/device_actions.cc
index 190c04b..49688f0 100644
--- a/chrome/browser/ui/ash/assistant/device_actions.cc
+++ b/chrome/browser/ui/ash/assistant/device_actions.cc
@@ -8,6 +8,8 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_pref_names.h"
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
@@ -22,8 +24,6 @@
 #include "chromeos/network/network_event_log.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "ui/display/types/display_constants.h"
diff --git a/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc b/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc
index 6b8cc03..52b0ee97 100644
--- a/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc
+++ b/chrome/browser/ui/ash/capture_mode/capture_mode_browsertest.cc
@@ -28,9 +28,9 @@
 
 namespace {
 
-// Defines a warning-level restriction type for video captures.
-const policy::DlpContentRestrictionSet kVideoCaptureWarned{
-    policy::DlpContentRestriction::kVideoCapture,
+// Defines a warning-level restriction type for screen captures.
+const policy::DlpContentRestrictionSet kScreenCaptureWarned{
+    policy::DlpContentRestriction::kScreenshot,
     policy::DlpRulesManager::Level::kWarn};
 
 // Returns the native window of the given `browser`.
@@ -79,7 +79,7 @@
 
 // Marks the active web contents of the given `browser` as DLP restricted with a
 // warning level.
-void MarkActiveTabAsDlpWarnedForVideoCapture(Browser* browser) {
+void MarkActiveTabAsDlpWarnedForScreenCapture(Browser* browser) {
   auto* dlp_content_observer = policy::DlpContentObserver::Get();
   ASSERT_TRUE(dlp_content_observer);
 
@@ -87,7 +87,7 @@
       browser->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(web_contents);
   dlp_content_observer->OnConfidentialityChanged(web_contents,
-                                                 kVideoCaptureWarned);
+                                                 kScreenCaptureWarned);
 }
 
 // Stops the video recording and waits for the DLP warning dialog to be added.
@@ -136,7 +136,7 @@
   ASSERT_TRUE(browser());
   StartVideoRecording();
 
-  MarkActiveTabAsDlpWarnedForVideoCapture(browser());
+  MarkActiveTabAsDlpWarnedForScreenCapture(browser());
   ash::CaptureModeTestApi test_api;
   // Video recording should not end as a result of adding a restriction of a
   // warning level type.
@@ -164,7 +164,7 @@
   ASSERT_TRUE(browser());
   StartVideoRecording();
 
-  MarkActiveTabAsDlpWarnedForVideoCapture(browser());
+  MarkActiveTabAsDlpWarnedForScreenCapture(browser());
   ash::CaptureModeTestApi test_api;
   // Video recording should not end as a result of adding a restriction of a
   // warning level type.
@@ -190,7 +190,7 @@
                        DlpWarningDialogOnSessionInitDismissed) {
   ASSERT_TRUE(browser());
 
-  MarkActiveTabAsDlpWarnedForVideoCapture(browser());
+  MarkActiveTabAsDlpWarnedForScreenCapture(browser());
   ash::CaptureModeTestApi test_api;
   EXPECT_FALSE(test_api.IsPendingDlpCheckOnSessionInit());
 
@@ -211,7 +211,7 @@
                        DlpWarningDialogOnSessionInitAccepted) {
   ASSERT_TRUE(browser());
 
-  MarkActiveTabAsDlpWarnedForVideoCapture(browser());
+  MarkActiveTabAsDlpWarnedForScreenCapture(browser());
   ash::CaptureModeTestApi test_api;
   EXPECT_FALSE(test_api.IsPendingDlpCheckOnSessionInit());
 
diff --git a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc
index fdee547..e4a9974 100644
--- a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc
+++ b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.cc
@@ -144,13 +144,9 @@
 
 bool ChromeCaptureModeDelegate::IsCaptureAllowedByDlp(
     const aura::Window* window,
-    const gfx::Rect& bounds,
-    bool for_video) const {
-  policy::DlpContentManager* dlp_content_manager =
-      policy::DlpContentManager::Get();
-  const ScreenshotArea area = ConvertToScreenshotArea(window, bounds);
-  return for_video ? !dlp_content_manager->IsVideoCaptureRestricted(area)
-                   : !dlp_content_manager->IsScreenshotRestricted(area);
+    const gfx::Rect& bounds) const {
+  return !policy::DlpContentManager::Get()->IsScreenshotRestricted(
+      ConvertToScreenshotArea(window, bounds));
 }
 
 bool ChromeCaptureModeDelegate::IsCaptureAllowedByPolicy() const {
diff --git a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h
index f26441f..26cf489b 100644
--- a/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h
+++ b/chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h
@@ -40,8 +40,7 @@
   void CheckCaptureModeInitRestrictionByDlp(
       ash::OnCaptureModeDlpRestrictionChecked callback) override;
   bool IsCaptureAllowedByDlp(const aura::Window* window,
-                             const gfx::Rect& bounds,
-                             bool for_video) const override;
+                             const gfx::Rect& bounds) const override;
   bool IsCaptureAllowedByPolicy() const override;
   void StartObservingRestrictedContent(
       const aura::Window* window,
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
index 29e7b04..91527cd 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -35,7 +35,7 @@
 #include "chrome/browser/ui/ash/chrome_new_window_client.h"
 #include "chrome/browser/ui/ash/chrome_new_window_delegate_provider.h"
 #include "chrome/browser/ui/ash/crosapi_new_window_delegate.h"
-#include "chrome/browser/ui/ash/desks_client.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_client.h"
 #include "chrome/browser/ui/ash/ime_controller_client_impl.h"
 #include "chrome/browser/ui/ash/in_session_auth_dialog_client.h"
 #include "chrome/browser/ui/ash/login_screen_client_impl.h"
@@ -227,7 +227,7 @@
     projector_client_ = std::make_unique<ProjectorClientImpl>();
   }
 
-  desks_client_ = std::make_unique<DesksClient>();
+  desks_templates_client_ = std::make_unique<DesksTemplatesClient>();
 
   if (ash::features::IsBluetoothRevampEnabled()) {
     chromeos::bluetooth_config::FastPairDelegate* delegate =
@@ -304,7 +304,7 @@
   night_light_client_.reset();
   mobile_data_notifications_.reset();
   chrome_shelf_controller_initializer_.reset();
-  desks_client_.reset();
+  desks_templates_client_.reset();
 
   wallpaper_controller_client_.reset();
   vpn_list_forwarder_.reset();
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
index 24c0b7e..3e979fe 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
@@ -28,7 +28,7 @@
 class AshShellInit;
 class AshWebViewFactoryImpl;
 class CastConfigControllerMediaRouter;
-class DesksClient;
+class DesksTemplatesClient;
 class ImeControllerClientImpl;
 class InSessionAuthDialogClient;
 class LoginScreenClientImpl;
@@ -113,7 +113,7 @@
 
   std::unique_ptr<internal::ChromeShelfControllerInitializer>
       chrome_shelf_controller_initializer_;
-  std::unique_ptr<DesksClient> desks_client_;
+  std::unique_ptr<DesksTemplatesClient> desks_templates_client_;
 
 #if BUILDFLAG(ENABLE_WAYLAND_SERVER)
   std::unique_ptr<ExoParts> exo_parts_;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 90809d8..4f06386 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -31,7 +31,7 @@
 #include "chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.h"
 #include "chrome/browser/ui/ash/capture_mode/chrome_capture_mode_delegate.h"
 #include "chrome/browser/ui/ash/chrome_accessibility_delegate.h"
-#include "chrome/browser/ui/ash/chrome_desks_templates_delegate.h"
+#include "chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.h"
 #include "chrome/browser/ui/ash/session_util.h"
 #include "chrome/browser/ui/ash/tab_scrubber.h"
diff --git a/chrome/browser/ui/ash/desks_templates/OWNERS b/chrome/browser/ui/ash/desks_templates/OWNERS
new file mode 100644
index 0000000..334225e
--- /dev/null
+++ b/chrome/browser/ui/ash/desks_templates/OWNERS
@@ -0,0 +1,2 @@
+sammiequon@chromium.org
+xdai@chromium.org
diff --git a/chrome/browser/ui/ash/chrome_desks_templates_delegate.cc b/chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.cc
similarity index 96%
rename from chrome/browser/ui/ash/chrome_desks_templates_delegate.cc
rename to chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.cc
index c016ec4..f88c41e1 100644
--- a/chrome/browser/ui/ash/chrome_desks_templates_delegate.cc
+++ b/chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.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/ui/ash/chrome_desks_templates_delegate.h"
+#include "chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.h"
 
 #include "ash/constants/app_types.h"
 #include "ash/constants/ash_features.h"
@@ -15,7 +15,7 @@
 #include "chrome/browser/favicon/favicon_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/ash/desks_client.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_client.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/chrome_features.h"
@@ -137,7 +137,7 @@
 }
 
 desks_storage::DeskModel* ChromeDesksTemplatesDelegate::GetDeskModel() {
-  return DesksClient::Get()->GetDeskModel();
+  return DesksTemplatesClient::Get()->GetDeskModel();
 }
 
 absl::optional<gfx::ImageSkia>
@@ -193,7 +193,7 @@
 
 void ChromeDesksTemplatesDelegate::LaunchAppsFromTemplate(
     std::unique_ptr<ash::DeskTemplate> desk_template) {
-  DesksClient::Get()->LaunchAppsFromTemplate(std::move(desk_template));
+  DesksTemplatesClient::Get()->LaunchAppsFromTemplate(std::move(desk_template));
 }
 
 // Returns true if `window` is supported in desk templates feature.
diff --git a/chrome/browser/ui/ash/chrome_desks_templates_delegate.h b/chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.h
similarity index 87%
rename from chrome/browser/ui/ash/chrome_desks_templates_delegate.h
rename to chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.h
index 78e1325..6e09030 100644
--- a/chrome/browser/ui/ash/chrome_desks_templates_delegate.h
+++ b/chrome/browser/ui/ash/desks_templates/chrome_desks_templates_delegate.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_UI_ASH_CHROME_DESKS_TEMPLATES_DELEGATE_H_
-#define CHROME_BROWSER_UI_ASH_CHROME_DESKS_TEMPLATES_DELEGATE_H_
+#ifndef CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_CHROME_DESKS_TEMPLATES_DELEGATE_H_
+#define CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_CHROME_DESKS_TEMPLATES_DELEGATE_H_
 
 #include <memory>
 
@@ -43,4 +43,4 @@
   bool IsWindowSupportedForDeskTemplate(aura::Window* window) const override;
 };
 
-#endif  // CHROME_BROWSER_UI_ASH_CHROME_DESKS_TEMPLATES_DELEGATE_H_
+#endif  // CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_CHROME_DESKS_TEMPLATES_DELEGATE_H_
diff --git a/chrome/browser/ui/ash/desk_template_app_launch_handler.cc b/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.cc
similarity index 90%
rename from chrome/browser/ui/ash/desk_template_app_launch_handler.cc
rename to chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.cc
index 0a5ecbae..e6c8e39c 100644
--- a/chrome/browser/ui/ash/desk_template_app_launch_handler.cc
+++ b/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_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 "chrome/browser/ui/ash/desk_template_app_launch_handler.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.h"
 
 #include <string>
 
@@ -36,13 +36,13 @@
 
 }  // namespace
 
-DeskTemplateAppLaunchHandler::DeskTemplateAppLaunchHandler(Profile* profile)
+DesksTemplatesAppLaunchHandler::DesksTemplatesAppLaunchHandler(Profile* profile)
     : ash::AppLaunchHandler(profile),
       read_handler_(app_restore::DeskTemplateReadHandler::Get()) {}
 
-DeskTemplateAppLaunchHandler::~DeskTemplateAppLaunchHandler() = default;
+DesksTemplatesAppLaunchHandler::~DesksTemplatesAppLaunchHandler() = default;
 
-void DeskTemplateAppLaunchHandler::SetRestoreDataAndLaunch(
+void DesksTemplatesAppLaunchHandler::SetRestoreDataAndLaunch(
     std::unique_ptr<app_restore::RestoreData> new_restore_data) {
   // Another desk template is underway.
   // TODO(sammiequon): Checking the read handler for restore data is temporary.
@@ -66,13 +66,13 @@
 
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(&DeskTemplateAppLaunchHandler::
+      base::BindOnce(&DesksTemplatesAppLaunchHandler::
                          ClearDeskTemplateReadHandlerRestoreData,
                      weak_ptr_factory_.GetWeakPtr()),
       kClearRestoreDataDuration);
 }
 
-bool DeskTemplateAppLaunchHandler::ShouldLaunchSystemWebAppOrChromeApp(
+bool DesksTemplatesAppLaunchHandler::ShouldLaunchSystemWebAppOrChromeApp(
     const std::string& app_id,
     const app_restore::RestoreData::LaunchList& launch_list) {
   // Find out if the app can have multiple instances. Apps that can have
@@ -124,17 +124,17 @@
       app_id, launch_list);
 }
 
-void DeskTemplateAppLaunchHandler::OnExtensionLaunching(
+void DesksTemplatesAppLaunchHandler::OnExtensionLaunching(
     const std::string& app_id) {
   read_handler_->SetNextRestoreWindowIdForChromeApp(app_id);
 }
 
 base::WeakPtr<ash::AppLaunchHandler>
-DeskTemplateAppLaunchHandler::GetWeakPtrAppLaunchHandler() {
+DesksTemplatesAppLaunchHandler::GetWeakPtrAppLaunchHandler() {
   return weak_ptr_factory_.GetWeakPtr();
 }
 
-void DeskTemplateAppLaunchHandler::LaunchBrowsers() {
+void DesksTemplatesAppLaunchHandler::LaunchBrowsers() {
   DCHECK(restore_data());
 
   const auto& launch_list = restore_data()->app_id_to_launch_list();
@@ -202,7 +202,7 @@
   restore_data()->RemoveApp(extension_misc::kChromeAppId);
 }
 
-void DeskTemplateAppLaunchHandler::MaybeLaunchArcApps() {
+void DesksTemplatesAppLaunchHandler::MaybeLaunchArcApps() {
   if (!ash::features::AreDesksTemplatesEnabled())
     return;
 
@@ -217,11 +217,11 @@
   }
 }
 
-void DeskTemplateAppLaunchHandler::ClearDeskTemplateReadHandlerRestoreData() {
+void DesksTemplatesAppLaunchHandler::ClearDeskTemplateReadHandlerRestoreData() {
   read_handler_->SetRestoreData(nullptr);
 }
 
-void DeskTemplateAppLaunchHandler::RecordRestoredAppLaunch(
+void DesksTemplatesAppLaunchHandler::RecordRestoredAppLaunch(
     apps::AppTypeName app_type_name) {
   // TODO: Add UMA Histogram.
   NOTIMPLEMENTED();
diff --git a/chrome/browser/ui/ash/desk_template_app_launch_handler.h b/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.h
similarity index 65%
rename from chrome/browser/ui/ash/desk_template_app_launch_handler.h
rename to chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.h
index fdf854b..32ea70c 100644
--- a/chrome/browser/ui/ash/desk_template_app_launch_handler.h
+++ b/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_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 CHROME_BROWSER_UI_ASH_DESK_TEMPLATE_APP_LAUNCH_HANDLER_H_
-#define CHROME_BROWSER_UI_ASH_DESK_TEMPLATE_APP_LAUNCH_HANDLER_H_
+#ifndef CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_DESKS_TEMPLATES_APP_LAUNCH_HANDLER_H_
+#define CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_DESKS_TEMPLATES_APP_LAUNCH_HANDLER_H_
 
 #include <memory>
 
@@ -21,15 +21,17 @@
 class RestoreData;
 }  // namespace app_restore
 
-// The DeskTemplateAppLaunchHandler class is passed in the desk template restore
-// data and profile, and will launch apps and web pages based on the template.
-class DeskTemplateAppLaunchHandler : public ash::AppLaunchHandler {
+// The DesksTemplatesAppLaunchHandler class is passed in the desk template
+// restore data and profile, and will launch apps and web pages based on the
+// template.
+class DesksTemplatesAppLaunchHandler : public ash::AppLaunchHandler {
  public:
-  explicit DeskTemplateAppLaunchHandler(Profile* profile);
-  DeskTemplateAppLaunchHandler(const DeskTemplateAppLaunchHandler&) = delete;
-  DeskTemplateAppLaunchHandler& operator=(const DeskTemplateAppLaunchHandler&) =
+  explicit DesksTemplatesAppLaunchHandler(Profile* profile);
+  DesksTemplatesAppLaunchHandler(const DesksTemplatesAppLaunchHandler&) =
       delete;
-  ~DeskTemplateAppLaunchHandler() override;
+  DesksTemplatesAppLaunchHandler& operator=(
+      const DesksTemplatesAppLaunchHandler&) = delete;
+  ~DesksTemplatesAppLaunchHandler() override;
 
   void SetRestoreDataAndLaunch(
       std::unique_ptr<app_restore::RestoreData> restore_data);
@@ -60,7 +62,7 @@
   // Cached convenience pointer to the desk template read handler.
   app_restore::DeskTemplateReadHandler* const read_handler_;
 
-  base::WeakPtrFactory<DeskTemplateAppLaunchHandler> weak_ptr_factory_{this};
+  base::WeakPtrFactory<DesksTemplatesAppLaunchHandler> weak_ptr_factory_{this};
 };
 
-#endif  // CHROME_BROWSER_UI_ASH_DESK_TEMPLATE_APP_LAUNCH_HANDLER_H_
+#endif  // CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_DESKS_TEMPLATES_APP_LAUNCH_HANDLER_H_
diff --git a/chrome/browser/ui/ash/desks_client.cc b/chrome/browser/ui/ash/desks_templates/desks_templates_client.cc
similarity index 74%
rename from chrome/browser/ui/ash/desks_client.cc
rename to chrome/browser/ui/ash/desks_templates/desks_templates_client.cc
index 4818d06..9692970 100644
--- a/chrome/browser/ui/ash/desks_client.cc
+++ b/chrome/browser/ui/ash/desks_templates/desks_templates_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 "chrome/browser/ui/ash/desks_client.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_client.h"
 
 #include <memory>
 
@@ -20,14 +20,15 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sync/desk_sync_service_factory.h"
-#include "chrome/browser/ui/ash/desk_template_app_launch_handler.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.h"
 #include "components/desks_storage/core/desk_sync_service.h"
 #include "components/desks_storage/core/local_desk_data_manager.h"
 #include "components/sync/model/model_type_store.h"
 #include "extensions/common/constants.h"
 
 namespace {
-DesksClient* g_desks_client_instance = nullptr;
+
+DesksTemplatesClient* g_desks_templates_client_instance = nullptr;
 
 // Histogram names
 constexpr char kWindowCountHistogramName[] = "Ash.DeskTemplate.WindowCount";
@@ -56,24 +57,26 @@
 
 }  // namespace
 
-DesksClient::DesksClient() : desks_controller_(ash::DesksController::Get()) {
-  DCHECK(!g_desks_client_instance);
-  g_desks_client_instance = this;
+DesksTemplatesClient::DesksTemplatesClient()
+    : desks_controller_(ash::DesksController::Get()) {
+  DCHECK(!g_desks_templates_client_instance);
+  g_desks_templates_client_instance = this;
   ash::SessionController::Get()->AddObserver(this);
 }
 
-DesksClient::~DesksClient() {
-  DCHECK_EQ(this, g_desks_client_instance);
-  g_desks_client_instance = nullptr;
+DesksTemplatesClient::~DesksTemplatesClient() {
+  DCHECK_EQ(this, g_desks_templates_client_instance);
+  g_desks_templates_client_instance = nullptr;
   ash::SessionController::Get()->RemoveObserver(this);
 }
 
 // static
-DesksClient* DesksClient::Get() {
-  return g_desks_client_instance;
+DesksTemplatesClient* DesksTemplatesClient::Get() {
+  return g_desks_templates_client_instance;
 }
 
-void DesksClient::OnActiveUserSessionChanged(const AccountId& account_id) {
+void DesksTemplatesClient::OnActiveUserSessionChanged(
+    const AccountId& account_id) {
   Profile* profile =
       ash::ProfileHelper::Get()->GetProfileByAccountId(account_id);
   if (profile == active_profile_ || !IsSupportedProfile(profile))
@@ -93,7 +96,7 @@
     GetDeskModel()->SetPolicyDeskTemplates(policy_desk_templates_it->second);
 }
 
-void DesksClient::CaptureActiveDeskAndSaveTemplate(
+void DesksTemplatesClient::CaptureActiveDeskAndSaveTemplate(
     CaptureActiveDeskAndSaveTemplateCallback callback) {
   if (!active_profile_) {
     std::move(callback).Run(/*desk_template=*/nullptr,
@@ -102,26 +105,29 @@
   }
 
   desks_controller_->CaptureActiveDeskAsTemplate(
-      base::BindOnce(&DesksClient::OnCapturedDeskTemplate,
+      base::BindOnce(&DesksTemplatesClient::OnCapturedDeskTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void DesksClient::UpdateDeskTemplate(const std::string& template_uuid,
-                                     const std::u16string& template_name,
-                                     UpdateDeskTemplateCallback callback) {
+void DesksTemplatesClient::UpdateDeskTemplate(
+    const std::string& template_uuid,
+    const std::u16string& template_name,
+    UpdateDeskTemplateCallback callback) {
   if (!active_profile_) {
     std::move(callback).Run(std::string(kNoCurrentUserError));
     return;
   }
 
   GetDeskModel()->GetEntryByUUID(
-      template_uuid, base::BindOnce(&DesksClient::OnGetTemplateToBeUpdated,
-                                    weak_ptr_factory_.GetWeakPtr(),
-                                    template_name, std::move(callback)));
+      template_uuid,
+      base::BindOnce(&DesksTemplatesClient::OnGetTemplateToBeUpdated,
+                     weak_ptr_factory_.GetWeakPtr(), template_name,
+                     std::move(callback)));
 }
 
-void DesksClient::DeleteDeskTemplate(const std::string& template_uuid,
-                                     DeleteDeskTemplateCallback callback) {
+void DesksTemplatesClient::DeleteDeskTemplate(
+    const std::string& template_uuid,
+    DeleteDeskTemplateCallback callback) {
   if (!active_profile_) {
     std::move(callback).Run(std::string(kNoCurrentUserError));
     return;
@@ -129,24 +135,25 @@
 
   GetDeskModel()->DeleteEntry(
       template_uuid,
-      base::BindOnce(&DesksClient::OnDeleteDeskTemplate,
+      base::BindOnce(&DesksTemplatesClient::OnDeleteDeskTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void DesksClient::GetDeskTemplates(GetDeskTemplatesCallback callback) {
+void DesksTemplatesClient::GetDeskTemplates(GetDeskTemplatesCallback callback) {
   if (!active_profile_) {
     std::move(callback).Run(/*desk_templates=*/{},
                             std::string(kNoCurrentUserError));
     return;
   }
 
-  GetDeskModel()->GetAllEntries(base::BindOnce(&DesksClient::OnGetAllTemplates,
-                                               weak_ptr_factory_.GetWeakPtr(),
-                                               std::move(callback)));
+  GetDeskModel()->GetAllEntries(
+      base::BindOnce(&DesksTemplatesClient::OnGetAllTemplates,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void DesksClient::LaunchDeskTemplate(const std::string& template_uuid,
-                                     LaunchDeskTemplateCallback callback) {
+void DesksTemplatesClient::LaunchDeskTemplate(
+    const std::string& template_uuid,
+    LaunchDeskTemplateCallback callback) {
   if (!active_profile_) {
     std::move(callback).Run(std::string(kNoCurrentUserError));
     return;
@@ -166,11 +173,11 @@
 
   GetDeskModel()->GetEntryByUUID(
       template_uuid,
-      base::BindOnce(&DesksClient::OnGetTemplateForDeskLaunch,
+      base::BindOnce(&DesksTemplatesClient::OnGetTemplateForDeskLaunch,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void DesksClient::LaunchAppsFromTemplate(
+void DesksTemplatesClient::LaunchAppsFromTemplate(
     std::unique_ptr<ash::DeskTemplate> desk_template) {
   DCHECK(desk_template);
   const app_restore::RestoreData* restore_data =
@@ -185,7 +192,7 @@
   RecordLaunchFromTemplateHistogram();
 }
 
-desks_storage::DeskModel* DesksClient::GetDeskModel() {
+desks_storage::DeskModel* DesksTemplatesClient::GetDeskModel() {
   if (chromeos::features::IsDeskTemplateSyncEnabled()) {
     return DeskSyncServiceFactory::GetForProfile(active_profile_)
         ->GetDeskModel();
@@ -197,7 +204,7 @@
 
 // Sets the preconfigured desk template.  Data contains the contents of the JSON
 // file with the template information
-void DesksClient::SetPolicyPreconfiguredTemplate(
+void DesksTemplatesClient::SetPolicyPreconfiguredTemplate(
     const AccountId& account_id,
     std::unique_ptr<std::string> data) {
   Profile* profile =
@@ -215,12 +222,12 @@
     GetDeskModel()->SetPolicyDeskTemplates(*data);
 }
 
-void DesksClient::RemovePolicyPreconfiguredTemplate(
+void DesksTemplatesClient::RemovePolicyPreconfiguredTemplate(
     const AccountId& account_id) {
   preconfigured_desk_templates_json_.erase(account_id);
 }
 
-void DesksClient::MaybeCreateAppLaunchHandler() {
+void DesksTemplatesClient::MaybeCreateAppLaunchHandler() {
   if (app_launch_handler_ &&
       app_launch_handler_->profile() == active_profile_) {
     return;
@@ -228,10 +235,10 @@
 
   DCHECK(active_profile_);
   app_launch_handler_ =
-      std::make_unique<DeskTemplateAppLaunchHandler>(active_profile_);
+      std::make_unique<DesksTemplatesAppLaunchHandler>(active_profile_);
 }
 
-void DesksClient::RecordWindowAndTabCountHistogram(
+void DesksTemplatesClient::RecordWindowAndTabCountHistogram(
     ash::DeskTemplate* desk_template) {
   const app_restore::RestoreData* restore_data =
       desk_template->desk_restore_data();
@@ -267,17 +274,17 @@
   base::UmaHistogramCounts100(kWindowAndTabCountHistogramName, total_count);
 }
 
-void DesksClient::RecordLaunchFromTemplateHistogram() {
+void DesksTemplatesClient::RecordLaunchFromTemplateHistogram() {
   base::UmaHistogramBoolean(kLaunchFromTemplateHistogramName, true);
 }
 
-void DesksClient::RecordTemplateCountHistogram() {
+void DesksTemplatesClient::RecordTemplateCountHistogram() {
   UMA_HISTOGRAM_EXACT_LINEAR(kUserTemplateCountHistogramName,
                              GetDeskModel()->GetEntryCount(),
                              GetDeskModel()->GetMaxEntryCount());
 }
 
-void DesksClient::OnGetTemplateForDeskLaunch(
+void DesksTemplatesClient::OnGetTemplateForDeskLaunch(
     LaunchDeskTemplateCallback callback,
     desks_storage::DeskModel::GetEntryByUuidStatus status,
     std::unique_ptr<ash::DeskTemplate> entry) {
@@ -289,12 +296,13 @@
   // Launch the windows as specified in the template to a new desk.
   const auto template_name = entry->template_name();
   desks_controller_->CreateAndActivateNewDeskForTemplate(
-      template_name, base::BindOnce(&DesksClient::OnCreateAndActivateNewDesk,
-                                    weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(entry), std::move(callback)));
+      template_name,
+      base::BindOnce(&DesksTemplatesClient::OnCreateAndActivateNewDesk,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(entry),
+                     std::move(callback)));
 }
 
-void DesksClient::OnCreateAndActivateNewDesk(
+void DesksTemplatesClient::OnCreateAndActivateNewDesk(
     std::unique_ptr<ash::DeskTemplate> desk_template,
     LaunchDeskTemplateCallback callback,
     bool on_create_activate_success) {
@@ -314,8 +322,8 @@
   std::move(callback).Run(std::string(""));
 }
 
-void DesksClient::OnCaptureActiveDeskAndSaveTemplate(
-    DesksClient::CaptureActiveDeskAndSaveTemplateCallback callback,
+void DesksTemplatesClient::OnCaptureActiveDeskAndSaveTemplate(
+    DesksTemplatesClient::CaptureActiveDeskAndSaveTemplateCallback callback,
     std::unique_ptr<ash::DeskTemplate> desk_template,
     desks_storage::DeskModel::AddOrUpdateEntryStatus status) {
   std::move(callback).Run(
@@ -328,8 +336,8 @@
   RecordTemplateCountHistogram();
 }
 
-void DesksClient::OnDeleteDeskTemplate(
-    DesksClient::DeleteDeskTemplateCallback callback,
+void DesksTemplatesClient::OnDeleteDeskTemplate(
+    DesksTemplatesClient::DeleteDeskTemplateCallback callback,
     desks_storage::DeskModel::DeleteEntryStatus status) {
   std::move(callback).Run(
       std::string(status != desks_storage::DeskModel::DeleteEntryStatus::kOk
@@ -338,8 +346,8 @@
   RecordTemplateCountHistogram();
 }
 
-void DesksClient::OnUpdateDeskTemplate(
-    DesksClient::UpdateDeskTemplateCallback callback,
+void DesksTemplatesClient::OnUpdateDeskTemplate(
+    DesksTemplatesClient::UpdateDeskTemplateCallback callback,
     desks_storage::DeskModel::AddOrUpdateEntryStatus status) {
   std::move(callback).Run(std::string(
       status != desks_storage::DeskModel::AddOrUpdateEntryStatus::kOk
@@ -347,9 +355,9 @@
           : ""));
 }
 
-void DesksClient::OnGetTemplateToBeUpdated(
+void DesksTemplatesClient::OnGetTemplateToBeUpdated(
     const std::u16string& template_name,
-    DesksClient::UpdateDeskTemplateCallback callback,
+    DesksTemplatesClient::UpdateDeskTemplateCallback callback,
     desks_storage::DeskModel::GetEntryByUuidStatus status,
     std::unique_ptr<ash::DeskTemplate> entry) {
   if (status != desks_storage::DeskModel::GetEntryByUuidStatus::kOk) {
@@ -360,12 +368,12 @@
   entry->set_template_name(template_name);
   GetDeskModel()->AddOrUpdateEntry(
       std::move(entry),
-      base::BindOnce(&DesksClient::OnUpdateDeskTemplate,
+      base::BindOnce(&DesksTemplatesClient::OnUpdateDeskTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void DesksClient::OnGetAllTemplates(
-    DesksClient::GetDeskTemplatesCallback callback,
+void DesksTemplatesClient::OnGetAllTemplates(
+    GetDeskTemplatesCallback callback,
     desks_storage::DeskModel::GetAllEntriesStatus status,
     std::vector<ash::DeskTemplate*> entries) {
   std::move(callback).Run(
@@ -375,7 +383,7 @@
                       : ""));
 }
 
-void DesksClient::OnCapturedDeskTemplate(
+void DesksTemplatesClient::OnCapturedDeskTemplate(
     CaptureActiveDeskAndSaveTemplateCallback callback,
     std::unique_ptr<ash::DeskTemplate> desk_template) {
   if (!desk_template)
@@ -385,7 +393,7 @@
   auto desk_template_clone = desk_template->Clone();
   GetDeskModel()->AddOrUpdateEntry(
       std::move(desk_template_clone),
-      base::BindOnce(&DesksClient::OnCaptureActiveDeskAndSaveTemplate,
+      base::BindOnce(&DesksTemplatesClient::OnCaptureActiveDeskAndSaveTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                      std::move(desk_template)));
 }
diff --git a/chrome/browser/ui/ash/desks_client.h b/chrome/browser/ui/ash/desks_templates/desks_templates_client.h
similarity index 84%
rename from chrome/browser/ui/ash/desks_client.h
rename to chrome/browser/ui/ash/desks_templates/desks_templates_client.h
index a187ddd..95be144 100644
--- a/chrome/browser/ui/ash/desks_client.h
+++ b/chrome/browser/ui/ash/desks_templates/desks_templates_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 CHROME_BROWSER_UI_ASH_DESKS_CLIENT_H_
-#define CHROME_BROWSER_UI_ASH_DESKS_CLIENT_H_
+#ifndef CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_DESKS_TEMPLATES_CLIENT_H_
+#define CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_DESKS_TEMPLATES_CLIENT_H_
 
 #include <memory>
 
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/desks_storage/core/desk_model.h"
 
-class DeskTemplateAppLaunchHandler;
+class DesksTemplatesAppLaunchHandler;
 
 namespace ash {
 class DeskTemplate;
@@ -24,27 +24,27 @@
 namespace desks_storage {
 class DeskModel;
 class LocalDeskDataManager;
-}
+}  // namespace desks_storage
 
 class Profile;
 
 // Class to handle all Desks in-browser functionalities. Will call into
 // ash::DesksController to do actual desk related operations.
-class DesksClient : public ash::SessionObserver {
+class DesksTemplatesClient : public ash::SessionObserver {
  public:
-  DesksClient();
-  DesksClient(const DesksClient&) = delete;
-  DesksClient& operator=(const DesksClient&) = delete;
-  ~DesksClient() override;
+  DesksTemplatesClient();
+  DesksTemplatesClient(const DesksTemplatesClient&) = delete;
+  DesksTemplatesClient& operator=(const DesksTemplatesClient&) = delete;
+  ~DesksTemplatesClient() override;
 
-  static DesksClient* Get();
+  static DesksTemplatesClient* Get();
 
   // ash::SessionObserver:
   void OnActiveUserSessionChanged(const AccountId& account_id) override;
 
   // TODO: Change the callback to accept a ash::DeskTemplate* type parameter
-  // later when DesksClient (or DesksController) hooks up with storage and can
-  // hold an in-memory captured desk template instance.
+  // later when DesksTemplatesClient (or DesksController) hooks up with storage
+  // and can hold an in-memory captured desk template instance.
   using CaptureActiveDeskAndSaveTemplateCallback =
       base::OnceCallback<void(std::unique_ptr<ash::DeskTemplate>,
                               std::string error)>;
@@ -107,8 +107,8 @@
   void RemovePolicyPreconfiguredTemplate(const AccountId& account_id);
 
  private:
-  friend class DesksClientTest;
-  friend class ScopedDeskClientAppLaunchHandlerSetter;
+  friend class DesksTemplatesClientTest;
+  friend class ScopedDesksTemplatesAppLaunchHandlerSetter;
 
   // Attempts to create `app_launch_handler_` if it doesn't already exist.
   void MaybeCreateAppLaunchHandler();
@@ -133,32 +133,32 @@
   // Callback function that allows the |CaptureActiveDeskAndSaveTemplate|
   // |callback| to be called as a |desks_storage::AddOrUpdateEntryCallback|.
   void OnCaptureActiveDeskAndSaveTemplate(
-      DesksClient::CaptureActiveDeskAndSaveTemplateCallback callback,
+      CaptureActiveDeskAndSaveTemplateCallback callback,
       std::unique_ptr<ash::DeskTemplate> desk_template,
       desks_storage::DeskModel::AddOrUpdateEntryStatus status);
 
   // Callback function that allows for the |DeleteDeskTemplateCallback| to be
   // called as a |desks_storage::DeleteEntryCallback|
-  void OnDeleteDeskTemplate(DesksClient::DeleteDeskTemplateCallback callback,
+  void OnDeleteDeskTemplate(DeleteDeskTemplateCallback callback,
                             desks_storage::DeskModel::DeleteEntryStatus status);
 
   // Callback function that allows the |UpdateDeskTemplateCallback| to be called
   // as a |desks_storage::AddOrUpdateEntryCallback|.
   void OnUpdateDeskTemplate(
-      DesksClient::UpdateDeskTemplateCallback callback,
+      UpdateDeskTemplateCallback callback,
       desks_storage::DeskModel::AddOrUpdateEntryStatus status);
 
   // Callback function that handles finding a template to be updated in
   // |UpdateDeskTemplate|
   void OnGetTemplateToBeUpdated(
       const std::u16string& template_name,
-      DesksClient::UpdateDeskTemplateCallback callback,
+      UpdateDeskTemplateCallback callback,
       desks_storage::DeskModel::GetEntryByUuidStatus status,
       std::unique_ptr<ash::DeskTemplate> entry);
 
   // Callback function that handles getting all DeskTemplates from
   // storage.
-  void OnGetAllTemplates(DesksClient::GetDeskTemplatesCallback callback,
+  void OnGetAllTemplates(GetDeskTemplatesCallback callback,
                          desks_storage::DeskModel::GetAllEntriesStatus status,
                          std::vector<ash::DeskTemplate*> entries);
 
@@ -175,7 +175,7 @@
   Profile* active_profile_ = nullptr;
 
   // The object that handles launching apps.
-  std::unique_ptr<DeskTemplateAppLaunchHandler> app_launch_handler_;
+  std::unique_ptr<DesksTemplatesAppLaunchHandler> app_launch_handler_;
 
   // A test only template for testing `LaunchDeskTemplate`.
   std::unique_ptr<ash::DeskTemplate> launch_template_for_test_;
@@ -186,7 +186,7 @@
   // The stored JSON values of preconfigured desk templates
   base::flat_map<AccountId, std::string> preconfigured_desk_templates_json_;
 
-  base::WeakPtrFactory<DesksClient> weak_ptr_factory_{this};
+  base::WeakPtrFactory<DesksTemplatesClient> weak_ptr_factory_{this};
 };
 
-#endif  // CHROME_BROWSER_UI_ASH_DESKS_CLIENT_H_
+#endif  // CHROME_BROWSER_UI_ASH_DESKS_TEMPLATES_DESKS_TEMPLATES_CLIENT_H_
diff --git a/chrome/browser/ui/ash/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc
similarity index 89%
rename from chrome/browser/ui/ash/desks_client_browsertest.cc
rename to chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc
index b5fa1d78..b625230 100644
--- a/chrome/browser/ui/ash/desks_client_browsertest.cc
+++ b/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.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/ui/ash/desks_client.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_client.h"
 
 #include <cstdint>
 #include <cstdlib>
@@ -33,7 +33,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_keep_alive_types.h"
 #include "chrome/browser/profiles/scoped_profile_keep_alive.h"
-#include "chrome/browser/ui/ash/desk_template_app_launch_handler.h"
+#include "chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -103,7 +103,7 @@
 std::unique_ptr<ash::DeskTemplate> CaptureActiveDeskAndSaveTemplate() {
   base::RunLoop run_loop;
   std::unique_ptr<ash::DeskTemplate> desk_template;
-  DesksClient::Get()->CaptureActiveDeskAndSaveTemplate(
+  DesksTemplatesClient::Get()->CaptureActiveDeskAndSaveTemplate(
       base::BindLambdaForTesting(
           [&](std::unique_ptr<ash::DeskTemplate> captured_desk_template,
               std::string error_string) {
@@ -117,7 +117,7 @@
 
 void DeleteDeskTemplate(const base::GUID uuid) {
   base::RunLoop run_loop;
-  DesksClient::Get()->DeleteDeskTemplate(
+  DesksTemplatesClient::Get()->DeleteDeskTemplate(
       uuid.AsLowercaseString(),
       base::BindLambdaForTesting(
           [&](std::string error_string) { run_loop.Quit(); }));
@@ -151,15 +151,16 @@
   event_generator.ClickLeftButton();
 }
 
-class MockDeskTemplateAppLaunchHandler : public DeskTemplateAppLaunchHandler {
+class MockDesksTemplatesAppLaunchHandler
+    : public DesksTemplatesAppLaunchHandler {
  public:
-  explicit MockDeskTemplateAppLaunchHandler(Profile* profile)
-      : DeskTemplateAppLaunchHandler(profile) {}
-  MockDeskTemplateAppLaunchHandler(const MockDeskTemplateAppLaunchHandler&) =
-      delete;
-  MockDeskTemplateAppLaunchHandler& operator=(
-      const MockDeskTemplateAppLaunchHandler&) = delete;
-  ~MockDeskTemplateAppLaunchHandler() override = default;
+  explicit MockDesksTemplatesAppLaunchHandler(Profile* profile)
+      : DesksTemplatesAppLaunchHandler(profile) {}
+  MockDesksTemplatesAppLaunchHandler(
+      const MockDesksTemplatesAppLaunchHandler&) = delete;
+  MockDesksTemplatesAppLaunchHandler& operator=(
+      const MockDesksTemplatesAppLaunchHandler&) = delete;
+  ~MockDesksTemplatesAppLaunchHandler() override = default;
 
   MOCK_METHOD(void,
               LaunchSystemWebAppOrChromeApp,
@@ -173,27 +174,27 @@
 
 // Scoped class that temporarily sets a new app launch handler for testing
 // purposes.
-class ScopedDeskClientAppLaunchHandlerSetter {
+class ScopedDesksTemplatesAppLaunchHandlerSetter {
  public:
-  explicit ScopedDeskClientAppLaunchHandlerSetter(
-      std::unique_ptr<DeskTemplateAppLaunchHandler> launch_handler) {
+  explicit ScopedDesksTemplatesAppLaunchHandlerSetter(
+      std::unique_ptr<DesksTemplatesAppLaunchHandler> launch_handler) {
     DCHECK_EQ(0, instance_count_);
     ++instance_count_;
 
-    DesksClient* desks_client = DesksClient::Get();
+    DesksTemplatesClient* desks_client = DesksTemplatesClient::Get();
     DCHECK(desks_client);
     old_app_launch_handler_ = std::move(desks_client->app_launch_handler_);
     desks_client->app_launch_handler_ = std::move(launch_handler);
   }
-  ScopedDeskClientAppLaunchHandlerSetter(
-      const ScopedDeskClientAppLaunchHandlerSetter&) = delete;
-  ScopedDeskClientAppLaunchHandlerSetter& operator=(
-      const ScopedDeskClientAppLaunchHandlerSetter&) = delete;
-  ~ScopedDeskClientAppLaunchHandlerSetter() {
+  ScopedDesksTemplatesAppLaunchHandlerSetter(
+      const ScopedDesksTemplatesAppLaunchHandlerSetter&) = delete;
+  ScopedDesksTemplatesAppLaunchHandlerSetter& operator=(
+      const ScopedDesksTemplatesAppLaunchHandlerSetter&) = delete;
+  ~ScopedDesksTemplatesAppLaunchHandlerSetter() {
     DCHECK_EQ(1, instance_count_);
     --instance_count_;
 
-    DesksClient* desks_client = DesksClient::Get();
+    DesksTemplatesClient* desks_client = DesksTemplatesClient::Get();
     DCHECK(desks_client);
     desks_client->app_launch_handler_ = std::move(old_app_launch_handler_);
   }
@@ -204,21 +205,21 @@
 
   // The old app launch handler prior to the object being created. May be
   // nullptr.
-  std::unique_ptr<DeskTemplateAppLaunchHandler> old_app_launch_handler_;
+  std::unique_ptr<DesksTemplatesAppLaunchHandler> old_app_launch_handler_;
 };
 
-int ScopedDeskClientAppLaunchHandlerSetter::instance_count_ = 0;
+int ScopedDesksTemplatesAppLaunchHandlerSetter::instance_count_ = 0;
 
-class DesksClientTest : public extensions::PlatformAppBrowserTest {
+class DesksTemplatesClientTest : public extensions::PlatformAppBrowserTest {
  public:
-  DesksClientTest() {
+  DesksTemplatesClientTest() {
     // This feature depends on full restore feature, so need to enable it.
     scoped_feature_list_.InitWithFeatures(
         /*enabled_features=*/{full_restore::features::kFullRestore,
                               ash::features::kDesksTemplates},
         /*disabled_features=*/{});
   }
-  ~DesksClientTest() override = default;
+  ~DesksTemplatesClientTest() override = default;
 
   void SetUpOnMainThread() override {
     ::full_restore::SetActiveProfilePath(profile()->GetPath());
@@ -226,13 +227,14 @@
   }
 
   void SetTemplate(std::unique_ptr<ash::DeskTemplate> launch_template) {
-    DesksClient::Get()->launch_template_for_test_ = std::move(launch_template);
+    DesksTemplatesClient::Get()->launch_template_for_test_ =
+        std::move(launch_template);
   }
 
   void LaunchTemplate(const base::GUID& uuid) {
     ash::DeskSwitchAnimationWaiter waiter;
-    DesksClient::Get()->LaunchDeskTemplate(uuid.AsLowercaseString(),
-                                           base::DoNothing());
+    DesksTemplatesClient::Get()->LaunchDeskTemplate(uuid.AsLowercaseString(),
+                                                    base::DoNothing());
     waiter.Wait();
   }
 
@@ -280,7 +282,7 @@
 };
 
 // Tests that a browser's urls can be captured correctly in the desk template.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, CaptureBrowserUrlsTest) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, CaptureBrowserUrlsTest) {
   // Create a new browser and add a few tabs to it.
   Browser* browser = CreateBrowser({GURL(kExampleUrl1), GURL(kExampleUrl2)});
   aura::Window* window = browser->window()->GetNativeWindow();
@@ -309,7 +311,7 @@
 
 // Tests that incognito browser windows will NOT be captured in the desk
 // template.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, CaptureIncognitoBrowserTest) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, CaptureIncognitoBrowserTest) {
   Browser* incognito_browser = CreateIncognitoBrowser();
   chrome::AddTabAt(incognito_browser, GURL(kExampleUrl1), /*index=*/-1,
                    /*foreground=*/true);
@@ -339,9 +341,10 @@
 
 // Tests that browsers and chrome apps can be captured correctly in the desk
 // template.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, CaptureActiveDeskAsTemplateTest) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       CaptureActiveDeskAsTemplateTest) {
   // Test that Singleton was properly initialized.
-  ASSERT_TRUE(DesksClient::Get());
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   // Change |browser|'s bounds.
   const gfx::Rect browser_bounds = gfx::Rect(0, 0, 800, 200);
@@ -422,7 +425,7 @@
 }
 
 // Tests that launching a desk template creates a desk with the given name.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchEmptyDeskTemplate) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, LaunchEmptyDeskTemplate) {
   const base::GUID kDeskUuid = base::GUID::GenerateRandomV4();
   const std::u16string kDeskName(u"Test Desk Name");
 
@@ -452,7 +455,8 @@
 
 // Tests that launching the same desk template multiple times creates desks with
 // different/incremented names.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchMultipleEmptyDeskTemplates) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       LaunchMultipleEmptyDeskTemplates) {
   const base::GUID kDeskUuid = base::GUID::GenerateRandomV4();
   const std::u16string kDeskName(u"Test Desk Name");
 
@@ -499,8 +503,8 @@
 
 // Tests that launching a template that contains a system web app works as
 // expected.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchTemplateWithSystemApp) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, LaunchTemplateWithSystemApp) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   // Create the settings app, which is a system web app.
   CreateSettingsSystemWebApp(browser()->profile());
@@ -544,8 +548,9 @@
 
 // Tests that launching a template that contains a system web app will move the
 // existing instance of the system web app to the current desk.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchTemplateWithSystemAppExisting) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       LaunchTemplateWithSystemAppExisting) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
   Profile* profile = browser()->profile();
 
   // Create the settings app, which is a system web app.
@@ -587,8 +592,8 @@
 }
 
 // Tests that launching a template that contains a chrome app works as expected.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchTemplateWithChromeApp) {
-  DesksClient* desks_client = DesksClient::Get();
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, LaunchTemplateWithChromeApp) {
+  DesksTemplatesClient* desks_client = DesksTemplatesClient::Get();
   ASSERT_TRUE(desks_client);
 
   // Create a chrome app.
@@ -627,10 +632,10 @@
   // `LaunchSystemWebAppOrChromeApp()` call with the associated extension is
   // seen.
   auto mock_app_launch_handler =
-      std::make_unique<MockDeskTemplateAppLaunchHandler>(profile());
-  MockDeskTemplateAppLaunchHandler* mock_app_launch_handler_ptr =
+      std::make_unique<MockDesksTemplatesAppLaunchHandler>(profile());
+  MockDesksTemplatesAppLaunchHandler* mock_app_launch_handler_ptr =
       mock_app_launch_handler.get();
-  ScopedDeskClientAppLaunchHandlerSetter scoped_launch_handler(
+  ScopedDesksTemplatesAppLaunchHandlerSetter scoped_launch_handler(
       std::move(mock_app_launch_handler));
 
   EXPECT_CALL(*mock_app_launch_handler_ptr,
@@ -642,8 +647,9 @@
 
 // Tests that launching a template that contains a browser window works as
 // expected.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchTemplateWithBrowserWindow) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       LaunchTemplateWithBrowserWindow) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   // Create a new browser and add a few tabs to it, and specify the active tab
   // index.
@@ -689,8 +695,9 @@
 
 // Tests that browser session restore isn't triggered when we launch a template
 // that contains a browser window.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, PreventBrowserSessionRestoreTest) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       PreventBrowserSessionRestoreTest) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   // Do not exit from test or delete the Profile* when last browser is closed.
   ScopedKeepAlive keep_alive(KeepAliveOrigin::BROWSER,
@@ -731,9 +738,9 @@
 }
 
 // Tests that the windows and tabs count histogram is recorded properly.
-IN_PROC_BROWSER_TEST_F(DesksClientTest,
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
                        DeskTemplateWindowAndTabCountHistogram) {
-  ASSERT_TRUE(DesksClient::Get());
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   base::HistogramTester histogram_tester;
 
@@ -765,9 +772,9 @@
 }
 
 // Tests that the launch from template histogram is recorded properly.
-IN_PROC_BROWSER_TEST_F(DesksClientTest,
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
                        DeskTemplateLaunchFromTemplateHistogram) {
-  ASSERT_TRUE(DesksClient::Get());
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   base::HistogramTester histogram_tester;
 
@@ -793,9 +800,9 @@
 }
 
 // Tests that the template count histogram is recorded properly.
-IN_PROC_BROWSER_TEST_F(DesksClientTest,
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
                        DeskTemplateUserTemplateCountHistogram) {
-  ASSERT_TRUE(DesksClient::Get());
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   base::HistogramTester histogram_tester;
 
@@ -816,8 +823,8 @@
 
 // Tests that browser windows created from a template have the correct bounds
 // and window state.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, BrowserWindowRestorationTest) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, BrowserWindowRestorationTest) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   // Create a new browser and set its bounds.
   Browser* browser_1 = CreateBrowser({GURL(kExampleUrl1), GURL(kExampleUrl2)});
@@ -878,8 +885,8 @@
 
 // Tests that saving and launching a template that contains a PWA works as
 // expected.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchTemplateWithPWA) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, LaunchTemplateWithPWA) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   Browser* pwa_browser =
       InstallAndLaunchPWA(GURL(kExampleUrl1), /*launch_in_browser=*/false);
@@ -933,8 +940,9 @@
 
 // Tests that saving and launching a template that contains a PWA in a browser
 // window works as expected.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, LaunchTemplateWithPWAInBrowser) {
-  ASSERT_TRUE(DesksClient::Get());
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       LaunchTemplateWithPWAInBrowser) {
+  ASSERT_TRUE(DesksTemplatesClient::Get());
 
   Browser* pwa_browser =
       InstallAndLaunchPWA(GURL(kYoutubeUrl), /*launch_in_browser=*/true);
@@ -965,7 +973,7 @@
 }
 
 // Tests that basic operations using the native UI work as expected.
-IN_PROC_BROWSER_TEST_F(DesksClientTest, NativeUIBasic) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, NativeUIBasic) {
   ash::ToggleOverview();
   ash::WaitForOverviewEnterAnimation();
 
@@ -998,9 +1006,10 @@
 
   // TODO(richui): Add tests for launching and deleting.
 }
-class DesksClientMultiProfileTest : public ash::LoginManagerTest {
+
+class DesksTemplatesClientMultiProfileTest : public ash::LoginManagerTest {
  public:
-  DesksClientMultiProfileTest() : ash::LoginManagerTest() {
+  DesksTemplatesClientMultiProfileTest() : ash::LoginManagerTest() {
     login_mixin_.AppendRegularUsers(2);
     account_id1_ = login_mixin_.users()[0].account_id;
     account_id2_ = login_mixin_.users()[1].account_id;
@@ -1009,7 +1018,7 @@
     scoped_feature_list_.InitAndEnableFeature(
         full_restore::features::kFullRestore);
   }
-  ~DesksClientMultiProfileTest() override = default;
+  ~DesksTemplatesClientMultiProfileTest() override = default;
 
   void SetUpOnMainThread() override {
     ash::LoginManagerTest::SetUpOnMainThread();
@@ -1028,7 +1037,7 @@
   AccountId account_id2_;
 };
 
-IN_PROC_BROWSER_TEST_F(DesksClientMultiProfileTest, MultiProfileTest) {
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientMultiProfileTest, MultiProfileTest) {
   CreateBrowser(
       chromeos::ProfileHelper::Get()->GetProfileByAccountId(account_id1_));
   // Capture the active desk, which contains the browser windows.
@@ -1042,7 +1051,7 @@
   auto get_templates_size = []() {
     base::RunLoop run_loop;
     int templates_num = 0;
-    DesksClient::Get()->GetDeskTemplates(base::BindLambdaForTesting(
+    DesksTemplatesClient::Get()->GetDeskTemplates(base::BindLambdaForTesting(
         [&](const std::vector<ash::DeskTemplate*>& desk_templates,
             std::string error_string) {
           templates_num = desk_templates.size();
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc
index 1bff31d..eb2bce52 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.cc
@@ -7,6 +7,8 @@
 #include <set>
 #include <string>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/holding_space/holding_space_constants.h"
 #include "ash/public/cpp/holding_space/holding_space_item.h"
 #include "ash/public/cpp/holding_space/holding_space_model.h"
@@ -23,8 +25,6 @@
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/chromeos/fileapi/file_change_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.h b/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.h
index 902405fd..5b7eb80e 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.h
+++ b/chrome/browser/ui/ash/holding_space/holding_space_file_system_delegate.h
@@ -8,6 +8,8 @@
 #include <memory>
 #include <vector>
 
+#include "ash/components/arc/session/connection_holder.h"
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/components/drivefs/drivefs_host_observer.h"
 #include "base/callback.h"
 #include "base/scoped_observation.h"
@@ -19,8 +21,6 @@
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_util.h"
 #include "components/arc/mojom/file_system.mojom-forward.h"
-#include "components/arc/session/connection_holder.h"
-#include "components/arc/session/connection_observer.h"
 
 namespace base {
 class FilePath;
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
index 7656d8c..bd502222e 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/file_icon_util.h"
 #include "ash/public/cpp/holding_space/holding_space_constants.h"
@@ -46,7 +47,6 @@
 #include "chromeos/disks/disk_mount_manager.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync_preferences/pref_service_mock_factory.h"
 #include "components/sync_preferences/pref_service_syncable.h"
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
index 049baef..ea19bad 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h"
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/new_window_delegate.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc
index a69e3aa4..3c5ac19 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h"
 
-#include "ash/constants/ash_features.h"
 #include "chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h"
 #include "chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h"
 #include "chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.h"
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
index d1a2973..d14381f9 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
@@ -5,6 +5,8 @@
 #include <memory>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "ash/constants/ash_features.h"
@@ -40,8 +42,6 @@
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_application_info.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/services/app_service/public/cpp/instance.h"
 #include "components/services/app_service/public/cpp/instance_registry.h"
@@ -213,39 +213,40 @@
 IN_PROC_BROWSER_TEST_F(AppServiceAppWindowBrowserTest, ExtensionAppsWindow) {
   const extensions::Extension* app =
       LoadAndLaunchPlatformApp("launch", "Launched");
-  extensions::AppWindow* window = CreateAppWindow(profile(), app);
-  ASSERT_TRUE(window);
+  extensions::AppWindow* app_window = CreateAppWindow(profile(), app);
+  ASSERT_TRUE(app_window);
 
-  auto windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app->id());
-  EXPECT_EQ(1u, windows.size());
+  auto instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app->id());
+  EXPECT_EQ(1u, instance_keys.size());
+  auto* window = instance_keys.begin()->Window();
 
-  EXPECT_EQ(apps::InstanceState::kStarted | apps::InstanceState::kRunning |
-                apps::InstanceState::kActive | apps::InstanceState::kVisible,
-            GetAppInstanceState(app->id(),
-                                apps::Instance::InstanceKey::ForWindowBasedApp(
-                                    *windows.begin())));
+  EXPECT_EQ(
+      apps::InstanceState::kStarted | apps::InstanceState::kRunning |
+          apps::InstanceState::kActive | apps::InstanceState::kVisible,
+      GetAppInstanceState(
+          app->id(), apps::Instance::InstanceKey::ForWindowBasedApp(window)));
 
   const ash::ShelfItem& item = GetLastShelfItem();
   // Since it is already active, clicking it should minimize.
   SelectItem(item.id);
-  EXPECT_EQ(apps::InstanceState::kStarted | apps::InstanceState::kRunning,
-            GetAppInstanceState(app->id(),
-                                apps::Instance::InstanceKey::ForWindowBasedApp(
-                                    *windows.begin())));
+  EXPECT_EQ(
+      apps::InstanceState::kStarted | apps::InstanceState::kRunning,
+      GetAppInstanceState(
+          app->id(), apps::Instance::InstanceKey::ForWindowBasedApp(window)));
 
   // Click the item again to activate the app.
   SelectItem(item.id);
-  EXPECT_EQ(apps::InstanceState::kStarted | apps::InstanceState::kRunning |
-                apps::InstanceState::kActive | apps::InstanceState::kVisible,
-            GetAppInstanceState(app->id(),
-                                apps::Instance::InstanceKey::ForWindowBasedApp(
-                                    *windows.begin())));
+  EXPECT_EQ(
+      apps::InstanceState::kStarted | apps::InstanceState::kRunning |
+          apps::InstanceState::kActive | apps::InstanceState::kVisible,
+      GetAppInstanceState(
+          app->id(), apps::Instance::InstanceKey::ForWindowBasedApp(window)));
 
-  CloseAppWindow(window);
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app->id());
-  EXPECT_EQ(0u, windows.size());
+  CloseAppWindow(app_window);
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app->id());
+  EXPECT_EQ(0u, instance_keys.size());
 }
 
 // Test that we have the correct instances with more than one window.
@@ -254,20 +255,21 @@
       LoadAndLaunchPlatformApp("launch", "Launched");
   extensions::AppWindow* app_window1 = CreateAppWindow(profile(), app);
 
-  auto windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app->id());
-  auto* window1 = *windows.begin();
+  auto instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app->id());
+  auto* window1 = instance_keys.begin()->Window();
 
   // Add a second window; confirm the shelf item stays; check the app menu.
   extensions::AppWindow* app_window2 = CreateAppWindow(profile(), app);
 
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app->id());
-  EXPECT_EQ(2u, windows.size());
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app->id());
+  EXPECT_EQ(2u, instance_keys.size());
   aura::Window* window2 = nullptr;
-  for (auto* window : windows) {
-    if (window != window1)
-      window2 = window;
+  for (auto& key : instance_keys) {
+    if (key.Window() != window1) {
+      window2 = key.Window();
+    }
   }
 
   // The window1 is inactive.
@@ -286,9 +288,9 @@
 
   // Close the second window; confirm the shelf item stays; check the app menu.
   CloseAppWindow(app_window2);
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app->id());
-  EXPECT_EQ(1u, windows.size());
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app->id());
+  EXPECT_EQ(1u, instance_keys.size());
 
   // The window1 is active again.
   EXPECT_EQ(
@@ -299,9 +301,9 @@
 
   // Close the first window; the shelf item should be removed.
   CloseAppWindow(app_window1);
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app->id());
-  EXPECT_EQ(0u, windows.size());
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app->id());
+  EXPECT_EQ(0u, instance_keys.size());
 }
 
 // Test that we have the correct instances with one HostedApp and one window.
@@ -394,16 +396,16 @@
   views::Widget* widget = CreateExoWindow("org.chromium.lacros.12345");
 
   using extension_misc::kLacrosAppId;
-  auto windows = app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(
-      kLacrosAppId);
-  EXPECT_EQ(1u, windows.size());
+  auto instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(kLacrosAppId);
+  EXPECT_EQ(1u, instance_keys.size());
   EXPECT_EQ(apps::InstanceState::kStarted | apps::InstanceState::kRunning |
                 apps::InstanceState::kActive | apps::InstanceState::kVisible,
             GetAppInstanceState(kLacrosAppId,
                                 apps::Instance::InstanceKey::ForWindowBasedApp(
-                                    *windows.begin())));
+                                    instance_keys.begin()->Window())));
 
-  auto instance_keys = app_service_proxy_->InstanceRegistry().GetInstanceKeys(
+  instance_keys = app_service_proxy_->InstanceRegistry().GetInstanceKeys(
       extension_misc::kLacrosAppId);
   EXPECT_EQ(1u, instance_keys.size());
   auto instance_key = *instance_keys.begin();
@@ -419,7 +421,7 @@
   EXPECT_EQ(apps::InstanceState::kStarted | apps::InstanceState::kRunning,
             GetAppInstanceState(kLacrosAppId,
                                 apps::Instance::InstanceKey::ForWindowBasedApp(
-                                    *windows.begin())));
+                                    instance_keys.begin()->Window())));
 
   // Click the item again to activate the window.
   SelectItem(item.id);
@@ -427,12 +429,12 @@
                 apps::InstanceState::kActive | apps::InstanceState::kVisible,
             GetAppInstanceState(kLacrosAppId,
                                 apps::Instance::InstanceKey::ForWindowBasedApp(
-                                    *windows.begin())));
+                                    instance_key.Window())));
 
   widget->CloseNow();
-  windows = app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(
-      kLacrosAppId);
-  EXPECT_EQ(0u, windows.size());
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(kLacrosAppId);
+  EXPECT_EQ(0u, instance_keys.size());
 }
 
 class AppServiceAppWindowBorealisBrowserTest
@@ -469,15 +471,14 @@
 
   views::Widget* widget = CreateExoWindow("org.chromium.borealis.wmclass.foo");
 
-  EXPECT_EQ(1u, app_service_proxy_->InstanceRegistry()
-                    .GetEnclosingAppWindows(app_id)
-                    .size());
+  EXPECT_EQ(
+      1u,
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id).size());
   EXPECT_NE(-1, shelf_model()->ItemIndexByAppID(app_id));
 
   widget->CloseNow();
-  EXPECT_TRUE(app_service_proxy_->InstanceRegistry()
-                  .GetEnclosingAppWindows(app_id)
-                  .empty());
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id).empty());
 }
 
 IN_PROC_BROWSER_TEST_F(AppServiceAppWindowBorealisBrowserTest,
@@ -485,9 +486,9 @@
   views::Widget* widget = CreateExoWindow("org.chromium.borealis.wmclass.bar");
   std::string app_id = "borealis_anon:org.chromium.borealis.wmclass.bar";
 
-  EXPECT_EQ(1u, app_service_proxy_->InstanceRegistry()
-                    .GetEnclosingAppWindows(app_id)
-                    .size());
+  EXPECT_EQ(
+      1u,
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id).size());
   ASSERT_NE(-1, shelf_model()->ItemIndexByAppID(app_id));
 
   // Initially, anonymous apps haven't been published, as that is an
@@ -508,9 +509,8 @@
                             .title));
 
   widget->CloseNow();
-  EXPECT_TRUE(app_service_proxy_->InstanceRegistry()
-                  .GetEnclosingAppWindows(app_id)
-                  .empty());
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id).empty());
 }
 
 IN_PROC_BROWSER_TEST_F(AppServiceAppWindowBorealisBrowserTest,
@@ -609,9 +609,8 @@
   controller_->Close(item.id);
   // Make sure that the window is closed.
   base::RunLoop().RunUntilIdle();
-  auto windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id);
-  EXPECT_EQ(0u, windows.size());
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id).empty());
 }
 
 // Tests that web app with multiple open windows can be activated from the app
@@ -779,10 +778,10 @@
   EXPECT_TRUE(controller_->GetItem(ash::ShelfID(app_id1)));
 
   // Check the window state in instance for app1
-  auto windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id1);
-  EXPECT_EQ(1u, windows.size());
-  aura::Window* window1 = *windows.begin();
+  auto instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id1);
+  EXPECT_EQ(1u, instance_keys.size());
+  aura::Window* window1 = instance_keys.begin()->Window();
   apps::InstanceState latest_state =
       app_service_proxy_->InstanceRegistry().GetState(
           apps::Instance::InstanceKey::ForWindowBasedApp(window1));
@@ -806,10 +805,10 @@
   EXPECT_TRUE(controller_->GetItem(ash::ShelfID(app_id2)));
 
   // Check the window state in instance for app2
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id2);
-  EXPECT_EQ(1u, windows.size());
-  aura::Window* window2 = *windows.begin();
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id2);
+  EXPECT_EQ(1u, instance_keys.size());
+  aura::Window* window2 = instance_keys.begin()->Window();
   latest_state = app_service_proxy_->InstanceRegistry().GetState(
       apps::Instance::InstanceKey::ForWindowBasedApp(window2));
   EXPECT_EQ(apps::InstanceState::kStarted | apps::InstanceState::kRunning |
@@ -839,9 +838,8 @@
   // Close the window for app1, and destroy the task.
   arc_window1->CloseNow();
   app_host()->OnTaskDestroyed(1);
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id1);
-  EXPECT_EQ(0u, windows.size());
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id1).empty());
 
   // App2 is activated.
   latest_state = app_service_proxy_->InstanceRegistry().GetState(
@@ -853,9 +851,8 @@
   // destroy the task for app2 and close the window.
   app_host()->OnTaskDestroyed(2);
   arc_window2->CloseNow();
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id2);
-  EXPECT_EQ(0u, windows.size());
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id2).empty());
 
   StopInstance();
 }
@@ -885,21 +882,24 @@
                             /*session_id=*/0);
 
   // Both windows should show up in the instance registry.
-  auto windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id);
-  EXPECT_EQ(2u, windows.size());
+  auto instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id);
+  EXPECT_EQ(2u, instance_keys.size());
 
   // Of those two, one should be hidden.
-  auto is_hidden = [](aura::Window* w) {
-    return w->GetProperty(ash::kHideInShelfKey);
+  auto is_hidden = [](const apps::Instance::InstanceKey& key) {
+    return key.Window()->GetProperty(ash::kHideInShelfKey);
   };
-  EXPECT_EQ(1, std::count_if(windows.begin(), windows.end(), is_hidden));
+  EXPECT_EQ(
+      1, std::count_if(instance_keys.begin(), instance_keys.end(), is_hidden));
 
   // The hidden window should be task_id 2.
   aura::Window* window1 =
-      *(std::find_if_not(windows.begin(), windows.end(), is_hidden));
+      (std::find_if_not(instance_keys.begin(), instance_keys.end(), is_hidden))
+          ->Window();
   aura::Window* window2 =
-      *(std::find_if(windows.begin(), windows.end(), is_hidden));
+      (std::find_if(instance_keys.begin(), instance_keys.end(), is_hidden))
+          ->Window();
 
   apps::InstanceState latest_state =
       app_service_proxy_->InstanceRegistry().GetState(
@@ -924,17 +924,17 @@
   // Close first window. No window should be hidden anymore.
   arc_window1->CloseNow();
   app_host()->OnTaskDestroyed(1);
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id);
-  EXPECT_EQ(1u, windows.size());
-  EXPECT_EQ(0, std::count_if(windows.begin(), windows.end(), is_hidden));
+  instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id);
+  EXPECT_EQ(1u, instance_keys.size());
+  EXPECT_EQ(
+      0, std::count_if(instance_keys.begin(), instance_keys.end(), is_hidden));
 
   // Close second window.
   app_host()->OnTaskDestroyed(2);
   arc_window2->CloseNow();
-  windows =
-      app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(app_id);
-  EXPECT_EQ(0u, windows.size());
+  EXPECT_TRUE(
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(app_id).empty());
 }
 
 // Test what happens when ARC is used to launch a payment task for a PWA app,
@@ -960,22 +960,23 @@
   EXPECT_FALSE(controller_->GetItem(ash::ShelfID(payment_app_id)));
 
   // The payment window should still show up in the instance registry.
-  auto windows = app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(
-      payment_app_id);
-  EXPECT_EQ(1u, windows.size());
+  auto instance_keys =
+      app_service_proxy_->InstanceRegistry().GetInstanceKeys(payment_app_id);
+  EXPECT_EQ(1u, instance_keys.size());
 
   // The payment window should be hidden
-  auto is_hidden = [](aura::Window* w) {
-    return w->GetProperty(ash::kHideInShelfKey);
+  auto is_hidden = [](const apps::Instance::InstanceKey& key) {
+    return key.Window()->GetProperty(ash::kHideInShelfKey);
   };
-  EXPECT_EQ(1, std::count_if(windows.begin(), windows.end(), is_hidden));
+  EXPECT_EQ(
+      1, std::count_if(instance_keys.begin(), instance_keys.end(), is_hidden));
 
   // No windows should remain if we close the payment window
   payment_window->CloseNow();
   app_host()->OnTaskDestroyed(1);
-  windows = app_service_proxy_->InstanceRegistry().GetEnclosingAppWindows(
-      payment_app_id);
-  EXPECT_EQ(0u, windows.size());
+  EXPECT_TRUE(app_service_proxy_->InstanceRegistry()
+                  .GetInstanceKeys(payment_app_id)
+                  .empty());
 }
 
 class AppServiceAppWindowSystemWebAppBrowserTest
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc
index 34ee58c8..d69c75e9 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc
@@ -59,8 +59,8 @@
     content::WebContents* old_contents,
     content::WebContents* new_contents) {
   if (old_contents) {
-    auto instance_key = apps::Instance::InstanceKey::ForWebBasedApp(
-        old_contents->GetNativeView());
+    auto instance_key =
+        apps::Instance::InstanceKey(old_contents->GetNativeView());
 
     // Get the app_id from the existed instance first. If there is no record for
     // the window, get the app_id from contents. Because when Chrome app open
@@ -80,15 +80,14 @@
           apps::InstanceState::kUnknown) {
         state = static_cast<apps::InstanceState>(state &
                                                  ~apps::InstanceState::kActive);
-        OnInstances(GetInstanceKeyForWebContents(old_contents), app_id,
-                    std::string(), state);
+        OnInstances(apps::Instance::InstanceKey(GetWindow(old_contents)),
+                    app_id, std::string(), state);
       }
     }
   }
 
   if (new_contents) {
-    apps::Instance::InstanceKey instance_key =
-        GetInstanceKeyForWebContents(new_contents);
+    auto instance_key = apps::Instance::InstanceKey(GetWindow(new_contents));
 
     // Get the app_id from the existed instance first. If there is no record for
     // the window, get the app_id from contents. Because when Chrome app open
@@ -122,8 +121,7 @@
 void AppServiceInstanceRegistryHelper::OnTabInserted(
     content::WebContents* contents) {
   std::string app_id = GetAppId(contents);
-  apps::Instance::InstanceKey instance_key =
-      GetInstanceKeyForWebContents(contents);
+  auto instance_key = apps::Instance::InstanceKey(GetWindow(contents));
 
   // When the user drags a tab to a new browser, or to an other browser, it
   // could generate a temp instance for this window with the Chrome application
@@ -147,8 +145,7 @@
 
 void AppServiceInstanceRegistryHelper::OnTabClosing(
     content::WebContents* contents) {
-  apps::Instance::InstanceKey instance_key =
-      GetInstanceKeyForWebContents(contents);
+  auto instance_key = apps::Instance::InstanceKey(GetWindow(contents));
 
   // When the tab is closed, if the window does not exists in the AppService
   // InstanceRegistry, we don't need to update the status.
@@ -191,9 +188,6 @@
   instance->SetLaunchId(launch_id);
   instance->UpdateState(state, base::Time::Now());
 
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
-  deltas.push_back(std::move(instance));
-
   // The window could be teleported from the inactive user's profile to the
   // current active user, so search all proxies. If the instance is found from a
   // proxy, still save to that proxy, otherwise, save to the current active user
@@ -207,7 +201,7 @@
       break;
     }
   }
-  proxy->InstanceRegistry().OnInstances(std::move(deltas));
+  proxy->InstanceRegistry().OnInstance(std::move(instance));
 }
 
 void AppServiceInstanceRegistryHelper::OnSetShelfIDForBrowserWindowContents(
@@ -218,15 +212,14 @@
   if (browser_shutdown::HasShutdownStarted())
     return;
 
-  apps::Instance::InstanceKey instance_key =
-      GetInstanceKeyForWebContents(contents);
-  if (!instance_key.IsValid() || !instance_key.GetEnclosingAppWindow())
+  auto* window = GetWindow(contents);
+  if (!window || !window->GetToplevelWindow())
     return;
 
   // If the app id is changed, call OnTabInserted to remove the old app id in
   // AppService InstanceRegistry, and insert the new app id.
   std::string app_id = GetAppId(contents);
-  const std::string old_app_id = GetAppId(instance_key);
+  const std::string old_app_id = GetAppId(apps::Instance::InstanceKey(window));
   if (app_id != old_app_id)
     OnTabInserted(contents);
 
@@ -236,9 +229,8 @@
   // OnWindowActivated. Also web apps are ready at the very late phase which
   // delays the shelf id setting for windows. So check the top window's visible
   // and activated status when we have the shelf id.
-  aura::Window* window = instance_key.GetEnclosingAppWindow();
-  const std::string top_app_id =
-      GetAppId(apps::Instance::InstanceKey::ForWindowBasedApp(window));
+  window = window->GetToplevelWindow();
+  const std::string top_app_id = GetAppId(apps::Instance::InstanceKey(window));
   if (!top_app_id.empty()) {
     app_id = top_app_id;
   } else if (static_cast<ash::AppType>(window->GetProperty(
@@ -313,8 +305,7 @@
     // state for the tab window to keep one instance for the Web app.
     auto instance_keys = GetInstanceKeys(shelf_id.app_id);
     for (const apps::Instance::InstanceKey& instance_key_it : instance_keys) {
-      if (instance_key_it.GetEnclosingAppWindow()->GetToplevelWindow() !=
-          window) {
+      if (instance_key_it.Window()->GetToplevelWindow() != window) {
         continue;
       }
 
@@ -353,8 +344,7 @@
     apps::InstanceState state = static_cast<apps::InstanceState>(
         apps::InstanceState::kStarted | apps::InstanceState::kRunning |
         apps::InstanceState::kActive | apps::InstanceState::kVisible);
-    apps::Instance::InstanceKey contents_instance_key =
-        GetInstanceKeyForWebContents(contents);
+    apps::Instance::InstanceKey contents_instance_key(GetWindow(contents));
 
     // Get the app_id from the existed instance first. The app_id for PWAs could
     // be changed based on the URL, e.g. google photos, which might cause
@@ -486,19 +476,16 @@
   return extension_misc::kChromeAppId;
 }
 
-apps::Instance::InstanceKey
-AppServiceInstanceRegistryHelper::GetInstanceKeyForWebContents(
+aura::Window* AppServiceInstanceRegistryHelper::GetWindow(
     content::WebContents* contents) {
   std::string app_id = shelf_controller_helper_->GetAppID(contents);
   aura::Window* window = contents->GetNativeView();
 
   // If |app_id| is empty, it is a browser tab. Returns the toplevel window in
   // this case.
-  if (app_id.empty()) {
-    return apps::Instance::InstanceKey::ForWindowBasedApp(
-        window->GetToplevelWindow());
-  }
-  return apps::Instance::InstanceKey::ForWebBasedApp(window);
+  if (app_id.empty())
+    window = window->GetToplevelWindow();
+  return window;
 }
 
 std::set<apps::Instance::InstanceKey>
@@ -530,8 +517,7 @@
   if (app_id == extension_misc::kChromeAppId)
     return;
 
-  aura::Window* top_level_window =
-      instance_key.GetEnclosingAppWindow()->GetToplevelWindow();
+  aura::Window* top_level_window = instance_key.Window()->GetToplevelWindow();
   browser_window_to_tab_instances_[top_level_window].insert(instance_key);
   tab_instance_to_browser_window_[instance_key] = top_level_window;
 }
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.h b/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.h
index fb0ebf57..6921cf2 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.h
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.h
@@ -103,12 +103,10 @@
   // application.
   std::string GetAppId(content::WebContents* contents) const;
 
-  // Returns an InstanceKey to represent |contents| in InstanceRegistry. If
-  // |contents| is a Web app, returns an InstanceKey representing the
-  // WebContents for it. If there is no app in |contents|, returns an
-  // InstanceKey for the toplevel window.
-  apps::Instance::InstanceKey GetInstanceKeyForWebContents(
-      content::WebContents* contents);
+  // Returns a window to represent |contents| in InstanceRegistry. If |contents|
+  // is a Web app, returns the native window for it. If there is no app in
+  // |contents|, returns the toplevel window.
+  aura::Window* GetWindow(content::WebContents* contents);
 
   // Returns instance keys in InstanceRegistry for the given |app_id|.
   std::set<apps::Instance::InstanceKey> GetInstanceKeys(
diff --git a/chrome/browser/ui/ash/shelf/arc_app_shelf_browsertest.cc b/chrome/browser/ui/ash/shelf/arc_app_shelf_browsertest.cc
index eafc18ed..a23bc26 100644
--- a/chrome/browser/ui/ash/shelf/arc_app_shelf_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/arc_app_shelf_browsertest.cc
@@ -8,6 +8,8 @@
 #include <vector>
 
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "ash/public/cpp/shelf_item_delegate.h"
@@ -37,8 +39,6 @@
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_test_util.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/ash/shelf/shelf_spinner_controller.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/exo/shell_surface.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/test/shell_surface_builder.h"
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 4e33634b..36bd600 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -67,6 +67,7 @@
 #include "chrome/browser/ui/startup/launch_mode_recorder.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/ui_features.h"
@@ -1333,7 +1334,7 @@
   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
 
   EXPECT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   tab_waiter.Wait();
@@ -1512,10 +1513,11 @@
   // Launch again with the same profile.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   chrome::startup::IsFirstRun first_run =
-      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                    : chrome::startup::IS_NOT_FIRST_RUN;
+      first_run::IsChromeFirstRun() ? chrome::startup::IsFirstRun::kYes
+                                    : chrome::startup::IsFirstRun::kNo;
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run);
-  launch.Launch(browser()->profile(), false, nullptr);
+  launch.Launch(browser()->profile(), chrome::startup::IsProcessStartup::kNo,
+                nullptr);
 
   // The launch should have created a new browser.
   ASSERT_EQ(2u, chrome::GetBrowserCount(browser()->profile()));
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index e508865..06c3d551 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -60,6 +60,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chrome/browser/lacros/lacros_url_handling.h"
+#include "chromeos/crosapi/cpp/gurl_os_handler_utils.h"
 #endif
 
 #if defined(USE_AURA)
@@ -585,6 +586,14 @@
       lacros_url_handling::MaybeInterceptNavigation(params->url)) {
     return nullptr;
   }
+  // If Lacros comes here with an internal os:// redirect scheme to Ash, and Ash
+  // does not accept the URL, we convert it into a Lacros chrome:// url instead.
+  // This will most likely end in a 404 inside the Lacros browser. Note that we
+  // do not want to create a "404 SWA application".
+  if (crosapi::gurl_os_handler_utils::IsAshOsUrl(params->url)) {
+    params->url =
+        crosapi::gurl_os_handler_utils::GetChromeUrlFromSystemUrl(params->url);
+  }
 #endif
 
   // Navigate() must not return early after this point.
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index b734a296..66204c27 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -786,6 +786,8 @@
   EXPECT_FALSE(client.GetTabMatcher().IsTabOpenWithURL(singleton_url, nullptr));
 }
 
+// TODO(crbug/1272155): Reactivate the test.
+#if !BUILDFLAG(IS_CHROMEOS_LACROS)
 // This test verifies that "switch to tab" prefers the latest used browser,
 // if multiple exist.
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, SwitchToTabLatestWindow) {
@@ -809,6 +811,7 @@
 
   EXPECT_EQ(browser2, test_browser);
 }
+#endif
 
 // Tests that a disposition of SINGLETON_TAB cannot see outside its
 // window.
@@ -1915,6 +1918,8 @@
   }
 }
 
+// TODO(crbug/1272155): Reactivate the test.
+#if !BUILDFLAG(IS_CHROMEOS_LACROS)
 // Test that subframe navigations generate a NavigationUIData with no
 // disposition.
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, SubFrameNavigationUIData) {
@@ -1948,5 +1953,6 @@
   EXPECT_EQ(WindowOpenDisposition::CURRENT_TAB,
             observer.last_navigation_ui_data()->window_open_disposition());
 }
+#endif
 
 }  // namespace
diff --git a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
index 619ae45d..2a239d5 100644
--- a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
@@ -4,6 +4,7 @@
 
 #include "ash/constants/ash_switches.h"
 #include "base/command_line.h"
+#include "build/chromeos_buildflags.h"
 #include "chrome/browser/ash/login/chrome_restart_request.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
@@ -24,14 +25,23 @@
 #include "content/public/test/browser_test.h"
 #include "ui/aura/window.h"
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h"
+#include "chromeos/lacros/lacros_service.h"
+#include "chromeos/lacros/lacros_test_helper.h"
+#endif
+
 namespace {
 
+using BrowserNavigatorTestChromeOS = BrowserNavigatorTest;
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+
 GURL GetGoogleURL() {
   return GURL("http://www.google.com/");
 }
 
-using BrowserNavigatorTestChromeOS = BrowserNavigatorTest;
-
 // Verifies that new browser is not opened for Signin profile.
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTestChromeOS, RestrictSigninProfile) {
   EXPECT_EQ(chrome::GetTotalBrowserCount(), 1u);
@@ -178,4 +188,97 @@
   }
 }
 
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+// Verifies that the navigation is trying to open the os:// scheme page in
+// Ash, will fail and then open it as chrome:// in Lacros to show a 404 error.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTestChromeOS, OsSchemeRedirectFail) {
+  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+
+  // Navigate to an unknown page with an os:// scheme.
+  NavigateParams params(MakeNavigateParams(browser()));
+  params.disposition = WindowOpenDisposition::SINGLETON_TAB;
+  params.url = GURL("os://foobar");
+  params.window_action = NavigateParams::SHOW_WINDOW;
+  params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
+  Navigate(&params);
+
+  // A new 404 page should be shown in the browser.
+  EXPECT_EQ(browser(), params.browser);
+  EXPECT_EQ(2, browser()->tab_strip_model()->count());
+  EXPECT_EQ(GURL("chrome://foobar"),
+            browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
+}
+
+// Verifies that the navigation of an os:// scheme page is opening an app on
+// the ash side and does not produce a navigation on the Lacros side.
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTestChromeOS, OsSchemeRedirectSucceed) {
+  if (chromeos::LacrosService::Get()->GetInterfaceVersion(
+          crosapi::mojom::TestController::Uuid_) <
+      static_cast<int>(crosapi::mojom::TestController::MethodMinVersions::
+                           kGetOpenAshBrowserWindowsMinVersion)) {
+    LOG(WARNING) << "Unsupported ash version.";
+    return;
+  }
+
+  crosapi::mojom::TestControllerAsyncWaiter waiter(
+      chromeos::LacrosService::Get()
+          ->GetRemote<crosapi::mojom::TestController>()
+          .get());
+
+  // Ash shouldn't have a browser window open by now.
+  uint32_t number = 1;
+  waiter.GetOpenAshBrowserWindows(&number);
+  EXPECT_EQ(0u, number);
+
+  // First we make sure that the GURL we are interested in is in our allow list.
+  chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get();
+  auto init_params = crosapi::mojom::BrowserInitParams::New();
+  init_params->accepted_internal_ash_urls =
+      std::vector<GURL>{GURL(chrome::kOsUIFlagsURL)};
+  lacros_service->SetInitParamsForTests(std::move(init_params));
+
+  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+  GURL url_before_navigation =
+      browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
+
+  // Navigate to a known Ash page.
+  NavigateParams params(MakeNavigateParams(browser()));
+  params.disposition = WindowOpenDisposition::SINGLETON_TAB;
+  params.url = GURL(chrome::kOsUIFlagsURL);
+  params.window_action = NavigateParams::SHOW_WINDOW;
+  params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
+  Navigate(&params);
+
+  // No change should have happened on the Lacros side.
+  EXPECT_EQ(browser(), params.browser);
+  EXPECT_EQ(1, browser()->tab_strip_model()->count());
+  EXPECT_EQ(url_before_navigation,
+            browser()->tab_strip_model()->GetActiveWebContents()->GetURL());
+
+  // Clean up the window we have created.
+
+  // Wait until we have the app running.
+  while (0 == number) {
+    usleep(25000);
+    waiter.GetOpenAshBrowserWindows(&number);
+  }
+
+  // Close it.
+  bool success = false;
+  waiter.CloseAllBrowserWindows(&success);
+  EXPECT_TRUE(success);
+
+  // Wait until all are gone.
+  while (0 != number) {
+    usleep(25000);
+    waiter.GetOpenAshBrowserWindows(&number);
+  }
+}
+
+#endif
+
 }  // namespace
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc
index d7923d2..7edaa53 100644
--- a/chrome/browser/ui/page_info/page_info_unittest.cc
+++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/page_specific_content_settings_delegate.h"
 #include "chrome/browser/ssl/stateful_ssl_host_state_delegate_factory.h"
-#include "chrome/browser/ssl/tls_deprecation_test_utils.h"
 #include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h"
 #include "chrome/browser/ui/page_info/chrome_page_info_delegate.h"
 #include "chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h"
@@ -1001,26 +1000,6 @@
 #endif
 }
 
-// Tests that the site connection status is correctly set for Legacy TLS sites.
-TEST_F(PageInfoTest, LegacyTLS) {
-  security_level_ = security_state::WARNING;
-  visible_security_state_.url = GURL("https://scheme-is-cryptographic.test");
-  visible_security_state_.certificate = cert();
-  visible_security_state_.cert_status = net::CERT_STATUS_LEGACY_TLS;
-  int status = 0;
-  status = SetSSLVersion(status, net::SSL_CONNECTION_VERSION_TLS1);
-  status = SetSSLVersion(status, CR_TLS_RSA_WITH_AES_256_CBC_SHA256);
-  visible_security_state_.connection_status = status;
-  visible_security_state_.connection_info_initialized = true;
-
-  SetDefaultUIExpectations(mock_ui());
-
-  EXPECT_EQ(PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS,
-            page_info()->site_connection_status());
-  EXPECT_EQ(PageInfo::SITE_IDENTITY_STATUS_CERT,
-            page_info()->site_identity_status());
-}
-
 #if !defined(OS_ANDROID)
 TEST_F(PageInfoTest, NoInfoBar) {
   SetDefaultUIExpectations(mock_ui());
diff --git a/chrome/browser/ui/shared_highlighting/shared_highlighting_promo.cc b/chrome/browser/ui/shared_highlighting/shared_highlighting_promo.cc
index 4792b6b..7ae1945 100644
--- a/chrome/browser/ui/shared_highlighting/shared_highlighting_promo.cc
+++ b/chrome/browser/ui/shared_highlighting/shared_highlighting_promo.cc
@@ -28,6 +28,11 @@
 void SharedHighlightingPromo::DidFinishLoad(
     content::RenderFrameHost* render_frame_host,
     const GURL& validated_url) {
+  if (!base::FeatureList::IsEnabled(
+          feature_engagement::kIPHDesktopSharedHighlightingFeature)) {
+    return;
+  }
+
   if (HasTextFragment(validated_url.spec()))
     CheckExistingSelectors(render_frame_host);
 }
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 4113d27..8a4fc6ff 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -64,6 +64,7 @@
 #include "chrome/browser/ui/startup/launch_mode_recorder.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
 #include "chrome/browser/ui/startup/startup_tab_provider.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/startup/web_app_startup_utils.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/web_applications/web_app_ui_manager_impl.h"
@@ -333,13 +334,13 @@
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
-void ShowProfilePicker(bool is_process_startup) {
+void ShowProfilePicker(chrome::startup::IsProcessStartup process_startup) {
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-    ProfilePicker::Show(
-        is_process_startup
-            ? ProfilePicker::EntryPoint::kOnStartup
-            : ProfilePicker::EntryPoint::kNewSessionOnExistingProcess);
-    return;
+  ProfilePicker::Show(
+      process_startup == chrome::startup::IsProcessStartup::kYes
+          ? ProfilePicker::EntryPoint::kOnStartup
+          : ProfilePicker::EntryPoint::kNewSessionOnExistingProcess);
+  return;
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
@@ -406,12 +407,13 @@
 bool MaybeLaunchUrlHandlerWebAppFromCmd(
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     Profile* last_used_profile,
     const std::vector<Profile*>& last_opened_profiles) {
   auto on_urls_unhandled_cb = base::BindOnce(
       [](const base::CommandLine& command_line, const base::FilePath& cur_dir,
-         bool process_startup, Profile* last_used_profile,
+         chrome::startup::IsProcessStartup process_startup,
+         Profile* last_used_profile,
          const std::vector<Profile*>& last_opened_profiles) {
         // TODO(crbug.com/1208199): Refactor StartupBrowserCreator and use the
         // state struct here.
@@ -483,8 +485,9 @@
                                   const Profiles& last_opened_profiles) {
   TRACE_EVENT0("startup", "StartupBrowserCreator::Start");
   SCOPED_UMA_HISTOGRAM_TIMER("Startup.StartupBrowserCreator_Start");
-  return ProcessCmdLineImpl(cmd_line, cur_dir, true, last_used_profile,
-                            last_opened_profiles);
+  return ProcessCmdLineImpl(cmd_line, cur_dir,
+                            chrome::startup::IsProcessStartup::kYes,
+                            last_used_profile, last_opened_profiles);
 }
 
 // static
@@ -538,14 +541,17 @@
   DCHECK(!command_line.HasSwitch(switches::kNotificationLaunchId));
 #endif  // defined(OS_WIN)
   in_synchronous_profile_launch_ =
-      process_startup == chrome::startup::IS_PROCESS_STARTUP;
+      process_startup == chrome::startup::IsProcessStartup::kYes;
 
   profile = GetPrivateProfileIfRequested(command_line, profile);
 
   if (!IsSilentLaunchEnabled(command_line, profile)) {
     StartupBrowserCreatorImpl lwp(cur_dir, command_line, this, is_first_run);
-    const bool launched = lwp.Launch(profile, in_synchronous_profile_launch_,
-                                     std::move(launch_mode_recorder));
+    const bool launched = lwp.Launch(
+        profile,
+        in_synchronous_profile_launch_ ? chrome::startup::IsProcessStartup::kYes
+                                       : chrome::startup::IsProcessStartup::kNo,
+        std::move(launch_mode_recorder));
     in_synchronous_profile_launch_ = false;
     if (!launched) {
       LOG(ERROR) << "launch error";
@@ -563,15 +569,12 @@
 bool StartupBrowserCreator::LaunchBrowserForLastProfiles(
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     Profile* last_used_profile,
     const Profiles& last_opened_profiles) {
-  chrome::startup::IsProcessStartup is_process_startup =
-      process_startup ? chrome::startup::IS_PROCESS_STARTUP
-                      : chrome::startup::IS_NOT_PROCESS_STARTUP;
   chrome::startup::IsFirstRun is_first_run =
-      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                    : chrome::startup::IS_NOT_FIRST_RUN;
+      first_run::IsChromeFirstRun() ? chrome::startup::IsFirstRun::kYes
+                                    : chrome::startup::IsFirstRun::kNo;
 
   // On Windows, when chrome is launched by notification activation where the
   // kNotificationLaunchId switch is used, always use |last_used_profile| which
@@ -594,7 +597,7 @@
       last_used_profile && last_used_profile->IsGuestSession()) {
     // The guest session is used to indicate the the profile picker should be
     // displayed on start-up. See GetStartupProfilePath().
-    ShowProfilePicker(/*is_process_startup=*/process_startup);
+    ShowProfilePicker(process_startup);
     return true;
   }
 
@@ -613,7 +616,7 @@
                                            /*create_if_needed=*/true)
                                      : last_used_profile;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-      if (process_startup) {
+      if (process_startup == chrome::startup::IsProcessStartup::kYes) {
         // If FullRestoreService is available for the profile (i.e. the full
         // restore feature is enabled and the profile is a regular user
         // profile), defer the browser launching to FullRestoreService code.
@@ -627,15 +630,15 @@
       }
 #endif
       return LaunchBrowser(command_line, profile_to_open, cur_dir,
-                           is_process_startup, is_first_run,
+                           process_startup, is_first_run,
                            std::make_unique<LaunchModeRecorder>());
     }
 
     // Show ProfilePicker if |last_used_profile| can't be auto opened.
-    ShowProfilePicker(/*is_process_startup=*/process_startup);
+    ShowProfilePicker(process_startup);
     return true;
   }
-  return ProcessLastOpenedProfiles(command_line, cur_dir, is_process_startup,
+  return ProcessLastOpenedProfiles(command_line, cur_dir, process_startup,
                                    is_first_run, last_used_profile,
                                    last_opened_profiles);
 }
@@ -786,14 +789,14 @@
 bool StartupBrowserCreator::ProcessCmdLineImpl(
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     Profile* last_used_profile,
     const Profiles& last_opened_profiles) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   TRACE_EVENT0("startup", "StartupBrowserCreator::ProcessCmdLineImpl");
 
   DCHECK(last_used_profile);
-  if (process_startup &&
+  if (process_startup == chrome::startup::IsProcessStartup::kYes &&
       command_line.HasSwitch(switches::kDisablePromptOnRepost)) {
     content::NavigationController::DisablePromptOnRepost();
   }
@@ -825,7 +828,7 @@
 #endif  // defined(OS_WIN) && BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
   if (command_line.HasSwitch(switches::kValidateCrx)) {
-    if (!process_startup) {
+    if (process_startup == chrome::startup::IsProcessStartup::kNo) {
       LOG(ERROR) << "chrome is already running; you must close all running "
                  << "instances before running with the --"
                  << switches::kValidateCrx << " flag";
@@ -878,7 +881,7 @@
     return true;
 #endif
 
-  if (!process_startup &&
+  if (process_startup == chrome::startup::IsProcessStartup::kNo &&
       command_line.HasSwitch(switches::kDumpBrowserHistograms)) {
     // Only handle --dump-browser-histograms from a rendezvous. In this case, do
     // not open a new browser window even if no output file was given.
@@ -919,12 +922,14 @@
 
   // If --no-startup-window is specified and Chrome is already running then do
   // not open a new window.
-  if (!process_startup && command_line.HasSwitch(switches::kNoStartupWindow))
+  if (process_startup == chrome::startup::IsProcessStartup::kNo &&
+      command_line.HasSwitch(switches::kNoStartupWindow)) {
     silent_launch = true;
+  }
 
   // If we don't want to launch a new browser window or tab we are done here.
   if (silent_launch) {
-    if (process_startup)
+    if (process_startup == chrome::startup::IsProcessStartup::kYes)
       startup_metric_utils::SetNonBrowserUIDisplayed();
     return true;
   }
@@ -1081,7 +1086,7 @@
 bool StartupBrowserCreator::ProcessLastOpenedProfiles(
     const base::CommandLine& command_line,
     const base::FilePath& cur_dir,
-    chrome::startup::IsProcessStartup is_process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     chrome::startup::IsFirstRun is_first_run,
     Profile* last_used_profile,
     const Profiles& last_opened_profiles) {
@@ -1124,14 +1129,14 @@
     if (!LaunchBrowser((profile == last_used_profile)
                            ? command_line
                            : command_line_without_urls,
-                       profile, cur_dir, is_process_startup, is_first_run,
+                       profile, cur_dir, process_startup, is_first_run,
                        profile == last_used_profile
                            ? std::make_unique<LaunchModeRecorder>()
                            : nullptr)) {
       return false;
     }
     // We've launched at least one browser.
-    is_process_startup = chrome::startup::IS_NOT_PROCESS_STARTUP;
+    process_startup = chrome::startup::IsProcessStartup::kNo;
   }
 
 // Set the |last_used_profile| to activate if a browser is launched for at
@@ -1140,8 +1145,8 @@
 // been launched so the observer knows about all profiles to wait before
 // activation this one.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
-  if (is_process_startup == chrome::startup::IS_PROCESS_STARTUP)
-    ShowProfilePicker(/*is_process_startup=*/true);
+  if (process_startup == chrome::startup::IsProcessStartup::kYes)
+    ShowProfilePicker(chrome::startup::IsProcessStartup::kYes);
   else
 #endif
     profile_launch_observer.Get().set_profile_to_activate(last_used_profile);
@@ -1191,8 +1196,9 @@
   if (status != Profile::CREATE_STATUS_INITIALIZED)
     return;
   StartupBrowserCreator startup_browser_creator;
-  startup_browser_creator.ProcessCmdLineImpl(command_line, cur_dir, false,
-                                             profile, Profiles());
+  startup_browser_creator.ProcessCmdLineImpl(
+      command_line, cur_dir, chrome::startup::IsProcessStartup::kNo, profile,
+      Profiles());
 }
 
 // static
@@ -1219,18 +1225,19 @@
   if (chrome::GetTotalBrowserCount() == 0)
     last_opened_profiles = profile_manager->GetLastOpenedProfiles();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-  startup_browser_creator.ProcessCmdLineImpl(command_line, cur_dir,
-                                             /*process_startup=*/false, profile,
-                                             last_opened_profiles);
+  startup_browser_creator.ProcessCmdLineImpl(
+      command_line, cur_dir, chrome::startup::IsProcessStartup::kNo, profile,
+      last_opened_profiles);
 }
 
 // static
-void StartupBrowserCreator::OpenStartupPages(Browser* browser,
-                                             bool process_startup) {
+void StartupBrowserCreator::OpenStartupPages(
+    Browser* browser,
+    chrome::startup::IsProcessStartup process_startup) {
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   chrome::startup::IsFirstRun is_first_run =
-      first_run::IsChromeFirstRun() ? chrome::startup::IS_FIRST_RUN
-                                    : chrome::startup::IS_NOT_FIRST_RUN;
+      first_run::IsChromeFirstRun() ? chrome::startup::IsFirstRun::kYes
+                                    : chrome::startup::IsFirstRun::kNo;
   StartupBrowserCreatorImpl startup_browser_creator_impl(
       base::FilePath(), command_line, is_first_run);
   SessionStartupPref session_startup_pref =
diff --git a/chrome/browser/ui/startup/startup_browser_creator.h b/chrome/browser/ui/startup/startup_browser_creator.h
index faf39801..58e91cac 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.h
+++ b/chrome/browser/ui/startup/startup_browser_creator.h
@@ -113,7 +113,9 @@
       const base::FilePath& startup_profile_dir);
 
   // Opens the set of startup pages from the current session startup prefs.
-  static void OpenStartupPages(Browser* browser, bool process_startup);
+  static void OpenStartupPages(
+      Browser* browser,
+      chrome::startup::IsProcessStartup process_startup);
 
   // Returns true if we're launching a profile synchronously. In that case, the
   // opened window should not cause a session restore.
@@ -129,18 +131,19 @@
   bool LaunchBrowser(const base::CommandLine& command_line,
                      Profile* profile,
                      const base::FilePath& cur_dir,
-                     chrome::startup::IsProcessStartup is_process_startup,
+                     chrome::startup::IsProcessStartup process_startup,
                      chrome::startup::IsFirstRun is_first_run,
                      std::unique_ptr<LaunchModeRecorder> launch_mode_recorder);
 
   // Launch browser for `last_opened_profiles` if it's not empty. Otherwise,
   // launch browser for `last_used_profile`. Return false if any browser is
   // failed to be launched. Otherwise, return true.
-  bool LaunchBrowserForLastProfiles(const base::CommandLine& command_line,
-                                    const base::FilePath& cur_dir,
-                                    bool process_startup,
-                                    Profile* last_used_profile,
-                                    const Profiles& last_opened_profiles);
+  bool LaunchBrowserForLastProfiles(
+      const base::CommandLine& command_line,
+      const base::FilePath& cur_dir,
+      chrome::startup::IsProcessStartup process_startup,
+      Profile* last_used_profile,
+      const Profiles& last_opened_profiles);
 
   // If Incognito or Guest mode are requested by policy or command line returns
   // the appropriate private browsing profile. Otherwise returns |profile|.
@@ -215,7 +218,7 @@
 
   bool ProcessCmdLineImpl(const base::CommandLine& command_line,
                           const base::FilePath& cur_dir,
-                          bool process_startup,
+                          chrome::startup::IsProcessStartup process_startup,
                           Profile* last_used_profile,
                           const Profiles& last_opened_profiles);
 
@@ -226,7 +229,7 @@
   bool ProcessLastOpenedProfiles(
       const base::CommandLine& command_line,
       const base::FilePath& cur_dir,
-      chrome::startup::IsProcessStartup is_process_startup,
+      chrome::startup::IsProcessStartup process_startup,
       chrome::startup::IsFirstRun is_first_run,
       Profile* last_used_profile,
       const Profiles& last_opened_profiles);
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 17b8d7b..3e759b25 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -63,6 +63,7 @@
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
 #include "chrome/browser/ui/startup/startup_tab_provider.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
@@ -208,8 +209,8 @@
 Browser* OpenNewBrowser(Profile* profile) {
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl creator(base::FilePath(), dummy,
-                                    chrome::startup::IS_FIRST_RUN);
-  creator.Launch(profile, false, nullptr);
+                                    chrome::startup::IsFirstRun::kYes);
+  creator.Launch(profile, chrome::startup::IsProcessStartup::kNo, nullptr);
   return chrome::FindBrowserWithProfile(profile);
 }
 
@@ -382,12 +383,13 @@
   ASSERT_EQ(popup, observer.added_browser_);
 
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
-  chrome::startup::IsFirstRun first_run = first_run::IsChromeFirstRun() ?
-      chrome::startup::IS_FIRST_RUN : chrome::startup::IS_NOT_FIRST_RUN;
+  chrome::startup::IsFirstRun first_run =
+      first_run::IsChromeFirstRun() ? chrome::startup::IsFirstRun::kYes
+                                    : chrome::startup::IsFirstRun::kNo;
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, first_run);
   // This should create a new window, but re-use the profile from |popup|. If
   // it used a null or invalid profile, it would crash.
-  launch.OpenURLsInBrowser(popup, false, urls);
+  launch.OpenURLsInBrowser(popup, chrome::startup::IsProcessStartup::kNo, urls);
   ASSERT_NE(popup, observer.added_browser_);
   BrowserList::RemoveObserver(&observer);
 }
@@ -485,7 +487,7 @@
   command_line.AppendSwitchASCII(switches::kApp, url.spec());
 
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   Browser* new_browser = FindOneOtherBrowser(browser());
@@ -531,7 +533,7 @@
   Browser* incognito = CreateIncognitoBrowser();
 
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       incognito->profile(), {}));
 
   Browser* new_browser = FindOneOtherBrowser(incognito);
@@ -711,7 +713,7 @@
   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
 
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   if (IsExpectedToAllowLaunch()) {
@@ -749,7 +751,7 @@
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   if (IsExpectedToAllowLaunch()) {
@@ -788,7 +790,7 @@
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   if (IsExpectedToAllowLaunch()) {
@@ -840,7 +842,7 @@
   command_line.AppendSwitchASCII(switches::kAppId, extension_app->id());
 
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
   tab_waiter.Wait();
 
@@ -897,7 +899,7 @@
       L"1|1|0|Default|0|https://example.com/|notification_id");
 
   ASSERT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   // The launch delegates to the notification system and doesn't open any new
@@ -911,7 +913,7 @@
   command_line.AppendSwitchNative(switches::kNotificationLaunchId, L"");
   StartupBrowserCreator browser_creator;
   ASSERT_FALSE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
 
   // No new browser window is open.
@@ -1690,8 +1692,8 @@
   SessionRestoreTestHelper restore_waiter;
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl creator(base::FilePath(), dummy,
-                                    chrome::startup::IS_NOT_FIRST_RUN);
-  creator.Launch(test_profile, false, nullptr);
+                                    chrome::startup::IsFirstRun::kNo);
+  creator.Launch(test_profile, chrome::startup::IsProcessStartup::kNo, nullptr);
   restore_waiter.Wait();
 
   // We expect a browser to open, but we should NOT get a duplicate app.
@@ -2048,9 +2050,10 @@
   // Trigger the restore via StartupBrowserCreator.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
-                                   chrome::startup::IS_NOT_FIRST_RUN);
+                                   chrome::startup::IsFirstRun::kNo);
   // Fake |process_startup| true.
-  EXPECT_TRUE(launch.Launch(profile1, /* process_startup */ true, nullptr));
+  EXPECT_TRUE(launch.Launch(profile1, chrome::startup::IsProcessStartup::kYes,
+                            nullptr));
 
   // We should get two windows from profile1.
   ASSERT_EQ(3u, BrowserList::GetInstance()->size());
@@ -2964,8 +2967,9 @@
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
 
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), false, nullptr));
+                                   chrome::startup::IsFirstRun::kYes);
+  ASSERT_TRUE(launch.Launch(browser()->profile(),
+                            chrome::startup::IsProcessStartup::kNo, nullptr));
 
   // This should have created a new browser window.
   Browser* new_browser = FindOneOtherBrowser(browser());
@@ -3020,8 +3024,9 @@
   // Do a process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), true, nullptr));
+                                   chrome::startup::IsFirstRun::kYes);
+  ASSERT_TRUE(launch.Launch(browser()->profile(),
+                            chrome::startup::IsProcessStartup::kYes, nullptr));
 
   // This should have created a new browser window.
   Browser* new_browser = FindOneOtherBrowser(browser());
@@ -3066,8 +3071,9 @@
   // Do a process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), true, nullptr));
+                                   chrome::startup::IsFirstRun::kYes);
+  ASSERT_TRUE(launch.Launch(browser()->profile(),
+                            chrome::startup::IsProcessStartup::kYes, nullptr));
 
   // This should have created a new browser window.
   Browser* new_browser = FindOneOtherBrowser(browser());
@@ -3287,8 +3293,9 @@
       const base::CommandLine& command_line) {
     Profile* profile = browser()->profile();
     StartupBrowserCreatorImpl launch(base::FilePath(), command_line,
-                                     chrome::startup::IS_NOT_FIRST_RUN);
-    EXPECT_TRUE(launch.Launch(profile, true, nullptr));
+                                     chrome::startup::IsFirstRun::kNo);
+    EXPECT_TRUE(launch.Launch(profile, chrome::startup::IsProcessStartup::kYes,
+                              nullptr));
 
     // This should have created a new browser window.
     Browser* new_browser = FindOneOtherBrowser(browser());
@@ -3397,8 +3404,9 @@
     command_line.AppendSwitch(switches::kKioskMode);
     command_line.AppendSwitch(extra_switch);
     StartupBrowserCreatorImpl launch(base::FilePath(), command_line,
-                                     chrome::startup::IS_NOT_FIRST_RUN);
-    EXPECT_TRUE(launch.Launch(profile, true, nullptr));
+                                     chrome::startup::IsFirstRun::kNo);
+    EXPECT_TRUE(launch.Launch(profile, chrome::startup::IsProcessStartup::kYes,
+                              nullptr));
 
     // This should have created a new browser window.
     Browser* new_browser = FindOneOtherBrowser(browser());
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index cf738ba..31f460b 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -51,6 +51,7 @@
 #include "chrome/browser/ui/startup/obsolete_system_infobar_delegate.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_tab_provider.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/welcome/helpers.h"
 #include "chrome/browser/ui/webui/whats_new/whats_new_util.h"
@@ -169,7 +170,7 @@
       command_line_(command_line),
       profile_(nullptr),
       browser_creator_(nullptr),
-      is_first_run_(is_first_run == chrome::startup::IS_FIRST_RUN) {}
+      is_first_run_(is_first_run) {}
 
 StartupBrowserCreatorImpl::StartupBrowserCreatorImpl(
     const base::FilePath& cur_dir,
@@ -179,7 +180,7 @@
     : cur_dir_(cur_dir),
       command_line_(command_line),
       browser_creator_(browser_creator),
-      is_first_run_(is_first_run == chrome::startup::IS_FIRST_RUN) {}
+      is_first_run_(is_first_run) {}
 
 // static
 void StartupBrowserCreatorImpl::MaybeToggleFullscreen(Browser* browser) {
@@ -193,7 +194,7 @@
 
 bool StartupBrowserCreatorImpl::Launch(
     Profile* profile,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     std::unique_ptr<LaunchModeRecorder> launch_mode_recorder) {
   DCHECK(profile);
   profile_ = profile;
@@ -220,7 +221,7 @@
   }
 
 #if defined(OS_MAC)
-  if (process_startup) {
+  if (process_startup == chrome::startup::IsProcessStartup::kYes) {
     // Check whether the auto-update system needs to be promoted from user
     // to system.
     KeystoneInfoBar::PromotionInfoBar(profile);
@@ -239,16 +240,17 @@
 
 Browser* StartupBrowserCreatorImpl::OpenURLsInBrowser(
     Browser* browser,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     const std::vector<GURL>& urls) {
   StartupTabs tabs;
   UrlsToTabs(urls, &tabs);
   return OpenTabsInBrowser(browser, process_startup, tabs);
 }
 
-Browser* StartupBrowserCreatorImpl::OpenTabsInBrowser(Browser* browser,
-                                                      bool process_startup,
-                                                      const StartupTabs& tabs) {
+Browser* StartupBrowserCreatorImpl::OpenTabsInBrowser(
+    Browser* browser,
+    chrome::startup::IsProcessStartup process_startup,
+    const StartupTabs& tabs) {
   DCHECK(!tabs.empty());
 
   // If we don't yet have a profile, try to use the one we're given from
@@ -286,8 +288,19 @@
     // asking us to open such a URL should really ask the handler directly.
     bool handled_by_chrome = ProfileIOData::IsHandledURL(tabs[i].url) ||
         (registry && registry->IsHandledProtocol(tabs[i].url.scheme()));
-    if (!process_startup && !handled_by_chrome)
+    if (process_startup == chrome::startup::IsProcessStartup::kNo &&
+        !handled_by_chrome) {
       continue;
+    }
+
+    // Start the What's New fetch but don't add the tab at this point. The tab
+    // will open as the foreground tab only if the remote content can be
+    // retrieved successfully. This prevents needing to automatically close the
+    // tab after opening it in the case where What's New does not load.
+    if (tabs[i].url == whats_new::GetWebUIStartupURL()) {
+      whats_new::StartWhatsNewFetch(browser);
+      continue;
+    }
 
     int add_types = first_tab ? TabStripModel::ADD_ACTIVE :
                                 TabStripModel::ADD_NONE;
@@ -302,7 +315,8 @@
     params.tabstrip_add_types = add_types;
 
 #if BUILDFLAG(ENABLE_RLZ)
-    if (process_startup && google_util::IsGoogleHomePageUrl(tabs[i].url)) {
+    if (process_startup == chrome::startup::IsProcessStartup::kYes &&
+        google_util::IsGoogleHomePageUrl(tabs[i].url)) {
       params.extra_headers = rlz::RLZTracker::GetAccessPointHttpHeader(
           rlz::RLZTracker::ChromeHomePage());
     }
@@ -326,7 +340,8 @@
 }
 
 StartupBrowserCreatorImpl::LaunchResult
-StartupBrowserCreatorImpl::DetermineURLsAndLaunch(bool process_startup) {
+StartupBrowserCreatorImpl::DetermineURLsAndLaunch(
+    chrome::startup::IsProcessStartup process_startup) {
   if (!ShouldLaunch(command_line_))
     return LaunchResult::kNormally;
 
@@ -389,7 +404,7 @@
     return result.launch_result;
 
   BrowserOpenBehaviorOptions behavior_options = 0;
-  if (process_startup)
+  if (process_startup == chrome::startup::IsProcessStartup::kYes)
     behavior_options |= PROCESS_STARTUP;
   if (is_post_crash_launch)
     behavior_options |= IS_POST_CRASH_LAUNCH;
@@ -421,9 +436,7 @@
       tabs, behavior, restore_options, process_startup, is_post_crash_launch);
 
   // Finally, add info bars.
-  AddInfoBarsIfNecessary(
-      browser, process_startup ? chrome::startup::IS_PROCESS_STARTUP
-                               : chrome::startup::IS_NOT_PROCESS_STARTUP);
+  AddInfoBarsIfNecessary(browser, process_startup);
   return result.launch_result;
 }
 
@@ -444,7 +457,7 @@
 StartupBrowserCreatorImpl::DetermineStartupTabsResult
 StartupBrowserCreatorImpl::DetermineStartupTabs(
     const StartupTabProvider& provider,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     bool is_incognito_or_guest,
     bool is_post_crash_launch,
     bool has_incompatible_applications,
@@ -501,13 +514,14 @@
 
     StartupTabs onboarding_tabs;
     if (promotional_tabs_enabled) {
+      StartupTabs welcome_back_tabs;
 #if defined(OS_WIN)
       // This is a launch from a prompt presented to an inactive user who chose
       // to open Chrome and is being brought to a specific URL for this one
       // launch. Launch the browser with the desired welcome back URL in the
       // foreground and the other ordinary URLs (e.g., a restored session) in
       // the background.
-      StartupTabs welcome_back_tabs = provider.GetWelcomeBackTabs(
+      welcome_back_tabs = provider.GetWelcomeBackTabs(
           profile_, browser_creator_, process_startup);
       AppendTabs(welcome_back_tabs, &tabs);
 #endif  // defined(OS_WIN)
@@ -522,8 +536,10 @@
 
       // Potentially add the What's New Page. Note that the What's New page
       // should never be shown in the same session as any first-run onboarding
-      // tabs.
-      if (onboarding_tabs.empty()) {
+      // tabs. It also shouldn't be shown with reset tabs or welcome back tabs
+      // that are required to always be the first foreground tab.
+      if (onboarding_tabs.empty() && reset_tabs.empty() &&
+          welcome_back_tabs.empty()) {
         StartupTabs new_features_tabs;
         new_features_tabs = provider.GetNewFeaturesTabs(whats_new_enabled);
         AppendTabs(new_features_tabs, &tabs);
@@ -553,13 +569,16 @@
   return {std::move(tabs), launch_result};
 }
 
-bool StartupBrowserCreatorImpl::MaybeAsyncRestore(const StartupTabs& tabs,
-                                                  bool process_startup,
-                                                  bool is_post_crash_launch) {
+bool StartupBrowserCreatorImpl::MaybeAsyncRestore(
+    const StartupTabs& tabs,
+    chrome::startup::IsProcessStartup process_startup,
+    bool is_post_crash_launch) {
   // Restore is performed synchronously on startup, and is never performed when
   // launching after crashing.
-  if (process_startup || is_post_crash_launch)
+  if (process_startup == chrome::startup::IsProcessStartup::kYes ||
+      is_post_crash_launch) {
     return false;
+  }
 
   // Note: there's no session service in incognito or guest mode.
   if (!SessionServiceFactory::GetForProfileForSessionRestore(profile_))
@@ -578,7 +597,7 @@
     const StartupTabs& tabs,
     BrowserOpenBehavior behavior,
     SessionRestore::BehaviorBitmask restore_options,
-    bool process_startup,
+    chrome::startup::IsProcessStartup process_startup,
     bool is_post_crash_launch) {
   Browser* browser = nullptr;
   if (behavior == BrowserOpenBehavior::SYNCHRONOUS_RESTORE) {
@@ -594,7 +613,8 @@
     if (browser)
       return browser;
   } else if (behavior == BrowserOpenBehavior::USE_EXISTING) {
-    browser = chrome::FindTabbedBrowser(profile_, process_startup);
+    browser = chrome::FindTabbedBrowser(
+        profile_, process_startup == chrome::startup::IsProcessStartup::kYes);
   }
 
   base::AutoReset<bool> synchronous_launch_resetter(
@@ -622,7 +642,7 @@
 
 void StartupBrowserCreatorImpl::AddInfoBarsIfNecessary(
     Browser* browser,
-    chrome::startup::IsProcessStartup is_process_startup) {
+    chrome::startup::IsProcessStartup process_startup) {
   if (!browser || !profile_ || browser->tab_strip_model()->count() == 0)
     return;
 
@@ -649,7 +669,7 @@
   // These info bars are not shown when the browser is being controlled by
   // automated tests, so that they don't interfere with tests that assume no
   // info bars.
-  if (is_process_startup == chrome::startup::IS_PROCESS_STARTUP &&
+  if (process_startup == chrome::startup::IsProcessStartup::kYes &&
       !command_line_.HasSwitch(switches::kTestType) &&
       !command_line_.HasSwitch(switches::kEnableAutomation)) {
     content::WebContents* web_contents =
@@ -675,11 +695,10 @@
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
     if (!command_line_.HasSwitch(switches::kNoDefaultBrowserCheck)) {
       // The default browser prompt should only be shown after the first run.
-      if (!is_first_run_)
+      if (is_first_run_ == chrome::startup::IsFirstRun::kNo)
         ShowDefaultBrowserPrompt(profile_);
     }
 #endif
-
   }
 }
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.h b/chrome/browser/ui/startup/startup_browser_creator_impl.h
index 93352f1..3e438920 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.h
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.h
@@ -57,17 +57,17 @@
   static void MaybeToggleFullscreen(Browser* browser);
 
   // Creates the necessary windows for startup. Returns true on success,
-  // false on failure. process_startup is true if Chrome is just
-  // starting up. If process_startup is false, it indicates Chrome was
-  // already running and the user wants to launch another instance.
+  // false on failure. |process_startup| indicates whether Chrome is just
+  // starting up or already running and the user wants to launch another
+  // instance.
   bool Launch(Profile* profile,
-              bool process_startup,
+              chrome::startup::IsProcessStartup process_startup,
               std::unique_ptr<LaunchModeRecorder> launch_mode_recorder);
 
   // Convenience for OpenTabsInBrowser that converts |urls| into a set of
   // Tabs.
   Browser* OpenURLsInBrowser(Browser* browser,
-                             bool process_startup,
+                             chrome::startup::IsProcessStartup process_startup,
                              const std::vector<GURL>& urls);
 
  private:
@@ -144,13 +144,14 @@
   // are added to is returned, which is either |browser|, the newly created
   // browser, or nullptr if browser could not be created.
   Browser* OpenTabsInBrowser(Browser* browser,
-                             bool process_startup,
+                             chrome::startup::IsProcessStartup process_startup,
                              const StartupTabs& tabs);
 
   // Determines the URLs to be shown at startup by way of various policies
   // (welcome, pinned tabs, etc.), determines whether a session restore
   // is necessary, and opens the URLs in a new or restored browser accordingly.
-  LaunchResult DetermineURLsAndLaunch(bool process_startup);
+  LaunchResult DetermineURLsAndLaunch(
+      chrome::startup::IsProcessStartup process_startup);
 
   // Returns a tuple of
   // - the tabs to be shown on startup, based on the policy functions in
@@ -159,7 +160,7 @@
   // - Whether there's launch tabs.
   DetermineStartupTabsResult DetermineStartupTabs(
       const StartupTabProvider& provider,
-      bool process_startup,
+      chrome::startup::IsProcessStartup process_startup,
       bool is_ephemeral_profile,
       bool is_post_crash_launch,
       bool has_incompatible_applications,
@@ -173,7 +174,7 @@
   // should continue (either synchronously, or asynchronously without
   // restoring).
   bool MaybeAsyncRestore(const StartupTabs& tabs,
-                         bool process_startup,
+                         chrome::startup::IsProcessStartup process_startup,
                          bool is_post_crash_launch);
 
   // Returns a browser displaying the contents of |tabs|. Based on |behavior|,
@@ -183,13 +184,13 @@
       const StartupTabs& tabs,
       BrowserOpenBehavior behavior,
       SessionRestore::BehaviorBitmask restore_options,
-      bool process_startup,
+      chrome::startup::IsProcessStartup process_startup,
       bool is_post_crash_launch);
 
   // Adds any startup infobars to the selected tab of the given browser.
   void AddInfoBarsIfNecessary(
       Browser* browser,
-      chrome::startup::IsProcessStartup is_process_startup);
+      chrome::startup::IsProcessStartup process_startup);
 
   // Determines how the launch flow should obtain a Browser.
   static BrowserOpenBehavior DetermineBrowserOpenBehavior(
@@ -210,7 +211,7 @@
   const base::CommandLine& command_line_;
   Profile* profile_ = nullptr;
   StartupBrowserCreator* browser_creator_;
-  bool is_first_run_;
+  chrome::startup::IsFirstRun is_first_run_;
 };
 
 #endif  // CHROME_BROWSER_UI_STARTUP_STARTUP_BROWSER_CREATOR_IMPL_H_
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc b/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
index 9aaa624..c2bd8871 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
@@ -96,12 +96,15 @@
   }
 
 #if defined(OS_WIN)
-  StartupTabs GetWelcomeBackTabs(Profile* profile,
-                                 StartupBrowserCreator* browser_creator,
-                                 bool process_startup) const override {
+  StartupTabs GetWelcomeBackTabs(
+      Profile* profile,
+      StartupBrowserCreator* browser_creator,
+      chrome::startup::IsProcessStartup process_startup) const override {
     StartupTabs tabs;
-    if (process_startup && (options_ & kWelcomeBackTab))
+    if (process_startup == chrome::startup::IsProcessStartup::kYes &&
+        (options_ & kWelcomeBackTab)) {
       tabs.emplace_back(GURL("https://welcome-back"), false);
+    }
     return tabs;
   }
 #endif  // defined(OS_WIN)
@@ -165,10 +168,11 @@
                                   kNewTabPageTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider, true, false, false, false,
-                                          true, true, false);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, false, false, false,
+      true, true, false);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
 
   ASSERT_EQ(4U, output.tabs.size());
@@ -178,8 +182,9 @@
   EXPECT_EQ("pinned", output.tabs[3].url.host());
 
   // No extra onboarding content for managed starts.
-  output = impl.DetermineStartupTabs(provider, true, false, false, false, false,
-                                     true, false);
+  output = impl.DetermineStartupTabs(provider,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, false, false, false, true, false);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
 
   ASSERT_EQ(3U, output.tabs.size());
@@ -188,8 +193,9 @@
   EXPECT_EQ("pinned", output.tabs[2].url.host());
 
   // No onboarding if not enabled even if promo is allowed.
-  output = impl.DetermineStartupTabs(provider, true, false, false, false, true,
-                                     false, false);
+  output = impl.DetermineStartupTabs(provider,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, false, false, true, false, false);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
 
   ASSERT_EQ(3U, output.tabs.size());
@@ -206,10 +212,11 @@
       kPinnedTabs | kPreferencesTabs | kNewTabPageTabs | kNewFeaturesTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider, true, true, false, false,
-                                          true, true, true);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, true, false, false,
+      true, true, true);
   EXPECT_EQ(Creator::LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(1U, output.tabs.size());
   // Check for the actual NTP URL, rather than the sentinel returned by the
@@ -227,11 +234,12 @@
                                   kNewFeaturesTabs | kPostCrashTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
   // Regular Crash Recovery case:
-  auto output = impl.DetermineStartupTabs(provider, true, false, true, false,
-                                          true, true, true);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, false, true, false,
+      true, true, true);
   EXPECT_EQ(Creator::LaunchResult::kNormally, output.launch_result);
 
   ASSERT_EQ(1U, output.tabs.size());
@@ -241,8 +249,9 @@
   EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), output.tabs[0].url);
 
   // Crash Recovery case with problem applications:
-  output = impl.DetermineStartupTabs(provider, true, false, true, true, true,
-                                     true, true);
+  output = impl.DetermineStartupTabs(provider,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, true, true, true, true, true);
   EXPECT_EQ(Creator::LaunchResult::kNormally, output.launch_result);
 
   ASSERT_EQ(1U, output.tabs.size());
@@ -257,10 +266,11 @@
       kPinnedTabs | kPreferencesTabs | kNewTabPageTabs | kNewFeaturesTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider, true, false, false, false,
-                                          true, true, true);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, false, false, false,
+      true, true, true);
   EXPECT_EQ(Creator::LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(1U, output.tabs.size());
   EXPECT_EQ("distribution", output.tabs[0].url.host());
@@ -277,10 +287,11 @@
                                   kNewFeaturesTabs | kCommandLineTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider, true, false, false, false,
-                                          true, true, true);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, false, false, false,
+      true, true, true);
   EXPECT_EQ(LaunchResult::kWithGivenUrls, output.launch_result);
 
   ASSERT_EQ(3U, output.tabs.size());
@@ -292,24 +303,27 @@
   // command line tabs.
 
   // Incognito
-  output = impl.DetermineStartupTabs(provider, true, true, false, false, true,
-                                     true, true);
+  output = impl.DetermineStartupTabs(provider,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     true, false, false, true, true, true);
   EXPECT_EQ(LaunchResult::kWithGivenUrls, output.launch_result);
 
   ASSERT_EQ(1U, output.tabs.size());
   EXPECT_EQ("cmd-line", output.tabs[0].url.host());
 
   // Crash Recovery
-  output = impl.DetermineStartupTabs(provider, true, false, true, false, true,
-                                     true, true);
+  output = impl.DetermineStartupTabs(provider,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, true, false, true, true, true);
   EXPECT_EQ(LaunchResult::kWithGivenUrls, output.launch_result);
 
   ASSERT_EQ(1U, output.tabs.size());
   EXPECT_EQ("cmd-line", output.tabs[0].url.host());
 
   // Crash Recovery with incompatible applications.
-  output = impl.DetermineStartupTabs(provider, true, false, true, true, true,
-                                     true, true);
+  output = impl.DetermineStartupTabs(provider,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, true, true, true, true, true);
   EXPECT_EQ(LaunchResult::kWithGivenUrls, output.launch_result);
   ASSERT_EQ(1U, output.tabs.size());
   EXPECT_EQ("cmd-line", output.tabs[0].url.host());
@@ -326,10 +340,11 @@
                                   kNewFeaturesTabs | kCrosapiTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider, true, false, false, false,
-                                          true, true, true);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, false, false, false,
+      true, true, true);
   EXPECT_EQ(LaunchResult::kWithGivenUrls, output.launch_result);
 
   ASSERT_EQ(1U, output.tabs.size());
@@ -344,10 +359,11 @@
                                              kNewTabPageTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider_allows_ntp, true, false,
-                                          false, false, true, true, false);
+  auto output = impl.DetermineStartupTabs(
+      provider_allows_ntp, chrome::startup::IsProcessStartup::kYes, false,
+      false, false, true, true, false);
   EXPECT_EQ(Creator::LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(3U, output.tabs.size());
   EXPECT_EQ("reset-trigger", output.tabs[0].url.host());
@@ -364,10 +380,11 @@
   FakeStartupTabProvider provider(kNewTabPageTabs | kNewFeaturesTabs);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider, true, false, false, false,
-                                          true, true, true);
+  auto output = impl.DetermineStartupTabs(
+      provider, chrome::startup::IsProcessStartup::kYes, false, false, false,
+      true, true, true);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(2U, output.tabs.size());
   EXPECT_EQ("whats-new", output.tabs[0].url.host());
@@ -376,8 +393,9 @@
   // New features can appear with prefs/pinned.
   FakeStartupTabProvider provider_with_pinned(
       kPinnedTabs | kPreferencesTabs | kNewTabPageTabs | kNewFeaturesTabs);
-  output = impl.DetermineStartupTabs(provider_with_pinned, true, false, false,
-                                     false, true, true, true);
+  output = impl.DetermineStartupTabs(provider_with_pinned,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, false, false, true, true, true);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(3U, output.tabs.size());
   EXPECT_EQ("whats-new", output.tabs[0].url.host());
@@ -387,8 +405,9 @@
   // Onboarding overrides What's New.
   FakeStartupTabProvider provider_with_onboarding(
       kOnboardingTabs | kNewTabPageTabs | kNewFeaturesTabs);
-  output = impl.DetermineStartupTabs(provider_with_onboarding, true, false,
-                                     false, false, true, true, true);
+  output = impl.DetermineStartupTabs(provider_with_onboarding,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, false, false, true, true, true);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(1U, output.tabs.size());
   EXPECT_EQ("onboarding", output.tabs[0].url.host());
@@ -404,10 +423,11 @@
                                              kWelcomeBackTab);
   Creator impl(base::FilePath(),
                base::CommandLine(base::CommandLine::NO_PROGRAM),
-               chrome::startup::IS_FIRST_RUN);
+               chrome::startup::IsFirstRun::kYes);
 
-  auto output = impl.DetermineStartupTabs(provider_allows_ntp, true, false,
-                                          false, false, true, true, false);
+  auto output = impl.DetermineStartupTabs(
+      provider_allows_ntp, chrome::startup::IsProcessStartup::kYes, false,
+      false, false, true, true, false);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(3U, output.tabs.size());
   EXPECT_EQ("welcome-back", output.tabs[0].url.host());
@@ -415,16 +435,18 @@
   EXPECT_EQ("pinned", output.tabs[2].url.host());
 
   // No welcome back for non-startup opens.
-  output = impl.DetermineStartupTabs(provider_allows_ntp, false, false, false,
-                                     false, true, true, false);
+  output = impl.DetermineStartupTabs(provider_allows_ntp,
+                                     chrome::startup::IsProcessStartup::kNo,
+                                     false, false, false, true, true, false);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(2U, output.tabs.size());
   EXPECT_EQ("prefs", output.tabs[0].url.host());
   EXPECT_EQ("pinned", output.tabs[1].url.host());
 
   // No welcome back for managed starts even if first run.
-  output = impl.DetermineStartupTabs(provider_allows_ntp, true, false, false,
-                                     false, false, true, false);
+  output = impl.DetermineStartupTabs(provider_allows_ntp,
+                                     chrome::startup::IsProcessStartup::kYes,
+                                     false, false, false, false, true, false);
   EXPECT_EQ(LaunchResult::kNormally, output.launch_result);
   ASSERT_EQ(2U, output.tabs.size());
   EXPECT_EQ("prefs", output.tabs[0].url.host());
diff --git a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
index 1866f9f..e8cf2a4 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_triggered_reset_browsertest_win.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/ui/startup/launch_mode_recorder.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/startup/startup_browser_creator_impl.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version.h"
@@ -146,8 +147,9 @@
   // Do a simple non-process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
-                                   chrome::startup::IS_NOT_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(profile, false, nullptr));
+                                   chrome::startup::IsFirstRun::kNo);
+  ASSERT_TRUE(
+      launch.Launch(profile, chrome::startup::IsProcessStartup::kNo, nullptr));
 
   // This should have created a new browser window.  |browser()| is still
   // around at this point, even though we've closed its window.
@@ -193,8 +195,9 @@
   // Do a process-startup browser launch.
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   StartupBrowserCreatorImpl launch(base::FilePath(), dummy, &browser_creator,
-                                   chrome::startup::IS_FIRST_RUN);
-  ASSERT_TRUE(launch.Launch(browser()->profile(), true, nullptr));
+                                   chrome::startup::IsFirstRun::kYes);
+  ASSERT_TRUE(launch.Launch(browser()->profile(),
+                            chrome::startup::IsProcessStartup::kYes, nullptr));
 
   // This should have created a new browser window.
   Browser* new_browser = FindOneOtherBrowser(browser());
@@ -229,8 +232,9 @@
   base::CommandLine dummy(base::CommandLine::NO_PROGRAM);
   {
     StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
-                                     chrome::startup::IS_NOT_FIRST_RUN);
-    ASSERT_TRUE(launch.Launch(browser()->profile(), false, nullptr));
+                                     chrome::startup::IsFirstRun::kNo);
+    ASSERT_TRUE(launch.Launch(browser()->profile(),
+                              chrome::startup::IsProcessStartup::kNo, nullptr));
   }
 
   // This should have created a new browser window.  |browser()| is still
@@ -268,8 +272,9 @@
   // Same kind of simple non-process-startup browser launch.
   {
     StartupBrowserCreatorImpl launch(base::FilePath(), dummy,
-                                     chrome::startup::IS_NOT_FIRST_RUN);
-    ASSERT_TRUE(launch.Launch(other_profile_ptr, false, nullptr));
+                                     chrome::startup::IsFirstRun::kNo);
+    ASSERT_TRUE(launch.Launch(other_profile_ptr,
+                              chrome::startup::IsProcessStartup::kNo, nullptr));
   }
 
   Browser* other_profile_browser =
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc
index a7c9852..c668fda 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -28,9 +28,11 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/settings/reset_settings_handler.h"
+#include "chrome/browser/ui/webui/whats_new/whats_new_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "components/prefs/pref_service.h"
@@ -133,10 +135,12 @@
 StartupTabs StartupTabProviderImpl::GetWelcomeBackTabs(
     Profile* profile,
     StartupBrowserCreator* browser_creator,
-    bool process_startup) const {
+    chrome::startup::IsProcessStartup process_startup) const {
   StartupTabs tabs;
-  if (!process_startup || !browser_creator)
+  if (process_startup == chrome::startup::IsProcessStartup::kNo ||
+      !browser_creator) {
     return tabs;
+  }
   if (browser_creator->welcome_back_page() &&
       CanShowWelcome(SyncServiceFactory::IsSyncAllowed(profile),
                      profile->IsSupervised(),
@@ -367,10 +371,8 @@
 StartupTabs StartupTabProviderImpl::GetNewFeaturesTabsForState(
     bool whats_new_enabled) {
   StartupTabs tabs;
-  if (whats_new_enabled) {
-    GURL url(chrome::kChromeUIWhatsNewURL);
-    tabs.emplace_back(net::AppendQueryParameter(url, "auto", "true"), false);
-  }
+  if (whats_new_enabled)
+    tabs.emplace_back(whats_new::GetWebUIStartupURL(), false);
   return tabs;
 }
 #endif
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h
index 43f1aad..59949a429 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.h
+++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -11,6 +11,7 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/ui/startup/startup_tab.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "url/gurl.h"
 
 class Profile;
@@ -41,9 +42,10 @@
 #if defined(OS_WIN)
   // Returns a "welcome back" tab to be shown if requested for a specific
   // launch.
-  virtual StartupTabs GetWelcomeBackTabs(Profile* profile,
-                                         StartupBrowserCreator* browser_creator,
-                                         bool process_startup) const = 0;
+  virtual StartupTabs GetWelcomeBackTabs(
+      Profile* profile,
+      StartupBrowserCreator* browser_creator,
+      chrome::startup::IsProcessStartup process_startup) const = 0;
 #endif  // defined(OS_WIN)
 
   // Checks for the presence of a trigger indicating the need to offer a Profile
@@ -190,9 +192,10 @@
   StartupTabs GetOnboardingTabs(Profile* profile) const override;
 
 #if defined(OS_WIN)
-  StartupTabs GetWelcomeBackTabs(Profile* profile,
-                                 StartupBrowserCreator* browser_creator,
-                                 bool process_startup) const override;
+  StartupTabs GetWelcomeBackTabs(
+      Profile* profile,
+      StartupBrowserCreator* browser_creator,
+      chrome::startup::IsProcessStartup process_startup) const override;
 #endif  // defined(OS_WIN)
 
   StartupTabs GetDistributionFirstRunTabs(
diff --git a/chrome/browser/ui/startup/startup_types.h b/chrome/browser/ui/startup/startup_types.h
index 33ab1bc..1229500a 100644
--- a/chrome/browser/ui/startup/startup_types.h
+++ b/chrome/browser/ui/startup/startup_types.h
@@ -8,20 +8,19 @@
 namespace chrome {
 namespace startup {
 
-enum IsProcessStartup {
-  IS_NOT_PROCESS_STARTUP,   // Session is being created when a Chrome process is
-                            // already running, e.g. clicking on a taskbar icon
-                            // when Chrome is already running, or restoring a
-                            // profile.
-  IS_PROCESS_STARTUP        // Session is being created when the Chrome process
-                            // is not already running.
+enum class IsProcessStartup : bool {
+  kNo,  // Session is being created when a Chrome process is already running,
+        // e.g. clicking on a taskbar icon when Chrome is already running, or
+        // restoring a profile.
+  kYes  // Session is being created when the Chrome process is not already
+        // running.
 };
 
-enum IsFirstRun {
-  IS_NOT_FIRST_RUN,         // Session is being created after Chrome has already
-                            // been run at least once on the system.
-  IS_FIRST_RUN              // Session is being created immediately after Chrome
-                            // has been installed on the system.
+enum class IsFirstRun : bool {
+  kNo,  // Session is being created after Chrome has already been run at least
+        // once on the system.
+  kYes  // Session is being created immediately after Chrome has been installed
+        // on the system.
 };
 
 }  // namespace startup
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index 4152ec41..ebdbe5b 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -63,14 +63,6 @@
 const base::Feature kExtensionsMenuAccessControl{
     "ExtensionsMenuAccessControl", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enables the hosting of an extension in the left aligned side panel of the
-// browser window. Currently used for a hosted extension experiment.
-const base::Feature kExtensionsSidePanel{"ExtensionsSidePanel",
-                                         base::FEATURE_DISABLED_BY_DEFAULT};
-
-const base::FeatureParam<std::string> kExtensionsSidePanelId{
-    &kExtensionsSidePanel, "ExtensionsSidePanelId", ""};
-
 // Enables the reauth flow for authenticated profiles with invalid credentials
 // when the force sign-in policy is enabled.
 const base::Feature kForceSignInReauth{"ForceSignInReauth",
@@ -226,6 +218,9 @@
 const base::Feature kToolbarUseHardwareBitmapDraw{
     "ToolbarUseHardwareBitmapDraw", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kUnifiedSidePanel{"UnifiedSidePanel",
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
+
 // This enables enables persistence of a WebContents in a 1-to-1 association
 // with the current Profile for WebUI bubbles. See https://crbug.com/1177048.
 const base::Feature kWebUIBubblePerProfilePersistence{
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index e413293b..f32f679 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -45,11 +45,6 @@
 
 extern const base::Feature kExtensionsMenuAccessControl;
 
-extern const base::Feature kExtensionsSidePanel;
-
-// The extension id of the extension hosted in the left aligned side panel.
-extern const base::FeatureParam<std::string> kExtensionsSidePanelId;
-
 extern const base::Feature kForceSignInReauth;
 
 extern const base::Feature kProminentDarkModeActiveTabTitle;
@@ -182,6 +177,8 @@
 // Works on Android 10+.
 extern const base::Feature kToolbarUseHardwareBitmapDraw;
 
+extern const base::Feature kUnifiedSidePanel;
+
 extern const base::Feature kWebUIBubblePerProfilePersistence;
 
 #if !defined(ANDROID)
diff --git a/chrome/browser/ui/views/DEPS b/chrome/browser/ui/views/DEPS
index 18ccd05..640070d 100644
--- a/chrome/browser/ui/views/DEPS
+++ b/chrome/browser/ui/views/DEPS
@@ -25,6 +25,7 @@
   ".*test.*": [
    "!ash",
    "+ash/components/arc/intent_helper",
+   "+ash/components/arc/session",
    "+ash/components/arc/test",
    "+ash/constants",
    "+ash/public",
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index f8414869..81562448 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/chrome_typography_provider.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/ui/popup_item_ids.h"
 #include "components/autofill/core/browser/ui/popup_types.h"
 #include "components/autofill/core/browser/ui/suggestion.h"
@@ -228,6 +229,36 @@
   return label;
 }
 
+// Returns the name of the network for payment method icons, empty string
+// otherwise.
+std::u16string GetIconAccessibleName(const std::string& icon_text) {
+  // Networks for which icons are currently shown.
+  if (icon_text == autofill::kAmericanExpressCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
+  if (icon_text == autofill::kDinersCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
+  if (icon_text == autofill::kDiscoverCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
+  if (icon_text == autofill::kEloCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_ELO);
+  if (icon_text == autofill::kJCBCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
+  if (icon_text == autofill::kMasterCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
+  if (icon_text == autofill::kMirCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MIR);
+  if (icon_text == autofill::kTroyCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_TROY);
+  if (icon_text == autofill::kUnionPay)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_UNION_PAY);
+  if (icon_text == autofill::kVisaCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
+  // Other networks.
+  if (icon_text == autofill::kGenericCard)
+    return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC);
+  return std::u16string();
+}
+
 }  // namespace
 
 namespace autofill {
@@ -531,6 +562,11 @@
   AutofillPopupController* controller = popup_view()->controller();
   std::vector<std::u16string> text;
 
+  auto suggestion = controller->GetSuggestionAt(GetLineNumber());
+  std::u16string icon_name = GetIconAccessibleName(suggestion.icon);
+  if (!icon_name.empty())
+    text.push_back(icon_name);
+
   auto main_text = controller->GetSuggestionMainTextAt(GetLineNumber());
   text.push_back(main_text);
 
@@ -545,7 +581,6 @@
   }
 
   // TODO(siyua): GetSuggestionLabelAt should return a vector of strings.
-  auto suggestion = controller->GetSuggestionAt(GetLineNumber());
   if (!suggestion.offer_label.empty()) {
     // |offer_label| is only populated for credit card suggestions.
     text.push_back(suggestion.offer_label);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 32508ef..e21f92e 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1474,7 +1474,8 @@
                              false);
   } else {
     // saved tab groups flag
-    if (base::FeatureList::IsEnabled(features::kTabGroupsSave)) {
+    if (base::FeatureList::IsEnabled(features::kTabGroupsSave) &&
+        !node->is_permanent_node()) {
       // Record as bookmark folder launch in dev when rendering tab groups from
       // folder data.
       RecordBookmarkFolderLaunch(BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR);
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
index a6d5b10..740541f 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/extensions/extensions_menu_view.h"
 
 #include "base/containers/contains.h"
+#include "base/feature_list.h"
 #include "base/i18n/case_conversion.h"
 #include "base/memory/ptr_util.h"
 #include "base/ranges/algorithm.h"
@@ -14,6 +15,7 @@
 #include "chrome/browser/ui/extensions/extension_action_view_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/bubble_menu_item_factory.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
@@ -494,6 +496,9 @@
     ExtensionsContainer* extensions_container,
     bool allow_pinning) {
   DCHECK(!g_extensions_dialog);
+  // Experiment `kExtensionsMenuAccessControl` is introducing a new menu. Check
+  // `ExtensionsMenuView` is only constructed when the experiment is disabled.
+  DCHECK(!base::FeatureList::IsEnabled(features::kExtensionsMenuAccessControl));
   g_extensions_dialog = new ExtensionsMenuView(
       anchor_view, browser, extensions_container, allow_pinning);
   views::Widget* widget =
diff --git a/chrome/browser/ui/views/extensions/extensions_side_panel_controller.cc b/chrome/browser/ui/views/extensions/extensions_side_panel_controller.cc
deleted file mode 100644
index 4d57b97..0000000
--- a/chrome/browser/ui/views/extensions/extensions_side_panel_controller.cc
+++ /dev/null
@@ -1,220 +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/ui/views/extensions/extensions_side_panel_controller.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
-#include "chrome/browser/extensions/extension_service.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 "chrome/browser/ui/views/toolbar/toolbar_button.h"
-#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
-#include "chrome/grit/generated_resources.h"
-#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/navigation_entry.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/view_type_utils.h"
-#include "extensions/common/api/extension_action/action_info.h"
-#include "extensions/common/extension_id.h"
-#include "net/base/url_util.h"
-#include "ui/base/metadata/metadata_header_macros.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
-#include "ui/color/color_id.h"
-#include "ui/color/color_provider.h"
-#include "ui/views/controls/webview/webview.h"
-
-namespace {
-
-// TODO(tluk): Figure out what our default width should be.
-constexpr int kDefaultWidth = 450;
-
-const char kSidePanelResourceName[] = "side_panel.html";
-const char kPanelActiveKey[] = "active";
-const char kPanelActivatableKey[] = "activatable";
-const char kPanelWidth[] = "width";
-const char kPanelTrueValue[] = "true";
-
-class ExtensionsSidePanelButton : public ToolbarButton {
- public:
-  METADATA_HEADER(ExtensionsSidePanelButton);
-
- protected:
-  SkColor GetForegroundColor(ButtonState state) const override {
-    // Highlight the activatable state of extension button to increase
-    // visibility.
-    switch (state) {
-      case ButtonState::STATE_HOVERED:
-      case ButtonState::STATE_PRESSED:
-      case ButtonState::STATE_NORMAL:
-        return GetColorProvider()->GetColor(
-            ui::kColorButtonBackgroundProminent);
-      default:
-        return ToolbarButton::GetForegroundColor(state);
-    }
-  }
-};
-
-BEGIN_METADATA(ExtensionsSidePanelButton, ToolbarButton)
-END_METADATA
-
-}  // namespace
-
-ExtensionsSidePanelController::ExtensionsSidePanelController(
-    SidePanel* side_panel,
-    BrowserView* browser_view)
-    : extension_id_(features::kExtensionsSidePanelId.Get()),
-      side_panel_(side_panel),
-      browser_view_(browser_view),
-      web_view_(side_panel_->AddChildView(
-          std::make_unique<views::WebView>(browser_view_->GetProfile()))) {
-  DCHECK(base::FeatureList::IsEnabled(features::kExtensionsSidePanel));
-  // Allow the embedder to handle accelerators not handled by the WebContents.
-  web_view_->set_allow_accelerators(true);
-
-  extensions::ExtensionRegistry* registry =
-      extensions::ExtensionRegistry::Get(browser_view->GetProfile());
-  registry_observation_.Observe(registry);
-
-  side_panel_->SetVisible(false);
-  side_panel_->SetPanelWidth(kDefaultWidth);
-
-  if (const extensions::Extension* extension = GetExtension()) {
-    SetNewWebContents();
-    web_view_->LoadInitialURL(
-        extension->GetResourceURL(kSidePanelResourceName));
-  }
-}
-
-ExtensionsSidePanelController::~ExtensionsSidePanelController() = default;
-
-std::unique_ptr<ToolbarButton>
-ExtensionsSidePanelController::CreateToolbarButton() {
-  auto toolbar_button = std::make_unique<ExtensionsSidePanelButton>();
-  toolbar_button->SetAccessibleName(
-      l10n_util::GetStringUTF16(IDS_ACCNAME_LEFT_ALIGNED_SIDE_PANEL_BUTTON));
-  toolbar_button->SetTooltipText(
-      l10n_util::GetStringUTF16(IDS_TOOLTIP_LEFT_ALIGNED_SIDE_PANEL_BUTTON));
-  // TODO(tluk): Update this to use the icon from the extension.
-  toolbar_button->SetVectorIcon(kWebIcon);
-  toolbar_button->SetCallback(base::BindRepeating(
-      &ExtensionsSidePanelController::SidePanelButtonPressed,
-      base::Unretained(this)));
-  toolbar_button->SetVisible(!!GetExtension());
-  toolbar_button->SetEnabled(false);
-  return toolbar_button;
-}
-
-void ExtensionsSidePanelController::ResetWebContents() {
-  if (!web_view_->web_contents() && !web_contents_)
-    return;
-
-  DCHECK_EQ(web_view_->web_contents(), web_contents_.get());
-  Observe(nullptr);
-  web_view_->SetWebContents(nullptr);
-  web_contents_.reset();
-}
-
-void ExtensionsSidePanelController::SetNewWebContents() {
-  if (web_view_->web_contents())
-    ResetWebContents();
-
-  DCHECK(!web_view_->web_contents());
-  DCHECK(!web_contents_);
-  web_contents_ = content::WebContents::Create(
-      content::WebContents::CreateParams(browser_view_->GetProfile()));
-
-  // Set the side panel as type kExtensionPopup given this most closely
-  // represents how we intend to use the extension for the side panel.
-  // TODO(tluk): Consider creating a new type specifically for the extension
-  // side panel.
-  extensions::SetViewType(web_contents_.get(),
-                          extensions::mojom::ViewType::kExtensionPopup);
-
-  Observe(web_contents_.get());
-  web_contents_->SetDelegate(this);
-  web_view_->SetWebContents(web_contents_.get());
-}
-
-content::WebContents* ExtensionsSidePanelController::OpenURLFromTab(
-    content::WebContents* source,
-    const content::OpenURLParams& params) {
-  return browser_view_->browser()->OpenURL(params);
-}
-
-bool ExtensionsSidePanelController::HandleKeyboardEvent(
-    content::WebContents* source,
-    const content::NativeWebKeyboardEvent& event) {
-  return unhandled_keyboard_event_handler_.HandleKeyboardEvent(
-      event, web_view_->GetFocusManager());
-}
-
-void ExtensionsSidePanelController::OnExtensionLoaded(
-    content::BrowserContext* browser_context,
-    const extensions::Extension* extension) {
-  if (extension->id() == extension_id_) {
-    SetNewWebContents();
-    web_view_->LoadInitialURL(
-        extension->GetResourceURL(kSidePanelResourceName));
-    browser_view_->toolbar()->left_side_panel_button()->SetVisible(true);
-  }
-}
-
-void ExtensionsSidePanelController::OnExtensionUnloaded(
-    content::BrowserContext* browser_context,
-    const extensions::Extension* extension,
-    extensions::UnloadedExtensionReason reason) {
-  if (extension->id() == extension_id_) {
-    ResetWebContents();
-    browser_view_->toolbar()->left_side_panel_button()->SetVisible(false);
-    side_panel_->SetVisible(false);
-  }
-}
-
-// The extension host uses URL params to control various properties of the side
-// panel such as visibility and width. Check for these params and adjust the
-// side panel accordingly.
-void ExtensionsSidePanelController::NavigationEntryCommitted(
-    const content::LoadCommittedDetails& load_details) {
-  const GURL& url = load_details.entry->GetURL();
-  std::string value;
-
-  // TODO(crbug.com/1203063): The side panel contents should not be active when
-  // the panel is not active. This could lead to issues wrt extension lifetime
-  // and resource consumption. Remove or fix this after the experiment has
-  // concluded.
-  if (net::GetValueForKeyInQuery(url, kPanelActiveKey, &value))
-    side_panel_->SetVisible(value == kPanelTrueValue);
-
-  if (net::GetValueForKeyInQuery(url, kPanelWidth, &value)) {
-    unsigned int width = 0;
-    base::StringToUint(value, &width);
-    side_panel_->SetPanelWidth(width);
-  }
-
-  if (net::GetValueForKeyInQuery(url, kPanelActivatableKey, &value)) {
-    auto* left_side_panel_button =
-        browser_view_->toolbar()->left_side_panel_button();
-    DCHECK(left_side_panel_button);
-    left_side_panel_button->SetEnabled(value == kPanelTrueValue);
-  }
-}
-
-const extensions::Extension* ExtensionsSidePanelController::GetExtension() {
-  return extensions::ExtensionRegistry::Get(browser_view_->GetProfile())
-      ->enabled_extensions()
-      .GetByID(extension_id_);
-}
-
-void ExtensionsSidePanelController::SidePanelButtonPressed() {
-  const auto* extension = GetExtension();
-  extensions::ExtensionAction action(
-      *extension, extensions::ActionInfo(extensions::ActionInfo::TYPE_BROWSER));
-  auto* web_contents =
-      browser_view_->browser()->tab_strip_model()->GetActiveWebContents();
-  extensions::ExtensionActionAPI::Get(browser_view_->GetProfile())
-      ->DispatchExtensionActionClicked(action, web_contents, extension);
-}
diff --git a/chrome/browser/ui/views/extensions/extensions_side_panel_controller.h b/chrome/browser/ui/views/extensions/extensions_side_panel_controller.h
deleted file mode 100644
index fa1d3de5..0000000
--- a/chrome/browser/ui/views/extensions/extensions_side_panel_controller.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_SIDE_PANEL_CONTROLLER_H_
-#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_SIDE_PANEL_CONTROLLER_H_
-
-#include <memory>
-
-#include "base/scoped_observation.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_registry_observer.h"
-#include "extensions/common/extension_id.h"
-#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
-
-namespace extensions {
-class Extension;
-}
-
-namespace views {
-class WebView;
-}  // namespace views
-
-class BrowserView;
-class SidePanel;
-class ToolbarButton;
-
-// A class that manages hosting the extension WebContents in the left aligned
-// side panel of the browser window.
-// TODO(crbug.com/1197555): Remove this once the experiment has concluded.
-class ExtensionsSidePanelController
-    : public content::WebContentsObserver,
-      public content::WebContentsDelegate,
-      public extensions::ExtensionRegistryObserver {
- public:
-  ExtensionsSidePanelController(SidePanel* side_panel,
-                                BrowserView* browser_view);
-  ExtensionsSidePanelController(const ExtensionsSidePanelController&) = delete;
-  ExtensionsSidePanelController& operator=(
-      const ExtensionsSidePanelController&) = delete;
-  ~ExtensionsSidePanelController() override;
-
-  std::unique_ptr<ToolbarButton> CreateToolbarButton();
-  void ResetWebContents();
-  void SetNewWebContents();
-
-  // content::WebContentsDelegate:
-  content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) override;
-  bool HandleKeyboardEvent(
-      content::WebContents* source,
-      const content::NativeWebKeyboardEvent& event) override;
-
-  // extensions::ExtensionRegistryObserver:
-  void OnExtensionLoaded(content::BrowserContext* browser_context,
-                         const extensions::Extension* extension) override;
-  void OnExtensionUnloaded(content::BrowserContext* browser_context,
-                           const extensions::Extension* extension,
-                           extensions::UnloadedExtensionReason reason) override;
-
-  views::WebView* get_web_view_for_testing() { return web_view_; }
-
- private:
-  // content::WebContentsObserver:
-  void NavigationEntryCommitted(
-      const content::LoadCommittedDetails& load_details) override;
-
-  const extensions::Extension* GetExtension();
-
-  void SidePanelButtonPressed();
-
-  const extensions::ExtensionId extension_id_;
-  SidePanel* side_panel_;
-  BrowserView* browser_view_;
-  views::WebView* web_view_;
-  std::unique_ptr<content::WebContents> web_contents_;
-
-  // A handler to handle unhandled keyboard messages coming back from the
-  // renderer process.
-  views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
-
-  base::ScopedObservation<extensions::ExtensionRegistry,
-                          extensions::ExtensionRegistryObserver>
-      registry_observation_{this};
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_SIDE_PANEL_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/extensions/extensions_side_panel_controller_browsertest.cc b/chrome/browser/ui/views/extensions/extensions_side_panel_controller_browsertest.cc
deleted file mode 100644
index 91aec8d..0000000
--- a/chrome/browser/ui/views/extensions/extensions_side_panel_controller_browsertest.cc
+++ /dev/null
@@ -1,161 +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 <memory>
-
-#include "base/strings/strcat.h"
-#include "base/strings/string_number_conversions.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/ui_features.h"
-#include "chrome/browser/ui/views/extensions/extensions_side_panel_controller.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/toolbar/toolbar_view.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/extension_builder.h"
-
-namespace {
-
-const char kTargetedId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-const char kSidePanelResourceName[] = "side_panel.html";
-const char kPanelActiveKey[] = "active";
-const char kPanelActivatableKey[] = "activatable";
-const char kPanelWidth[] = "width";
-const char kTrue[] = "true";
-const char kFalse[] = "false";
-
-std::string GetResourceString(const std::string& key,
-                              const std::string& value) {
-  return base::StrCat({kSidePanelResourceName, "?", key, "=", value});
-}
-
-}  // namespace
-
-class ExtensionsSidePanelControllerBrowserTest : public InProcessBrowserTest {
- public:
-  ExtensionsSidePanelControllerBrowserTest() {
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        {features::kExtensionsSidePanel},
-        {{"ExtensionsSidePanelId", kTargetedId}});
-  }
-
-  void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
-    extension_ = extensions::ExtensionBuilder("foo").SetID(kTargetedId).Build();
-    GetExtensionService()->AddExtension(extension_.get());
-
-    // The following should exist when the `kExtensionsSidePanel` feature flag
-    // is enabled and the extension with id specified by `ExtensionsSidePanelId`
-    // is present.
-    ASSERT_NE(nullptr, side_panel());
-    ASSERT_NE(nullptr, side_panel_button());
-    ASSERT_NE(nullptr, controller());
-  }
-
-  extensions::ExtensionService* GetExtensionService() {
-    return extensions::ExtensionSystem::Get(browser()->profile())
-        ->extension_service();
-  }
-
-  BrowserView* browser_view() {
-    return static_cast<BrowserView*>(browser()->window());
-  }
-
-  SidePanel* side_panel() {
-    return browser_view()->left_aligned_side_panel_for_testing();
-  }
-
-  ToolbarButton* side_panel_button() {
-    return browser_view()->toolbar()->left_side_panel_button();
-  }
-
-  ExtensionsSidePanelController* controller() {
-    return browser_view()->extensions_side_panel_controller();
-  }
-
-  const extensions::Extension* extension() { return extension_.get(); }
-
- private:
-  scoped_refptr<const extensions::Extension> extension_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_F(ExtensionsSidePanelControllerBrowserTest,
-                       LeftSidePanelButtonVisibleOnlyWhenExtensionEnabled) {
-  EXPECT_TRUE(side_panel_button()->GetVisible());
-
-  // Remove the extension.
-  GetExtensionService()->UnloadExtension(
-      kTargetedId, extensions::UnloadedExtensionReason::UNINSTALL);
-  EXPECT_FALSE(side_panel_button()->GetVisible());
-
-  // Reenable the extension.
-  GetExtensionService()->AddExtension(extension());
-  EXPECT_TRUE(side_panel_button()->GetVisible());
-}
-
-IN_PROC_BROWSER_TEST_F(ExtensionsSidePanelControllerBrowserTest,
-                       ToggleSidePanelViaURLParams) {
-  EXPECT_FALSE(side_panel()->GetVisible());
-
-  // Toggle the side panel into the visible state.
-  controller()->get_web_view_for_testing()->LoadInitialURL(
-      extension()->GetResourceURL(GetResourceString(kPanelActiveKey, kTrue)));
-  content::WaitForLoadStop(
-      controller()->get_web_view_for_testing()->GetWebContents());
-  EXPECT_TRUE(side_panel()->GetVisible());
-
-  // Hide the side panel.
-  controller()->get_web_view_for_testing()->LoadInitialURL(
-      extension()->GetResourceURL(GetResourceString(kPanelActiveKey, kFalse)));
-  content::WaitForLoadStop(
-      controller()->get_web_view_for_testing()->GetWebContents());
-  EXPECT_FALSE(side_panel()->GetVisible());
-}
-
-IN_PROC_BROWSER_TEST_F(ExtensionsSidePanelControllerBrowserTest,
-                       SetSidePanelWidthViaURLParams) {
-  constexpr int kWidth1 = 300;
-  controller()->get_web_view_for_testing()->LoadInitialURL(
-      extension()->GetResourceURL(
-          GetResourceString(kPanelWidth, base::NumberToString(kWidth1))));
-  content::WaitForLoadStop(
-      controller()->get_web_view_for_testing()->GetWebContents());
-  EXPECT_EQ(side_panel()->GetPreferredSize().width(), kWidth1);
-
-  constexpr int kWidth2 = 200;
-  controller()->get_web_view_for_testing()->LoadInitialURL(
-      extension()->GetResourceURL(
-          GetResourceString(kPanelWidth, base::NumberToString(kWidth2))));
-  content::WaitForLoadStop(
-      controller()->get_web_view_for_testing()->GetWebContents());
-  EXPECT_EQ(side_panel()->GetPreferredSize().width(), kWidth2);
-}
-
-IN_PROC_BROWSER_TEST_F(ExtensionsSidePanelControllerBrowserTest,
-                       SetSidePanelActivatableViaURLParams) {
-  EXPECT_FALSE(side_panel_button()->GetEnabled());
-
-  // Set the side panel to be activatable, enabling the side panel button.
-  controller()->get_web_view_for_testing()->LoadInitialURL(
-      extension()->GetResourceURL(
-          GetResourceString(kPanelActivatableKey, kTrue)));
-  content::WaitForLoadStop(
-      controller()->get_web_view_for_testing()->GetWebContents());
-  EXPECT_TRUE(side_panel_button()->GetEnabled());
-
-  // Set activatable to false, disabling the side panel button.
-  controller()->get_web_view_for_testing()->LoadInitialURL(
-      extension()->GetResourceURL(
-          GetResourceString(kPanelActivatableKey, kFalse)));
-  content::WaitForLoadStop(
-      controller()->get_web_view_for_testing()->GetWebContents());
-  EXPECT_FALSE(side_panel_button()->GetEnabled());
-}
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc
new file mode 100644
index 0000000..e603bf2b
--- /dev/null
+++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc
@@ -0,0 +1,121 @@
+// 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/ui/views/extensions/extensions_tabbed_menu_view.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_provider.h"
+
+namespace {
+ExtensionsTabbedMenuView* g_extensions_dialog = nullptr;
+}  // namespace
+
+ExtensionsTabbedMenuView::ExtensionsTabbedMenuView(
+    views::View* anchor_view,
+    ExtensionsToolbarButton::ButtonType button_type)
+    : BubbleDialogDelegateView(anchor_view,
+                               views::BubbleBorder::Arrow::TOP_RIGHT) {
+  // Ensure layer masking is used for the extensions menu to ensure buttons with
+  // layer effects sitting flush with the bottom of the bubble are clipped
+  // appropriately.
+  SetPaintClientToLayer(true);
+
+  set_margins(gfx::Insets(0));
+
+  SetButtons(ui::DIALOG_BUTTON_NONE);
+  SetShowCloseButton(true);
+  SetTitle(IDS_EXTENSIONS_MENU_TITLE);
+  GetViewAccessibility().OverrideName(GetAccessibleWindowTitle());
+
+  SetEnableArrowKeyTraversal(true);
+
+  // Let anchor view's MenuButtonController handle the highlight.
+  set_highlight_button_when_shown(false);
+
+  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
+  SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical));
+
+  CreateTabbedPane(button_type);
+}
+
+ExtensionsTabbedMenuView::~ExtensionsTabbedMenuView() {
+  g_extensions_dialog = nullptr;
+}
+
+// static
+views::Widget* ExtensionsTabbedMenuView::ShowBubble(
+    views::View* anchor_view,
+    ExtensionsToolbarButton::ButtonType button_type) {
+  DCHECK(!g_extensions_dialog);
+  DCHECK(base::FeatureList::IsEnabled(features::kExtensionsMenuAccessControl));
+  g_extensions_dialog = new ExtensionsTabbedMenuView(anchor_view, button_type);
+  views::Widget* widget =
+      views::BubbleDialogDelegateView::CreateBubble(g_extensions_dialog);
+  widget->Show();
+  return widget;
+}
+
+// static
+bool ExtensionsTabbedMenuView::IsShowing() {
+  return g_extensions_dialog != nullptr;
+}
+
+// static
+void ExtensionsTabbedMenuView::Hide() {
+  DCHECK(base::FeatureList::IsEnabled(features::kExtensionsMenuAccessControl));
+  if (IsShowing()) {
+    g_extensions_dialog->GetWidget()->Close();
+    // Set the dialog to nullptr since `GetWidget->Close()` is not synchronous.
+    g_extensions_dialog = nullptr;
+  }
+}
+
+// static
+ExtensionsTabbedMenuView*
+ExtensionsTabbedMenuView::GetExtensionsTabbedMenuViewForTesting() {
+  return g_extensions_dialog;
+}
+
+size_t ExtensionsTabbedMenuView::GetSelectedTabIndex() const {
+  return tabbed_pane_->GetSelectedTabIndex();
+}
+
+std::u16string ExtensionsTabbedMenuView::GetAccessibleWindowTitle() const {
+  // The title is already spoken via the call to SetTitle().
+  return std::u16string();
+}
+
+void ExtensionsTabbedMenuView::CreateTabbedPane(
+    ExtensionsToolbarButton::ButtonType button_type) {
+  tabbed_pane_ = AddChildView(std::make_unique<views::TabbedPane>());
+  tabbed_pane_->SetFocusBehavior(views::View::FocusBehavior::NEVER);
+
+  // TODO(crbug.com/1263310): Populate site access tab.
+  auto permissions_view = std::make_unique<views::View>();
+  tabbed_pane_->AddTab(
+      l10n_util::GetStringUTF16(IDS_EXTENSIONS_MENU_SITE_ACCESS_TAB_TITLE),
+      std::move(permissions_view));
+
+  // TODO(crbug.com/1263311): Populate extensions installed tab.
+  auto installed_view = std::make_unique<views::View>();
+  tabbed_pane_->AddTab(
+      l10n_util::GetStringUTF16(IDS_EXTENSIONS_MENU_EXTENSIONS_TAB_TITLE),
+      std::move(installed_view));
+
+  // Tabs left to right order is 'site access tab' | 'extensions tab'.
+  tabbed_pane_->SelectTabAt(button_type ==
+                            ExtensionsToolbarButton::ButtonType::kExtensions);
+}
+
+BEGIN_METADATA(ExtensionsTabbedMenuView, views::BubbleDialogDelegateView)
+END_METADATA
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.h b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.h
new file mode 100644
index 0000000..4c17e13
--- /dev/null
+++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.h
@@ -0,0 +1,61 @@
+// 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_UI_VIEWS_EXTENSIONS_EXTENSIONS_TABBED_MENU_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_TABBED_MENU_VIEW_H_
+
+#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+
+namespace views {
+class TabbedPane;
+}  // namespace views
+
+// ExtensionsTabbedMenuView is the extensions menu dialog with a tabbed pane.
+// TODO(crbug.com/1263311): Brief explanation of each tabs goal after
+// implementing them.
+class ExtensionsTabbedMenuView : public views::BubbleDialogDelegateView {
+ public:
+  METADATA_HEADER(ExtensionsTabbedMenuView);
+  ExtensionsTabbedMenuView(views::View* anchor_view,
+                           ExtensionsToolbarButton::ButtonType button_type);
+  ~ExtensionsTabbedMenuView() override;
+  ExtensionsTabbedMenuView(const ExtensionsTabbedMenuView&) = delete;
+  const ExtensionsTabbedMenuView& operator=(const ExtensionsTabbedMenuView&) =
+      delete;
+
+  // Displays the ExtensionsTabbedMenu under `anchor_view` with the selected tab
+  // open by the `selected_tab_index` given. Only one menu is allowed to be
+  // shown at a time (outside of tests).
+  static views::Widget* ShowBubble(
+      views::View* anchor_view,
+      ExtensionsToolbarButton::ButtonType button_type);
+
+  // Returns true if there is currently an ExtensionsTabbedMenuView showing
+  // (across all browsers and profiles).
+  static bool IsShowing();
+
+  // Hides the currently-showing ExtensionsTabbedMenuView, if any exists.
+  static void Hide();
+
+  // Returns the currently-showing ExtensionsTabbedMenuView, if any exists.
+  static ExtensionsTabbedMenuView* GetExtensionsTabbedMenuViewForTesting();
+
+  // Returns the index of the currently selected tab.
+  size_t GetSelectedTabIndex() const;
+
+  // views::BubbleDialogDelegateView:
+  std::u16string GetAccessibleWindowTitle() const override;
+
+ private:
+  // Initially creates the tabs and opens the corresponding one based on the
+  // `button_type`.
+  void CreateTabbedPane(ExtensionsToolbarButton::ButtonType button_type_);
+
+  // The view containing the menu's two tabs.
+  views::TabbedPane* tabbed_pane_ = nullptr;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_TABBED_MENU_VIEW_H_
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc
new file mode 100644
index 0000000..b1d65de
--- /dev/null
+++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc
@@ -0,0 +1,237 @@
+// 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/ui/views/extensions/extensions_tabbed_menu_view.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "components/crx_file/id_util.h"
+#include "content/public/test/web_contents_tester.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/value_builder.h"
+#include "extensions/test/test_extension_dir.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/views/layout/animating_layout_manager_test_util.h"
+#include "ui/views/test/button_test_api.h"
+
+namespace {
+
+std::unique_ptr<base::ListValue> ToListValue(
+    const std::vector<std::string>& permissions) {
+  extensions::ListBuilder builder;
+  for (const std::string& permission : permissions)
+    builder.Append(permission);
+  return builder.Build();
+}
+
+}  // namespace
+
+class ExtensionsTabbedMenuViewUnitTest : public TestWithBrowserView {
+ public:
+  ExtensionsTabbedMenuViewUnitTest();
+  ~ExtensionsTabbedMenuViewUnitTest() override = default;
+  ExtensionsTabbedMenuViewUnitTest(const ExtensionsTabbedMenuViewUnitTest&) =
+      delete;
+  ExtensionsTabbedMenuViewUnitTest& operator=(
+      const ExtensionsTabbedMenuViewUnitTest&) = delete;
+
+  // TestWithBrowserView:
+  void SetUp() override;
+
+  extensions::ExtensionService* extension_service() {
+    return extension_service_;
+  }
+  ExtensionsToolbarButton* extensions_button() {
+    return browser_view()
+        ->toolbar()
+        ->extensions_container()
+        ->GetExtensionsToolbarControls()
+        ->extensions_button();
+  }
+  ExtensionsToolbarButton* site_access_button() {
+    return browser_view()
+        ->toolbar()
+        ->extensions_container()
+        ->GetExtensionsToolbarControls()
+        ->site_access_button_for_testing();
+  }
+  ExtensionsTabbedMenuView* extensions_tabbed_menu() {
+    return ExtensionsTabbedMenuView::GetExtensionsTabbedMenuViewForTesting();
+  }
+
+  // Adds a new tab to the tab strip, and returns the WebContentsTester
+  // associated with it.
+  content::WebContentsTester* AddWebContentsAndGetTester();
+
+  // Adds an extension with no host permissions.
+  const extensions::Extension* InstallExtension(const std::string& name);
+
+  // Adds an extension with the given host permission.
+  const extensions::Extension* InstallExtensionWithHostPermissions(
+      const std::string& name,
+      const std::vector<std::string>& host_permissions);
+
+  // Triggers the pressed event of the given `button`.
+  void ClickToolbarButton(ExtensionsToolbarButton* button);
+
+  // Since this is a unittest, the ExtensionsToolbarContainer sometimes needs a
+  // nudge to re-layout the views.
+  void LayoutContainerIfNecessary();
+
+ private:
+  extensions::ExtensionService* extension_service_ = nullptr;
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+ExtensionsTabbedMenuViewUnitTest::ExtensionsTabbedMenuViewUnitTest() {
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kExtensionsMenuAccessControl);
+}
+
+void ExtensionsTabbedMenuViewUnitTest::SetUp() {
+  TestWithBrowserView::SetUp();
+
+  extensions::TestExtensionSystem* extension_system =
+      static_cast<extensions::TestExtensionSystem*>(
+          extensions::ExtensionSystem::Get(profile()));
+  extension_system->CreateExtensionService(
+      base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
+
+  extension_service_ =
+      extensions::ExtensionSystem::Get(profile())->extension_service();
+
+  // Shorten delay on animations so tests run faster.
+  views::test::ReduceAnimationDuration(
+      browser_view()->toolbar()->extensions_container());
+}
+
+content::WebContentsTester*
+ExtensionsTabbedMenuViewUnitTest::AddWebContentsAndGetTester() {
+  std::unique_ptr<content::WebContents> contents(
+      content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
+  content::WebContents* raw_contents = contents.get();
+  browser()->tab_strip_model()->AppendWebContents(std::move(contents), true);
+  EXPECT_EQ(browser()->tab_strip_model()->GetActiveWebContents(), raw_contents);
+  return content::WebContentsTester::For(raw_contents);
+}
+
+const extensions::Extension* ExtensionsTabbedMenuViewUnitTest::InstallExtension(
+    const std::string& name) {
+  return InstallExtensionWithHostPermissions(name, {});
+}
+
+const extensions::Extension*
+ExtensionsTabbedMenuViewUnitTest::InstallExtensionWithHostPermissions(
+    const std::string& name,
+    const std::vector<std::string>& host_permissions) {
+  scoped_refptr<const extensions::Extension> extension =
+      extensions::ExtensionBuilder(name)
+          .SetManifestKey("manifest_version", 3)
+          .SetManifestKey("host_permissions", ToListValue(host_permissions))
+          .SetID(crx_file::id_util::GenerateId(name))
+          .Build();
+  extension_service()->AddExtension(extension.get());
+
+  // Force the container to re-layout, since a new extension was added.
+  LayoutContainerIfNecessary();
+
+  return extension.get();
+}
+
+void ExtensionsTabbedMenuViewUnitTest::ClickToolbarButton(
+    ExtensionsToolbarButton* button) {
+  button->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(),
+                                        gfx::Point(), ui::EventTimeForNow(),
+                                        ui::EF_LEFT_MOUSE_BUTTON, 0));
+  LayoutContainerIfNecessary();
+}
+
+void ExtensionsTabbedMenuViewUnitTest::LayoutContainerIfNecessary() {
+  browser_view()
+      ->toolbar()
+      ->extensions_container()
+      ->GetWidget()
+      ->LayoutRootViewIfNecessary();
+}
+
+TEST_F(ExtensionsTabbedMenuViewUnitTest, ButtonOpensAndClosesCorrespondingTab) {
+  content::WebContentsTester* web_contents_tester =
+      AddWebContentsAndGetTester();
+
+  // Load an extension with all urls permissions so the site access button is
+  // visible.
+  InstallExtensionWithHostPermissions("all_urls", {"<all_urls>"});
+
+  // Navigate to an url where the extension should have access to.
+  const GURL url("http://www.a.com");
+  web_contents_tester->NavigateAndCommit(url);
+  EXPECT_TRUE(site_access_button()->GetVisible());
+  EXPECT_FALSE(ExtensionsTabbedMenuView::IsShowing());
+
+  // Click on the extensions button when the menu is closed. Extensions menu
+  // should open in the installed extensions tab.
+  ClickToolbarButton(extensions_button());
+  EXPECT_TRUE(ExtensionsTabbedMenuView::IsShowing());
+  EXPECT_EQ(extensions_tabbed_menu()->GetSelectedTabIndex(), 1u);
+
+  // Click on the extensions button when the menu is open. Extensions menu
+  // should be closed.
+  ClickToolbarButton(extensions_button());
+  EXPECT_FALSE(ExtensionsTabbedMenuView::IsShowing());
+
+  // Click on the site access button when the menu is closed. Extensions menu
+  // should open in the site access tab.
+  ClickToolbarButton(site_access_button());
+  EXPECT_TRUE(ExtensionsTabbedMenuView::IsShowing());
+  EXPECT_EQ(extensions_tabbed_menu()->GetSelectedTabIndex(), 0u);
+
+  // Click on the site access button when the menu is open. Extensions menu
+  // should close.
+  ClickToolbarButton(site_access_button());
+  EXPECT_FALSE(ExtensionsTabbedMenuView::IsShowing());
+}
+
+TEST_F(ExtensionsTabbedMenuViewUnitTest, TogglingButtonsClosesMenu) {
+  content::WebContentsTester* web_contents_tester =
+      AddWebContentsAndGetTester();
+
+  // Load an extension with all urls permissions so the site access button is
+  // visible.
+  InstallExtensionWithHostPermissions("all_urls", {"<all_urls>"});
+
+  // Navigate to an url where the extension should have access to.
+  const GURL url("http://www.a.com");
+  web_contents_tester->NavigateAndCommit(url);
+  EXPECT_TRUE(site_access_button()->GetVisible());
+  EXPECT_FALSE(ExtensionsTabbedMenuView::IsShowing());
+
+  // Click on the extensions button when the menu is closed. Extensions menu
+  // should open.
+  ClickToolbarButton(extensions_button());
+  EXPECT_TRUE(ExtensionsTabbedMenuView::IsShowing());
+
+  // Click on the site access button when the menu is open. Extensions menu
+  // should close since the button click is treated as a click outside the menu,
+  // and therefore closing the menu, instead of triggering the button's click
+  // action.
+  // TODO(crbug.com/1263311): Toggle to the corresponding tab when clicking on
+  // the other control when the menu is open.
+  ClickToolbarButton(site_access_button());
+  EXPECT_FALSE(ExtensionsTabbedMenuView::IsShowing());
+
+  // Click on the site access button when the menu is closed. Extensions menu
+  // should open.
+  ClickToolbarButton(site_access_button());
+  EXPECT_TRUE(ExtensionsTabbedMenuView::IsShowing());
+
+  // Click on the extensions button when the menu is open. Extensions menu
+  // should close, as explained previously.
+  ClickToolbarButton(extensions_button());
+  EXPECT_FALSE(ExtensionsTabbedMenuView::IsShowing());
+}
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
index 1bd4bad..d62b5dab 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
@@ -4,13 +4,16 @@
 
 #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h"
 
+#include "base/feature_list.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/extensions/extensions_menu_view.h"
+#include "chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.h"
 #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
@@ -135,19 +138,26 @@
 }
 
 void ExtensionsToolbarButton::ToggleExtensionsMenu() {
-  // TODO(crbug.com/1239772): Once the extension menu tabs are implemented, need
-  // to check for the button type to a) hide the menu, b) change tabs or c) open
-  // menu in the correct tab.
-  if (ExtensionsMenuView::IsShowing()) {
+  if (ExtensionsTabbedMenuView::IsShowing()) {
+    ExtensionsTabbedMenuView::Hide();
+    return;
+  } else if (ExtensionsMenuView::IsShowing()) {
     ExtensionsMenuView::Hide();
     return;
   }
+
   pressed_lock_ = menu_button_controller_->TakeLock();
   extensions_container_->OnMenuOpening();
   base::RecordAction(base::UserMetricsAction("Extensions.Toolbar.MenuOpened"));
-  ExtensionsMenuView::ShowBubble(this, browser_, extensions_container_,
-                                 extensions_container_->CanShowIconInToolbar())
-      ->AddObserver(this);
+  views::Widget* menu;
+  if (base::FeatureList::IsEnabled(features::kExtensionsMenuAccessControl)) {
+    menu = ExtensionsTabbedMenuView::ShowBubble(this, button_type_);
+  } else {
+    menu = ExtensionsMenuView::ShowBubble(
+        this, browser_, extensions_container_,
+        extensions_container_->CanShowIconInToolbar());
+  }
+  menu->AddObserver(this);
 }
 
 bool ExtensionsToolbarButton::GetExtensionsMenuShowing() const {
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
index 388eaecf..e12204db 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
@@ -82,6 +82,11 @@
   // Gets the extension menu button for the toolbar.
   ExtensionsToolbarButton* GetExtensionsButton() const;
 
+  // Gets the extensions toolbar controls.
+  ExtensionsToolbarControls* GetExtensionsToolbarControls() const {
+    return extensions_controls_;
+  }
+
   // Get the view corresponding to the extension |id|, if any.
   ToolbarActionView* GetViewForId(const std::string& id);
 
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index eac6f2c..0bd00fc 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -91,7 +91,6 @@
 #include "chrome/browser/ui/views/download/download_shelf_web_view.h"
 #include "chrome/browser/ui/views/exclusive_access_bubble_views.h"
 #include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views.h"
-#include "chrome/browser/ui/views/extensions/extensions_side_panel_controller.h"
 #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
 #include "chrome/browser/ui/views/eye_dropper/eye_dropper.h"
 #include "chrome/browser/ui/views/find_bar_host.h"
@@ -771,34 +770,16 @@
   }
 #endif
 
-  // Only either Side Search or the extensions side panel experiment should be
-  // occupying the left aligned side panel at a given time.
-  const bool side_search_enabled =
 #if BUILDFLAG(ENABLE_SIDE_SEARCH)
-      IsSideSearchEnabled(browser_->profile());
-#else
-      false;
-#endif  // BUILDFLAG(ENABLE_SIDE_SEARCH)
-
-  if (browser_->is_type_normal() &&
-      (side_search_enabled ||
-       base::FeatureList::IsEnabled(features::kExtensionsSidePanel))) {
+  if (browser_->is_type_normal() && IsSideSearchEnabled(browser_->profile())) {
     left_aligned_side_panel_ = AddChildView(std::make_unique<SidePanel>(this));
     left_aligned_side_panel_separator_ =
         AddChildView(std::make_unique<ContentsSeparator>());
 
-#if BUILDFLAG(ENABLE_SIDE_SEARCH)
-    if (side_search_enabled) {
-      side_search_controller_ = std::make_unique<SideSearchBrowserController>(
-          left_aligned_side_panel_, this);
-    }
-#endif  // BUILDFLAG(ENABLE_SIDE_SEARCH)
-    if (!side_search_enabled) {
-      extensions_side_panel_controller_ =
-          std::make_unique<ExtensionsSidePanelController>(
-              left_aligned_side_panel_, this);
-    }
+    side_search_controller_ = std::make_unique<SideSearchBrowserController>(
+        left_aligned_side_panel_, this);
   }
+#endif  // BUILDFLAG(ENABLE_SIDE_SEARCH)
 
   // InfoBarContainer needs to be added as a child here for drop-shadow, but
   // needs to come after toolbar in focus order (see EnsureFocusOrder()).
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 72454b4..c2922171 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -63,7 +63,6 @@
 class Browser;
 class ContentsLayoutManager;
 class ExclusiveAccessBubbleViews;
-class ExtensionsSidePanelController;
 class FeaturePromoControllerViews;
 class FullscreenControlHost;
 class InfoBarContainerView;
@@ -194,10 +193,6 @@
     return left_aligned_side_panel_;
   }
 
-  ExtensionsSidePanelController* extensions_side_panel_controller() {
-    return extensions_side_panel_controller_.get();
-  }
-
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   lens::LensSidePanelController* lens_side_panel_controller() {
     return lens_side_panel_controller_.get();
@@ -963,10 +958,6 @@
   SidePanel* left_aligned_side_panel_ = nullptr;
   views::View* left_aligned_side_panel_separator_ = nullptr;
 
-  // A controller that handles extensions hosted in the left aligned side panel.
-  std::unique_ptr<ExtensionsSidePanelController>
-      extensions_side_panel_controller_;
-
   // The Lens side panel.
   SidePanel* lens_side_panel_ = nullptr;
 
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
index 81afcf85..fa9cd3b 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
@@ -7,6 +7,8 @@
 #include <memory>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
@@ -32,8 +34,6 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #include "components/services/app_service/public/cpp/icon_loader.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h
index 34cc564..e33633d 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h
@@ -13,6 +13,7 @@
 #include "ui/events/event_observer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/event_monitor.h"
+#include "ui/views/metadata/view_factory.h"
 
 namespace content {
 class WebContents;
@@ -118,4 +119,11 @@
   DisplayReason display_reason_ = AUTOMATIC;
 };
 
+BEGIN_VIEW_BUILDER(,
+                   LocationBarBubbleDelegateView,
+                   views::BubbleDialogDelegateView)
+END_VIEW_BUILDER
+
+DEFINE_VIEW_BUILDER(, LocationBarBubbleDelegateView)
+
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_BAR_BUBBLE_DELEGATE_VIEW_H_
diff --git a/chrome/browser/ui/views/payments/secure_payment_confirmation_views_util.cc b/chrome/browser/ui/views/payments/secure_payment_confirmation_views_util.cc
index 146adc5..f57ebcf 100644
--- a/chrome/browser/ui/views/payments/secure_payment_confirmation_views_util.cc
+++ b/chrome/browser/ui/views/payments/secure_payment_confirmation_views_util.cc
@@ -19,7 +19,7 @@
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/progress_bar.h"
-#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/box_layout_view.h"
 #include "ui/views/view.h"
 
 namespace payments {
@@ -96,31 +96,23 @@
     int progress_bar_id,
     int header_icon_id,
     bool use_cart_image) {
-  auto header = std::make_unique<views::View>();
-
-  views::GridLayout* layout =
-      header->SetLayoutManager(std::make_unique<views::GridLayout>());
-  views::ColumnSet* columns = layout->AddColumnSet(0);
-  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 1.0,
-                     views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
+  auto header = std::make_unique<views::BoxLayoutView>();
+  header->SetOrientation(views::BoxLayout::Orientation::kVertical);
+  header->SetBetweenChildSpacing(kHeaderIconTopPadding);
 
   // Progress bar
-  layout->StartRow(views::GridLayout::kFixedSize, 0, kProgressBarHeight);
   auto progress_bar = CreateSecurePaymentConfirmationProgressBarView();
   progress_bar->SetID(progress_bar_id);
   progress_bar->SetVisible(false);
-  layout->AddView(std::move(progress_bar));
-
-  layout->AddPaddingRow(views::GridLayout::kFixedSize, kHeaderIconTopPadding);
+  auto* container = header->AddChildView(std::make_unique<views::View>());
+  container->SetPreferredSize(progress_bar->GetPreferredSize());
+  container->AddChildView(std::move(progress_bar));
 
   // Header icon
-  layout->StartRow(
-      views::GridLayout::kFixedSize, 0,
-      use_cart_image ? kShoppingCartHeaderIconHeight : kHeaderIconHeight);
   auto image_view =
       std::make_unique<SecurePaymentConfirmationIconView>(use_cart_image);
   image_view->SetID(header_icon_id);
-  layout->AddView(std::move(image_view));
+  header->AddChildView(std::move(image_view));
 
   return header;
 }
diff --git a/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc b/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc
index 09f0c7fd..6d0c9e2 100644
--- a/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc
+++ b/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.cc
@@ -26,8 +26,9 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/image_view.h"
+#include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
-#include "ui/views/layout/layout_provider.h"
+#include "ui/views/layout/table_layout_view.h"
 #include "ui/views/view.h"
 
 namespace {
@@ -36,13 +37,6 @@
 constexpr int kImageWidthPx = 336;
 constexpr int kImageHeightPx = 252;
 
-// Adds a new small vertical padding row to the current bottom of |layout|.
-void AddSmallPaddingRow(views::GridLayout* layout) {
-  layout->AddPaddingRow(views::GridLayout::kFixedSize,
-                        ChromeLayoutProvider::Get()->GetDistanceMetric(
-                            DISTANCE_UNRELATED_CONTROL_VERTICAL_LARGE));
-}
-
 }  // namespace
 
 namespace sharing_hub {
@@ -81,105 +75,102 @@
 }
 
 void ScreenshotCapturedBubble::Init() {
+  auto* layout_provider = ChromeLayoutProvider::Get();
+
   // Requesting TEXT for trailing prevents extra padding at bottom of dialog.
-  gfx::Insets insets =
-      ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
-          views::DialogContentType::kControl, views::DialogContentType::kText);
-  set_margins(insets);
-
-  // Internal IDs for column layout; no effect on UI.
-  constexpr int kImageColumnSetId = 0;
-  constexpr int kDownloadRowColumnSetId = 1;
-
-  // Add top-level Grid Layout manager for this dialog.
-  views::GridLayout* const layout =
-      SetLayoutManager(std::make_unique<views::GridLayout>());
-
-  // Captured image, with padding and border.
-  views::ColumnSet* column_set_image = layout->AddColumnSet(kImageColumnSetId);
-
-  const int border_radius = views::LayoutProvider::Get()->GetCornerRadiusMetric(
-      views::Emphasis::kHigh);
+  gfx::Insets insets = layout_provider->GetDialogInsetsForContentType(
+      views::DialogContentType::kControl, views::DialogContentType::kText);
+  const int border_radius =
+      layout_provider->GetCornerRadiusMetric(views::Emphasis::kHigh);
 
   int width_padding =
       (kImageWidthPx + border_radius - GetImageSize().width()) / 2;
 
-  column_set_image->AddPaddingColumn(views::GridLayout::kFixedSize,
-                                     width_padding);
-  column_set_image->AddColumn(
-      views::GridLayout::CENTER,  // Center horizontally, do not resize.
-      views::GridLayout::CENTER,  // Align center vertically, do not resize.
-      1.0, views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
   using Alignment = views::ImageView::Alignment;
-  auto image_view = std::make_unique<views::ImageView>();
-  image_view->SetBorder(views::CreateRoundedRectBorder(
-      /*thickness=*/2, border_radius, gfx::kGoogleGrey200));
-  image_view->SetHorizontalAlignment(Alignment::kCenter);
-  image_view->SetVerticalAlignment(Alignment::kCenter);
-  image_view->SetImageSize(GetImageSize());
-  image_view->SetPreferredSize(GetImageSize() +
-                               gfx::Size(border_radius, border_radius));
-  image_view->SetBackground(
-      views::CreateRoundedRectBackground(SK_ColorWHITE, border_radius));
+  auto builder =
+      views::Builder<ScreenshotCapturedBubble>(this)
+          .set_margins(insets)
+          .SetLayoutManager(std::make_unique<views::BoxLayout>(
+              views::BoxLayout::Orientation::kVertical, gfx::Insets(),
+              layout_provider->GetDistanceMetric(
+                  DISTANCE_UNRELATED_CONTROL_VERTICAL_LARGE)))
+          .AddChild(
+              views::Builder<views::TableLayoutView>()
+                  .AddPaddingColumn(views::TableLayout::kFixedSize,
+                                    width_padding)
+                  .AddColumn(views::LayoutAlignment::kCenter,
+                             views::LayoutAlignment::kCenter, 1.0,
+                             views::TableLayout::ColumnSize::kUsePreferred, 0,
+                             0)
+                  .AddPaddingColumn(views::TableLayout::kFixedSize,
+                                    width_padding)
+                  .AddRows(1, views::TableLayout::kFixedSize, 0)
+                  .AddChild(
+                      views::Builder<views::ImageView>()
+                          .SetBorder(views::CreateRoundedRectBorder(
+                              /*thickness=*/2, border_radius,
+                              gfx::kGoogleGrey200))
+                          .SetHorizontalAlignment(Alignment::kCenter)
+                          .SetVerticalAlignment(Alignment::kCenter)
+                          .SetImageSize(GetImageSize())
+                          .SetPreferredSize(
+                              GetImageSize() +
+                              gfx::Size(border_radius, border_radius))
+                          .SetBackground(views::CreateRoundedRectBackground(
+                              SK_ColorWHITE, border_radius))
+                          .SetImage(image_.ToImageSkia())
+                          .SetVisible(true)));
+  auto edit_button =
+      views::Builder<views::MdTextButton>()
+          .SetCallback(
+              base::BindRepeating(&ScreenshotCapturedBubble::EditButtonPressed,
+                                  base::Unretained(this)))
+          .SetText(l10n_util::GetStringUTF16(
+              IDS_BROWSER_SHARING_SCREENSHOT_DIALOG_EDIT_BUTTON_LABEL))
+          .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+          .Build();
 
-  layout->StartRow(views::GridLayout::kFixedSize, kImageColumnSetId);
+  auto download_button =
+      views::Builder<views::MdTextButton>()
+          .SetCallback(base::BindRepeating(
+              &ScreenshotCapturedBubble::DownloadButtonPressed,
+              base::Unretained(this)))
+          .SetText(l10n_util::GetStringUTF16(
+              IDS_BROWSER_SHARING_SCREENSHOT_DIALOG_DOWNLOAD_BUTTON_LABEL))
+          .SetHorizontalAlignment(gfx::ALIGN_RIGHT)
+          .SetProminent(true)
+          .Build();
 
-  image_view->SetImage(image_.ToImageSkia());
-  image_view->SetVisible(true);
-  image_view_ = layout->AddView(std::move(image_view));
-
-  column_set_image->AddPaddingColumn(views::GridLayout::kFixedSize,
-                                     width_padding);
-
-  // Edit button.
-  auto edit_button = std::make_unique<views::MdTextButton>(
-      base::BindRepeating(&ScreenshotCapturedBubble::EditButtonPressed,
-                          base::Unretained(this)),
-      l10n_util::GetStringUTF16(
-          IDS_BROWSER_SHARING_SCREENSHOT_DIALOG_EDIT_BUTTON_LABEL));
-  edit_button->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-
-  // Download button.
-  auto download_button = std::make_unique<views::MdTextButton>(
-      base::BindRepeating(&ScreenshotCapturedBubble::DownloadButtonPressed,
-                          base::Unretained(this)),
-      l10n_util::GetStringUTF16(
-          IDS_BROWSER_SHARING_SCREENSHOT_DIALOG_DOWNLOAD_BUTTON_LABEL));
-  download_button->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
-  download_button->SetProminent(true);
-
-  // Padding
-  AddSmallPaddingRow(layout);
-
-  // Controls row: optional edit button and download button.
-  views::ColumnSet* control_columns =
-      layout->AddColumnSet(kDownloadRowColumnSetId);
-  // Column for edit button.
+  auto download_row = views::Builder<views::TableLayoutView>();
   if (base::FeatureList::IsEnabled(share::kSharingDesktopScreenshotsEdit)) {
-    control_columns->AddColumn(
-        views::GridLayout::LEADING, views::GridLayout::CENTER, 1.0,
-        views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-    layout->StartRow(views::GridLayout::kFixedSize, kDownloadRowColumnSetId);
-
-    int kPaddingEditDownloadButtonPx =
+    const int kPaddingEditDownloadButtonPx =
         kImageWidthPx - edit_button->CalculatePreferredSize().width() -
         download_button->CalculatePreferredSize().width();
-    // Spacing between the edit and download buttons.
-    control_columns->AddPaddingColumn(views::GridLayout::kFixedSize,
-                                      kPaddingEditDownloadButtonPx);
+
+    download_row
+        .AddColumn(views::LayoutAlignment::kStart,
+                   views::LayoutAlignment::kCenter, 1.0,
+                   views::TableLayout::ColumnSize::kUsePreferred, 0, 0)
+        .AddPaddingColumn(views::TableLayout::kFixedSize,
+                          kPaddingEditDownloadButtonPx);
   }
 
   // Column for download button
-  control_columns->AddColumn(
-      views::GridLayout::TRAILING, views::GridLayout::CENTER, 1.0,
-      views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  layout->StartRow(views::GridLayout::kFixedSize, kDownloadRowColumnSetId);
+  download_row
+      .AddColumn(views::LayoutAlignment::kEnd, views::LayoutAlignment::kCenter,
+                 1.0, views::TableLayout::ColumnSize::kUsePreferred, 0, 0)
+      .AddRows(1, views::TableLayout::kFixedSize, 0);
 
   if (base::FeatureList::IsEnabled(share::kSharingDesktopScreenshotsEdit)) {
-    edit_button_ = layout->AddView(std::move(edit_button));
+    download_row.AddChild(
+        views::Builder<views::MdTextButton>(std::move(edit_button))
+            .CopyAddressTo(&edit_button_));
   }
-  download_button_ = layout->AddView(std::move(download_button));
-  // End controls row
+  download_row.AddChild(
+      views::Builder<views::MdTextButton>(std::move(download_button))
+          .CopyAddressTo(&download_button_));
+
+  std::move(builder).AddChild(std::move(download_row)).BuildChildren();
 }
 
 /*static*/
diff --git a/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.h b/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.h
index d772caf..28cb51f 100644
--- a/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.h
+++ b/chrome/browser/ui/views/sharing_hub/screenshot/screenshot_captured_bubble.h
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/metadata/view_factory.h"
 
 namespace content {
 class WebContents;
@@ -73,6 +74,11 @@
   views::LabelButton* edit_button_ = nullptr;
 };
 
+BEGIN_VIEW_BUILDER(, ScreenshotCapturedBubble, LocationBarBubbleDelegateView)
+END_VIEW_BUILDER
+
 }  // namespace sharing_hub
 
+DEFINE_VIEW_BUILDER(, sharing_hub::ScreenshotCapturedBubble)
+
 #endif  // CHROME_BROWSER_UI_VIEWS_SHARING_HUB_SCREENSHOT_SCREENSHOT_CAPTURED_BUBBLE_H_
diff --git a/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc b/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc
new file mode 100644
index 0000000..0d2ce1d
--- /dev/null
+++ b/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.cc
@@ -0,0 +1,139 @@
+// 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/ui/views/side_panel/read_later_side_panel_web_view.h"
+
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/user_education/feature_promo_controller_views.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "ui/views/controls/menu/menu_runner.h"
+
+ReadLaterSidePanelWebView::ReadLaterSidePanelWebView(
+    Browser* browser,
+    base::RepeatingClosure close_cb)
+    : browser_(browser),
+      close_cb_(std::move(close_cb)),
+      contents_wrapper_(std::make_unique<BubbleContentsWrapperT<ReadLaterUI>>(
+          GURL(chrome::kChromeUIReadLaterURL),
+          browser->profile(),
+          IDS_READ_LATER_TITLE,
+          /*webui_resizes_host=*/false,
+          /*esc_closes_ui=*/false)) {
+  SetVisible(false);
+  contents_wrapper_->SetHost(weak_factory_.GetWeakPtr());
+  contents_wrapper_->ReloadWebContents();
+  SetWebContents(contents_wrapper_->web_contents());
+  set_allow_accelerators(true);
+
+  if (base::FeatureList::IsEnabled(features::kSidePanelDragAndDrop)) {
+    extensions::BookmarkManagerPrivateDragEventRouter::CreateForWebContents(
+        contents_wrapper_->web_contents());
+  }
+
+  browser_->tab_strip_model()->AddObserver(this);
+}
+
+void ReadLaterSidePanelWebView::SetVisible(bool visible) {
+  views::WebView::SetVisible(visible);
+  base::RecordAction(
+      base::UserMetricsAction(visible ? "SidePanel.Show" : "SidePanel.Hide"));
+  if (visible) {
+    // Record usage for side panel promo.
+    feature_engagement::TrackerFactory::GetForBrowserContext(
+        browser_->profile())
+        ->NotifyEvent("side_panel_shown");
+
+    // Close IPH for side panel if shown.
+    FeaturePromoControllerViews* const feature_promo_controller =
+        BrowserView::GetBrowserViewForBrowser(browser_)
+            ->feature_promo_controller();
+    feature_promo_controller->CloseBubble(
+        feature_engagement::kIPHReadingListInSidePanelFeature);
+  }
+}
+
+ReadLaterSidePanelWebView::~ReadLaterSidePanelWebView() = default;
+
+void ReadLaterSidePanelWebView::ViewHierarchyChanged(
+    const views::ViewHierarchyChangedDetails& details) {
+  WebView::ViewHierarchyChanged(details);
+  // Ensure the WebContents is in a visible state after being added to the
+  // side panel so the correct lifecycle hooks are triggered.
+  if (details.is_add && details.child == this)
+    contents_wrapper_->web_contents()->WasShown();
+}
+
+void ReadLaterSidePanelWebView::ShowUI() {
+  SetVisible(true);
+  RequestFocus();
+  UpdateActiveURL(browser_->tab_strip_model()->GetActiveWebContents());
+}
+
+void ReadLaterSidePanelWebView::CloseUI() {
+  close_cb_.Run();
+}
+
+void ReadLaterSidePanelWebView::ShowCustomContextMenu(
+    gfx::Point point,
+    std::unique_ptr<ui::MenuModel> menu_model) {
+  ConvertPointToScreen(this, &point);
+  context_menu_model_ = std::move(menu_model);
+  context_menu_runner_ = std::make_unique<views::MenuRunner>(
+      context_menu_model_.get(),
+      views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
+  context_menu_runner_->RunMenuAt(
+      GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
+      views::MenuAnchorPosition::kTopLeft, ui::MENU_SOURCE_MOUSE,
+      contents_wrapper_->web_contents()->GetContentNativeView());
+}
+
+void ReadLaterSidePanelWebView::HideCustomContextMenu() {
+  if (context_menu_runner_)
+    context_menu_runner_->Cancel();
+}
+
+bool ReadLaterSidePanelWebView::HandleKeyboardEvent(
+    content::WebContents* source,
+    const content::NativeWebKeyboardEvent& event) {
+  return unhandled_keyboard_event_handler_.HandleKeyboardEvent(
+      event, GetFocusManager());
+}
+
+void ReadLaterSidePanelWebView::OnTabStripModelChanged(
+    TabStripModel* tab_strip_model,
+    const TabStripModelChange& change,
+    const TabStripSelectionChange& selection) {
+  if (GetVisible() && selection.active_tab_changed())
+    UpdateActiveURL(tab_strip_model->GetActiveWebContents());
+}
+
+void ReadLaterSidePanelWebView::TabChangedAt(content::WebContents* contents,
+                                             int index,
+                                             TabChangeType change_type) {
+  if (GetVisible() && index == browser_->tab_strip_model()->active_index() &&
+      change_type == TabChangeType::kAll) {
+    UpdateActiveURL(browser_->tab_strip_model()->GetWebContentsAt(index));
+  }
+}
+
+void ReadLaterSidePanelWebView::UpdateActiveURL(
+    content::WebContents* contents) {
+  auto* controller = contents_wrapper_->GetWebUIController();
+  if (!controller || !contents)
+    return;
+
+  controller->GetAs<ReadLaterUI>()->SetActiveTabURL(
+      chrome::GetURLToBookmark(contents));
+}
diff --git a/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.h b/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.h
new file mode 100644
index 0000000..a6b1adb
--- /dev/null
+++ b/chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.h
@@ -0,0 +1,77 @@
+// 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_UI_VIEWS_SIDE_PANEL_READ_LATER_SIDE_PANEL_WEB_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_LATER_SIDE_PANEL_WEB_VIEW_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "chrome/browser/ui/views/bubble/bubble_contents_wrapper.h"
+#include "chrome/browser/ui/webui/read_later/read_later_ui.h"
+#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
+#include "ui/views/controls/webview/webview.h"
+
+class Browser;
+
+namespace ui {
+class MenuModel;
+}  // namespace ui
+
+namespace views {
+class MenuRunner;
+}  // namespace views
+
+class ReadLaterSidePanelWebView : public views::WebView,
+                                  public TabStripModelObserver,
+                                  public BubbleContentsWrapper::Host {
+ public:
+  ReadLaterSidePanelWebView(Browser* browser, base::RepeatingClosure close_cb);
+  ReadLaterSidePanelWebView(const ReadLaterSidePanelWebView&) = delete;
+  ReadLaterSidePanelWebView& operator=(const ReadLaterSidePanelWebView&) =
+      delete;
+  ~ReadLaterSidePanelWebView() override;
+
+  void SetVisible(bool visible) override;
+
+  void ViewHierarchyChanged(
+      const views::ViewHierarchyChangedDetails& details) override;
+
+  // BubbleContentsWrapper::Host:
+  void ShowUI() override;
+  void CloseUI() override;
+  void ShowCustomContextMenu(
+      gfx::Point point,
+      std::unique_ptr<ui::MenuModel> menu_model) override;
+  void HideCustomContextMenu() override;
+  bool HandleKeyboardEvent(
+      content::WebContents* source,
+      const content::NativeWebKeyboardEvent& event) override;
+
+  // TabStripModelObserver:
+  void OnTabStripModelChanged(
+      TabStripModel* tab_strip_model,
+      const TabStripModelChange& change,
+      const TabStripSelectionChange& selection) override;
+
+  void TabChangedAt(content::WebContents* contents,
+                    int index,
+                    TabChangeType change_type) override;
+
+ private:
+  void UpdateActiveURL(content::WebContents* contents);
+
+  Browser* const browser_;
+  base::RepeatingClosure close_cb_;
+  std::unique_ptr<BubbleContentsWrapperT<ReadLaterUI>> contents_wrapper_;
+  std::unique_ptr<views::MenuRunner> context_menu_runner_;
+  std::unique_ptr<ui::MenuModel> context_menu_model_;
+  // A handler to handle unhandled keyboard messages coming back from the
+  // renderer process.
+  views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
+  base::WeakPtrFactory<ReadLaterSidePanelWebView> weak_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_READ_LATER_SIDE_PANEL_WEB_VIEW_H_
diff --git a/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc b/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc
index 31bac5e5..834cb34 100644
--- a/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc
@@ -10,162 +10,23 @@
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
-#include "chrome/browser/feature_engagement/tracker_factory.h"
-#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/read_later/reading_list_model_factory.h"
-#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
-#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/chrome_view_class_properties.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/side_panel/read_later_side_panel_web_view.h"
 #include "chrome/browser/ui/views/side_panel/side_panel.h"
-#include "chrome/browser/ui/views/user_education/feature_promo_controller_views.h"
-#include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/feature_engagement/public/feature_constants.h"
-#include "components/feature_engagement/public/tracker.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/controls/button/button_controller.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/webview/webview.h"
 #include "ui/views/view_class_properties.h"
 
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 #include "chrome/browser/ui/views/lens/lens_side_panel_controller.h"
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
-namespace {
-
-class ReadLaterSidePanelWebView : public views::WebView,
-                                  public TabStripModelObserver,
-                                  public BubbleContentsWrapper::Host {
- public:
-  ReadLaterSidePanelWebView(Browser* browser, base::RepeatingClosure close_cb)
-      : browser_(browser),
-        close_cb_(std::move(close_cb)),
-        contents_wrapper_(std::make_unique<BubbleContentsWrapperT<ReadLaterUI>>(
-            GURL(chrome::kChromeUIReadLaterURL),
-            browser->profile(),
-            IDS_READ_LATER_TITLE,
-            /*webui_resizes_host=*/false,
-            /*esc_closes_ui=*/false)) {
-    SetVisible(false);
-    contents_wrapper_->SetHost(weak_factory_.GetWeakPtr());
-    contents_wrapper_->ReloadWebContents();
-    SetWebContents(contents_wrapper_->web_contents());
-    set_allow_accelerators(true);
-
-    if (base::FeatureList::IsEnabled(features::kSidePanelDragAndDrop)) {
-      extensions::BookmarkManagerPrivateDragEventRouter::CreateForWebContents(
-          contents_wrapper_->web_contents());
-    }
-
-    browser_->tab_strip_model()->AddObserver(this);
-  }
-
-  void SetVisible(bool visible) override {
-    views::WebView::SetVisible(visible);
-    base::RecordAction(
-        base::UserMetricsAction(visible ? "SidePanel.Show" : "SidePanel.Hide"));
-    if (visible) {
-      // Record usage for side panel promo.
-      feature_engagement::TrackerFactory::GetForBrowserContext(
-          browser_->profile())
-          ->NotifyEvent("side_panel_shown");
-
-      // Close IPH for side panel if shown.
-      FeaturePromoControllerViews* const feature_promo_controller =
-          BrowserView::GetBrowserViewForBrowser(browser_)
-              ->feature_promo_controller();
-      feature_promo_controller->CloseBubble(
-          feature_engagement::kIPHReadingListInSidePanelFeature);
-    }
-  }
-
-  void ViewHierarchyChanged(
-      const views::ViewHierarchyChangedDetails& details) override {
-    WebView::ViewHierarchyChanged(details);
-    // Ensure the WebContents is in a visible state after being added to the
-    // side panel so the correct lifecycle hooks are triggered.
-    if (details.is_add && details.child == this)
-      contents_wrapper_->web_contents()->WasShown();
-  }
-
-  // BubbleContentsWrapper::Host:
-  void ShowUI() override {
-    SetVisible(true);
-    RequestFocus();
-    UpdateActiveURL(browser_->tab_strip_model()->GetActiveWebContents());
-  }
-  void CloseUI() override { close_cb_.Run(); }
-  void ShowCustomContextMenu(
-      gfx::Point point,
-      std::unique_ptr<ui::MenuModel> menu_model) override {
-    ConvertPointToScreen(this, &point);
-    context_menu_model_ = std::move(menu_model);
-    context_menu_runner_ = std::make_unique<views::MenuRunner>(
-        context_menu_model_.get(),
-        views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
-    context_menu_runner_->RunMenuAt(
-        GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
-        views::MenuAnchorPosition::kTopLeft, ui::MENU_SOURCE_MOUSE,
-        contents_wrapper_->web_contents()->GetContentNativeView());
-  }
-  void HideCustomContextMenu() override {
-    if (context_menu_runner_)
-      context_menu_runner_->Cancel();
-  }
-  bool HandleKeyboardEvent(
-      content::WebContents* source,
-      const content::NativeWebKeyboardEvent& event) override {
-    return unhandled_keyboard_event_handler_.HandleKeyboardEvent(
-        event, GetFocusManager());
-  }
-
-  // TabStripModelObserver:
-  void OnTabStripModelChanged(
-      TabStripModel* tab_strip_model,
-      const TabStripModelChange& change,
-      const TabStripSelectionChange& selection) override {
-    if (GetVisible() && selection.active_tab_changed())
-      UpdateActiveURL(tab_strip_model->GetActiveWebContents());
-  }
-
-  void TabChangedAt(content::WebContents* contents,
-                    int index,
-                    TabChangeType change_type) override {
-    if (GetVisible() && index == browser_->tab_strip_model()->active_index() &&
-        change_type == TabChangeType::kAll) {
-      UpdateActiveURL(browser_->tab_strip_model()->GetWebContentsAt(index));
-    }
-  }
-
- private:
-  void UpdateActiveURL(content::WebContents* contents) {
-    auto* controller = contents_wrapper_->GetWebUIController();
-    if (!controller || !contents)
-      return;
-
-    controller->GetAs<ReadLaterUI>()->SetActiveTabURL(
-        chrome::GetURLToBookmark(contents));
-  }
-
-  Browser* const browser_;
-  base::RepeatingClosure close_cb_;
-  std::unique_ptr<BubbleContentsWrapperT<ReadLaterUI>> contents_wrapper_;
-  std::unique_ptr<views::MenuRunner> context_menu_runner_;
-  std::unique_ptr<ui::MenuModel> context_menu_model_;
-  // A handler to handle unhandled keyboard messages coming back from the
-  // renderer process.
-  views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
-  base::WeakPtrFactory<ReadLaterSidePanelWebView> weak_factory_{this};
-};
-
-}  // namespace
-
 SidePanelToolbarButton::SidePanelToolbarButton(Browser* browser)
     : ToolbarButton(base::BindRepeating(&SidePanelToolbarButton::ButtonPressed,
                                         base::Unretained(this))),
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 5e0b824..d1155447 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -41,7 +41,6 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h"
 #include "chrome/browser/ui/views/extensions/extension_popup.h"
-#include "chrome/browser/ui/views/extensions/extensions_side_panel_controller.h"
 #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h"
 #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
@@ -300,11 +299,6 @@
   }
 
   // Always add children in order from left to right, for accessibility.
-  if (browser_view_->extensions_side_panel_controller()) {
-    left_side_panel_button_ =
-        AddChildView(browser_view_->extensions_side_panel_controller()
-                         ->CreateToolbarButton());
-  }
   back_ = AddChildView(std::move(back));
   forward_ = AddChildView(std::move(forward));
   reload_ = AddChildView(std::move(reload));
diff --git a/chrome/browser/ui/views/touch_selection_menu_chromeos.cc b/chrome/browser/ui/views/touch_selection_menu_chromeos.cc
index 41449a6..55fd153 100644
--- a/chrome/browser/ui/views/touch_selection_menu_chromeos.cc
+++ b/chrome/browser/ui/views/touch_selection_menu_chromeos.cc
@@ -6,12 +6,12 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/browser/ui/views/touch_selection_menu_runner_chromeos.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/image/image_skia.h"
diff --git a/chrome/browser/ui/views/touch_selection_menu_runner_chromeos.cc b/chrome/browser/ui/views/touch_selection_menu_runner_chromeos.cc
index 192e97315..96ce5fe 100644
--- a/chrome/browser/ui/views/touch_selection_menu_runner_chromeos.cc
+++ b/chrome/browser/ui/views/touch_selection_menu_runner_chromeos.cc
@@ -6,13 +6,13 @@
 
 #include <utility>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/views/touch_selection_menu_chromeos.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "ui/aura/window.h"
 #include "ui/base/layout.h"
 #include "ui/display/display.h"
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index 28e65134..b1127364 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -70,9 +70,9 @@
 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
 #include "ui/views/controls/throbber.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
 #include "ui/views/layout/flex_layout.h"
 #include "ui/views/layout/flex_layout_types.h"
-#include "ui/views/layout/grid_layout.h"
 #include "ui/views/style/platform_style.h"
 #include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
@@ -106,8 +106,7 @@
 std::unique_ptr<views::View> CreateWordmarkView() {
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   auto view = std::make_unique<views::View>();
-  views::GridLayout* layout =
-      view->SetLayoutManager(std::make_unique<views::GridLayout>());
+  view->SetLayoutManager(std::make_unique<views::BoxLayout>());
 
   // Translate icon
   const int translate_icon_id = IDR_TRANSLATE_TAB_WORDMARK;
@@ -117,13 +116,7 @@
       ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
           translate_icon_id);
   translate_icon->SetImage(*translate_icon_image);
-
-  views::ColumnSet* cs = layout->AddColumnSet(0);
-  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  layout->StartRow(1, 0);
-  layout->AddView(std::move(translate_icon));
+  view->AddChildView(std::move(translate_icon));
 
   return view;
 #else
@@ -771,41 +764,17 @@
 
 std::unique_ptr<views::View> TranslateBubbleView::CreateViewErrorNoTitle(
     std::unique_ptr<views::Button> advanced_button) {
+  const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
   auto view = std::make_unique<views::View>();
-  views::GridLayout* layout =
-      view->SetLayoutManager(std::make_unique<views::GridLayout>());
+  views::BoxLayout* layout =
+      view->SetLayoutManager(std::make_unique<views::BoxLayout>(
+          views::BoxLayout::Orientation::kVertical));
+  layout->set_between_child_spacing(
+      provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL));
 
-  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
-
-  enum { COLUMN_SET_ID_TITLE, COLUMN_SET_ID_BUTTONS };
-
-  views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_TITLE);
-  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(1, provider->GetDistanceMetric(
-                              views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-  cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-
-  cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
-  cs->AddPaddingColumn(1.0, 0);
-  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
-  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-
-  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_TITLE);
-
+  // Title row.
+  auto title_row = std::make_unique<views::View>();
+  title_row->SetLayoutManager(std::make_unique<views::FlexLayout>());
   int error_message_id = IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE_TITLE;
   auto error_message_label = std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(error_message_id),
@@ -813,14 +782,25 @@
   const int vertical_spacing =
       provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
   error_message_label->SetLineHeight(vertical_spacing * 5);
+  error_message_label->SetHorizontalAlignment(
+      gfx::HorizontalAlignment::ALIGN_LEFT);
   error_message_label->SetProperty(views::kElementIdentifierKey, kErrorMessage);
-  layout->AddView(std::move(error_message_label));
-  layout->AddView(CreateCloseButton());
+  error_message_label->SetProperty(
+      views::kFlexBehaviorKey,
+      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
+                               views::MaximumFlexSizeRule::kUnbounded));
 
-  layout->StartRowWithPadding(
-      views::GridLayout::kFixedSize, COLUMN_SET_ID_BUTTONS,
-      views::GridLayout::kFixedSize,
-      provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL));
+  title_row->AddChildView(std::move(error_message_label));
+  auto* close_button = title_row->AddChildView(CreateCloseButton());
+  close_button->SetProperty(views::kCrossAxisAlignmentKey,
+                            views::LayoutAlignment::kStart);
+  view->AddChildView(std::move(title_row));
+
+  // Button row.
+  auto button_row = std::make_unique<views::BoxLayoutView>();
+  button_row->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd);
+  button_row->SetBetweenChildSpacing(
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
   auto try_again_button = std::make_unique<views::MdTextButton>(
       base::BindRepeating(
           [](TranslateBubbleModel* model) {
@@ -830,11 +810,16 @@
           base::Unretained(model_.get())),
       l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN));
   try_again_button->SetID(BUTTON_ID_TRY_AGAIN);
-  layout->AddView(std::move(try_again_button));
+  button_row->AddChildView(std::move(try_again_button));
+  button_row->AddChildView(std::move(advanced_button));
+  button_row->SetProperty(
+      views::kMarginsKey,
+      gfx::Insets(0, 0, 0,
+                  provider->GetDistanceMetric(
+                      views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
+  view->AddChildView(std::move(button_row));
 
-  layout->AddView(std::move(advanced_button));
-
-  Layout();
+  // Layout();
   return view;
 }
 
@@ -955,127 +940,75 @@
     std::unique_ptr<views::Button> advanced_reset_button,
     std::unique_ptr<views::Button> advanced_done_button,
     std::unique_ptr<views::Checkbox> advanced_always_translate_checkbox) {
+  const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
   auto view = std::make_unique<AdvancedViewContainer>();
-  views::GridLayout* layout =
-      view->SetLayoutManager(std::make_unique<views::GridLayout>());
+  auto* layout = view->SetLayoutManager(std::make_unique<views::BoxLayout>());
+  layout->set_between_child_spacing(
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
 
   std::unique_ptr<views::ImageView> language_icon = CreateTranslateIcon();
-
-  enum {
-    COLUMN_SET_ID_TITLE,
-    COLUMN_SET_ID_LANGUAGES,
-    COLUMN_SET_ID_ALWAYS_CHECKBOX,
-    COLUMN_SET_ID_BUTTONS
-  };
-
-  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
-
-  views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_TITLE);
-  if (!UseGoogleTranslateBranding()) {
-    cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
-                  views::GridLayout::kFixedSize,
-                  views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-    cs->AddPaddingColumn(views::GridLayout::kFixedSize,
-                         provider->GetDistanceMetric(
-                             views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-  }
-  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(1, provider->GetDistanceMetric(
-                              views::DISTANCE_RELATED_CONTROL_HORIZONTAL) *
-                              4);
-  cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-
-  cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
-
-  if (!UseGoogleTranslateBranding()) {
-    cs->AddPaddingColumn(views::GridLayout::kFixedSize,
-                         language_icon->CalculatePreferredSize().width());
-    cs->AddPaddingColumn(views::GridLayout::kFixedSize,
-                         provider->GetDistanceMetric(
-                             views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-    cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
-                  views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  } else {
-    cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
-                  views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  }
-  cs->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-
-  cs = layout->AddColumnSet(COLUMN_SET_ID_ALWAYS_CHECKBOX);
-  if (!UseGoogleTranslateBranding()) {
-    cs->AddPaddingColumn(views::GridLayout::kFixedSize,
-                         language_icon->CalculatePreferredSize().width());
-    cs->AddPaddingColumn(views::GridLayout::kFixedSize,
-                         provider->GetDistanceMetric(
-                             views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-    cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
-                  views::GridLayout::kFixedSize,
-                  views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  } else {
-    cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
-                  views::GridLayout::kFixedSize,
-                  views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  }
-
-  cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
-  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(
-      1.0, provider->GetDistanceMetric(DISTANCE_UNRELATED_CONTROL_HORIZONTAL));
-  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
-  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize,
-                views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  cs->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
-
-  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_TITLE);
+  const int vertical_spacing =
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
   if (!UseGoogleTranslateBranding()) {
     // If the bottom branding isn't showing, display the leading translate
     // icon otherwise it's not obvious what the bubble is about. This should
     // only happen on non-Chrome-branded builds.
-    layout->AddView(std::move(language_icon));
+    auto* icon_view =
+        view->AddChildView(std::make_unique<views::BoxLayoutView>());
+    icon_view->SetOrientation(views::BoxLayout::Orientation::kVertical);
+    icon_view->AddChildView(std::move(language_icon));
+    icon_view->SetProperty(views::kMarginsKey,
+                           gfx::Insets(vertical_spacing, 0));
   }
-  const int vertical_spacing =
-      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
-  language_title_label->SetLineHeight(vertical_spacing * 5);
-  layout->AddView(std::move(language_title_label));
-  layout->AddView(CreateCloseButton());
+  auto* form_view = view->AddChildView(std::make_unique<views::View>());
+  form_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical, gfx::Insets(),
+      vertical_spacing));
 
-  layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing);
+  language_title_label->SetProperty(
+      views::kMarginsKey,
+      gfx::Insets(vertical_spacing, 0, vertical_spacing,
+                  provider->GetDistanceMetric(
+                      views::DISTANCE_RELATED_CONTROL_HORIZONTAL) *
+                      4));
+  language_title_label->SetProperty(views::kCrossAxisAlignmentKey,
+                                    views::LayoutAlignment::kStart);
+  auto* title_row = form_view->AddChildView(std::make_unique<views::View>());
+  title_row->SetLayoutManager(std::make_unique<views::FlexLayout>());
+  title_row->AddChildView(std::move(language_title_label));
+  title_row->AddChildView(CreateCloseButton())
+      ->SetProperty(views::kCrossAxisAlignmentKey,
+                    views::LayoutAlignment::kStart);
 
-  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_LANGUAGES);
-  layout->AddView(std::move(combobox));
+  form_view->AddChildView(std::move(combobox))
+      ->SetProperty(
+          views::kMarginsKey,
+          gfx::Insets(0, 0, 0,
+                      provider->GetDistanceMetric(
+                          views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
 
+  auto button_row = std::make_unique<views::BoxLayoutView>();
   if (advanced_always_translate_checkbox) {
-    layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing);
-    layout->StartRow(views::GridLayout::kFixedSize,
-                     COLUMN_SET_ID_ALWAYS_CHECKBOX);
     advanced_always_translate_checkbox_ =
-        layout->AddView(std::move(advanced_always_translate_checkbox));
-    layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing * 2);
+        form_view->AddChildView(std::move(advanced_always_translate_checkbox));
+    button_row->SetProperty(views::kMarginsKey,
+                            gfx::Insets(vertical_spacing, 0, 0, 0));
   } else {
-    layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing * 3);
+    button_row->SetProperty(views::kMarginsKey,
+                            gfx::Insets(2 * vertical_spacing, 0, 0, 0));
   }
 
-  layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_BUTTONS);
-  layout->SkipColumns(1);
-
-  layout->AddView(std::move(advanced_reset_button));
-  layout->AddView(std::move(advanced_done_button));
+  button_row->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd);
+  button_row->SetBetweenChildSpacing(
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  button_row->SetProperty(
+      views::kMarginsKey,
+      gfx::Insets(0, 0, 0,
+                  provider->GetDistanceMetric(
+                      views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
+  button_row->AddChildView(std::move(advanced_reset_button));
+  button_row->AddChildView(std::move(advanced_done_button));
+  form_view->AddChildView(std::move(button_row));
 
   UpdateAdvancedView();
 
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h
index 8ed94a83..a60ea64 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.h
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -32,6 +32,10 @@
 
 class Browser;
 
+namespace translate {
+class TranslateBubbleVisualTest;
+}  // namespace translate
+
 namespace views {
 class Checkbox;
 class Combobox;
@@ -136,6 +140,7 @@
   };
 
   friend class TranslateBubbleViewTest;
+  friend class translate::TranslateBubbleVisualTest;
   friend void ::translate::test_utils::PressTranslate(::Browser*);
   friend void ::translate::test_utils::PressRevert(::Browser*);
   friend void ::translate::test_utils::SelectTargetLanguageByDisplayName(
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc
index 75e8184..466576e 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc
@@ -17,6 +17,8 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/translate/translate_bubble_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -163,4 +165,38 @@
   EXPECT_LT(0, counter.GetCount(ax::mojom::Event::kAlert));
 }
 
+class TranslateBubbleVisualTest
+    : public SupportsTestDialog<TranslateBubbleViewBrowserTest> {
+ public:
+  TranslateBubbleVisualTest(const TranslateBubbleVisualTest&) = delete;
+  TranslateBubbleVisualTest& operator=(const TranslateBubbleVisualTest&) =
+      delete;
+
+ protected:
+  TranslateBubbleVisualTest() = default;
+
+  // TestBrowserDialog:
+  void ShowUi(const std::string& name) override {
+    GURL french_url = GURL(embedded_test_server()->GetURL("/french_page.html"));
+    NavigateAndWaitForLanguageDetection(french_url, "fr");
+    DCHECK(TranslateBubbleView::GetCurrentBubble());
+    TranslateBubbleView::GetCurrentBubble()->SwitchView(state_);
+  }
+
+  void set_state(TranslateBubbleModel::ViewState state) { state_ = state; }
+
+ private:
+  TranslateBubbleModel::ViewState state_;
+};
+
+IN_PROC_BROWSER_TEST_F(TranslateBubbleVisualTest, InvokeUi_error) {
+  set_state(TranslateBubbleModel::ViewState::VIEW_STATE_ERROR);
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(TranslateBubbleVisualTest, InvokeUi_advanced) {
+  set_state(TranslateBubbleModel::ViewState::VIEW_STATE_SOURCE_LANGUAGE);
+  ShowAndVerifyUi();
+}
+
 }  // namespace translate
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_interactive_uitest.cc
index 4d75dace..e7b5478 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view_interactive_uitest.cc
@@ -35,11 +35,13 @@
 #include "ui/base/interaction/interaction_sequence.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_features.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/interaction/element_tracker_views.h"
 #include "ui/views/interaction/interaction_sequence_views.h"
+#include "ui/views/test/button_test_api.h"
 
 namespace translate {
 
@@ -82,6 +84,16 @@
   view->HandleAccessibleAction(action_data);
 }
 
+void ButtonClickCallBack(ui::InteractionSequence* sequence,
+                         ui::TrackedElement* element) {
+  // The button might be ignored by HandleAccessibleAction() because it has a
+  // bound of size 0 (not yet laid out). Hence, notify click directly.
+  views::test::ButtonTestApi(
+      static_cast<views::Button*>(ElementToView(element)))
+      .NotifyClick(ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(),
+                                  gfx::Point(), ui::EventTimeForNow(), 0, 0));
+}
+
 }  // namespace
 
 class TranslateBubbleViewUITest
@@ -249,7 +261,7 @@
       // P4.Tap on cancel button option in the translate bubble popup box.
       .AddStep(ui::InteractionSequence::StepBuilder()
                    .SetElementID(TranslateBubbleView::kCloseButton)
-                   .SetStartCallback(base::BindOnce(ElementClickCallback))
+                   .SetStartCallback(base::BindOnce(ButtonClickCallBack))
                    .SetMustRemainVisible(false)
                    .Build())
       // V4.Tapping the close button dismisses the translate bubble.
@@ -316,7 +328,7 @@
               .Build())
       .AddStep(ui::InteractionSequence::StepBuilder()
                    .SetElementID(TranslateBubbleView::kTargetLanguageDoneButton)
-                   .SetStartCallback(base::BindOnce(ElementClickCallback))
+                   .SetStartCallback(base::BindOnce(ButtonClickCallBack))
                    .SetMustRemainVisible(false)
                    .Build())
       // V2. Verify that the language list will be dismissed, the target
@@ -419,7 +431,7 @@
                    .Build())
       .AddStep(ui::InteractionSequence::StepBuilder()
                    .SetElementID(TranslateBubbleView::kSourceLanguageDoneButton)
-                   .SetStartCallback(base::BindOnce(ElementClickCallback))
+                   .SetStartCallback(base::BindOnce(ButtonClickCallBack))
                    .SetMustRemainVisible(false)
                    .Build())
       // V2. The language list will be dismissed, the source language tab
diff --git a/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc b/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
index 71c5c13..7809975 100644
--- a/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
+++ b/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
@@ -30,6 +30,7 @@
 #include "chrome/grit/theme_resources.h"
 #include "chrome/installer/util/experiment.h"
 #include "chrome/installer/util/experiment_storage.h"
+#include "components/strings/grit/components_strings.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
@@ -65,8 +66,12 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout_view.h"
 #include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/table_layout_view.h"
+#include "ui/views/metadata/view_factory.h"
 #include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_removals_observer.h"
 
@@ -171,31 +176,33 @@
 
 // Builds a Win10-styled rectangular button, for this toast displayed outside of
 // the browser.
-std::unique_ptr<views::LabelButton> CreateWin10StyleButton(
+views::Builder<views::LabelButton> CreateWin10StyleButton(
     views::Button::PressedCallback callback,
     const std::u16string& text,
     TryChromeButtonType button_type) {
-  auto button = std::make_unique<views::LabelButton>(std::move(callback), text,
-                                                     CONTEXT_WINDOWS10_NATIVE);
-  button->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-
-  button->SetBackground(views::CreateSolidBackground(
-      button_type == TryChromeButtonType::OPEN_CHROME ? kButtonAcceptColor
-                                                      : kButtonNoThanksColor));
-  button->SetEnabledTextColors(kButtonTextColor);
-  // Request specific 32pt height, 166+pt width.
-  button->SetMinSize(gfx::Size(166, 32));
-  button->SetMaxSize(gfx::Size(0, 32));
-  // Make button focusable for keyboard navigation.
-  button->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
-  return button;
+  return views::Builder<views::LabelButton>(
+             std::make_unique<views::LabelButton>(std::move(callback), text,
+                                                  CONTEXT_WINDOWS10_NATIVE))
+      .SetHorizontalAlignment(gfx::ALIGN_CENTER)
+      .SetBackground(views::CreateSolidBackground(
+          button_type == TryChromeButtonType::OPEN_CHROME
+              ? kButtonAcceptColor
+              : kButtonNoThanksColor))
+      .SetEnabledTextColors(kButtonTextColor)
+      // Request specific 32pt height, 166+pt width.
+      .SetMinSize(gfx::Size(166, 32))
+      .SetMaxSize(gfx::Size(0, 32))
+      // Make button focusable for keyboard navigation.
+      .SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
 }
 
+}  // namespace
+
 // A View that unconditionally reports that it handles mouse presses. This
 // results in the widget capturing the mouse so that it receives a
 // ET_MOUSE_CAPTURE_CHANGED event upon button release following a drag out of
 // the background of the widget.
-class ClickableView : public views::View {
+class ClickableView : public views::BoxLayoutView {
  public:
   METADATA_HEADER(ClickableView);
   ClickableView() = default;
@@ -210,10 +217,13 @@
   return true;
 }
 
-BEGIN_METADATA(ClickableView, views::View)
+BEGIN_VIEW_BUILDER(, ClickableView, views::BoxLayoutView)
+END_VIEW_BUILDER
+
+BEGIN_METADATA(ClickableView, views::BoxLayoutView)
 END_METADATA
 
-}  // namespace
+DEFINE_VIEW_BUILDER(, ClickableView)
 
 // A helper class that determines properties of the desktop on which the popup
 // will be shown, finds Chrome's taskbar icon, and handles calculations to
@@ -1044,8 +1054,10 @@
   // that the logoff was cancelled. The toast may as well be shown.
 
   // Create the popup.
-  auto logo = std::make_unique<views::ImageView>();
-  logo->SetImage(gfx::CreateVectorIcon(kInactiveToastLogoIcon, kHeaderColor));
+  auto logo =
+      views::Builder<views::ImageView>()
+          .SetImage(gfx::CreateVectorIcon(kInactiveToastLogoIcon, kHeaderColor))
+          .Build();
   const gfx::Size logo_size = logo->GetPreferredSize();
 
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
@@ -1057,15 +1069,18 @@
   popup_->AddObserver(this);
   popup_->Init(std::move(params));
 
-  auto contents_view = std::make_unique<ClickableView>();
-  contents_view->SetBackground(
-      views::CreateSolidBackground(kTryChromeBackgroundColor));
-  views::GridLayout* layout =
-      contents_view->SetLayoutManager(std::make_unique<views::GridLayout>());
-  layout->set_minimum_size(gfx::Size(kToastWidth, 0));
-  views::ColumnSet* columns;
-
-  context_->AddBorderToContents(popup_, contents_view.get());
+  auto contents_view =
+      views::Builder<ClickableView>()
+          .SetOrientation(views::BoxLayout::Orientation::kVertical)
+          .SetBackground(
+              views::CreateSolidBackground(kTryChromeBackgroundColor))
+          .SetMinimumCrossAxisSize(kToastWidth)
+          .CustomConfigure(base::BindOnce(
+              [](Context* context, views::Widget* popup,
+                 ClickableView* contents_view) {
+                context->AddBorderToContents(popup, contents_view);
+              },
+              context_.get(), popup_));
 
   // Padding around the left, top, and right of the logo.
   static constexpr int kLogoPadding = 10;
@@ -1085,133 +1100,143 @@
   // header are in the second row.
   const int kLabelWidth = kToastWidth - kLogoPadding - logo_size.width() -
                           kLogoPadding - kSpacingAfterHeadingHorizontal;
-  columns = layout->AddColumnSet(0);
-  columns->AddPaddingColumn(views::GridLayout::kFixedSize,
-                            kLogoPadding - kTryChromeBorderThickness);
-  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
-                     views::GridLayout::kFixedSize,
-                     views::GridLayout::ColumnSize::kFixed, logo_size.width(),
-                     logo_size.height());
-  columns->AddPaddingColumn(views::GridLayout::kFixedSize, kLogoPadding);
-  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1.0,
-                     views::GridLayout::ColumnSize::kFixed, kLabelWidth, 0);
-  columns->AddPaddingColumn(views::GridLayout::kFixedSize,
-                            kSpacingHeadingToClose);
-  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
-                     views::GridLayout::kFixedSize,
-                     views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  columns->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      kCloseButtonRightPadding - kTryChromeBorderThickness);
 
-  // Optional third row: [pad][text].
-  const int logo_padding = logo_size.width() + kLogoPadding;
-  columns = layout->AddColumnSet(1);
-  columns->AddPaddingColumn(
-      views::GridLayout::kFixedSize,
-      kLogoPadding - kTryChromeBorderThickness + logo_padding);
-  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1.0,
-                     views::GridLayout::ColumnSize::kFixed, kLabelWidth, 0);
+  auto table_view =
+      views::Builder<views::TableLayoutView>()
+          .SetIncludeHidden(true)
+          .AddPaddingColumn(views::TableLayout::kFixedSize,
+                            kLogoPadding - kTryChromeBorderThickness)
+          .AddColumn(views::LayoutAlignment::kStart,
+                     views::LayoutAlignment::kStart,
+                     views::TableLayout::kFixedSize,
+                     views::TableLayout::ColumnSize::kFixed, logo_size.width(),
+                     logo_size.height())
+          .AddPaddingColumn(views::TableLayout::kFixedSize, kLogoPadding)
+          .AddColumn(views::LayoutAlignment::kStretch,
+                     views::LayoutAlignment::kStretch, 1.0,
+                     views::TableLayout::ColumnSize::kFixed, kLabelWidth, 0)
+          .AddPaddingColumn(views::TableLayout::kFixedSize,
+                            kSpacingHeadingToClose)
+          .AddColumn(views::LayoutAlignment::kStart,
+                     views::LayoutAlignment::kStart,
+                     views::TableLayout::kFixedSize,
+                     views::TableLayout::ColumnSize::kUsePreferred, 0, 0)
+          .AddPaddingColumn(
+              views::TableLayout::kFixedSize,
+              kCloseButtonRightPadding - kTryChromeBorderThickness)
+          .AddPaddingRow(views::TableLayout::kFixedSize,
+                         kCloseButtonTopPadding - kTryChromeBorderThickness)
+          .AddRows(1, views::TableLayout::kFixedSize,
+                   kLogoPadding - kCloseButtonTopPadding)
+          .AddRows(1, views::TableLayout::kFixedSize, 0)
+          // Skip two columns in this first row
+          .AddChildren(views::Builder<views::View>(),
+                       views::Builder<views::View>());
 
-  // Fourth row: [pad][buttons][pad].
-  columns = layout->AddColumnSet(2);
-  columns->AddPaddingColumn(views::GridLayout::kFixedSize,
-                            kTextButtonPadding - kTryChromeBorderThickness);
-  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
-                     views::GridLayout::kFixedSize,
-                     views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  columns->AddPaddingColumn(views::GridLayout::kFixedSize,
-                            kTextButtonPadding - kTryChromeBorderThickness);
-
-  // First row.
-  layout->AddPaddingRow(views::GridLayout::kFixedSize,
-                        kCloseButtonTopPadding - kTryChromeBorderThickness);
-  layout->StartRow(views::GridLayout::kFixedSize, 0,
-                   kLogoPadding - kCloseButtonTopPadding);
-  layout->SkipColumns(1);
-  layout->SkipColumns(1);
   // Close button if included in the variant.
   if (kExperiments[group_].close_style ==
           ExperimentVariations::CloseStyle::kCloseX ||
       kExperiments[group_].close_style ==
           ExperimentVariations::CloseStyle::kNoThanksButtonAndCloseX) {
-    auto close_button =
-        std::make_unique<views::ImageButton>(base::BindRepeating(
-            &TryChromeDialog::ButtonPressed, base::Unretained(this),
-            installer::ExperimentMetrics::kSelectedClose));
-    close_button->SetImage(
-        views::Button::STATE_NORMAL,
-        gfx::CreateVectorIcon(kInactiveToastCloseIcon, kBodyColor));
-    DCHECK_EQ(close_button->GetPreferredSize().width(), kCloseButtonWidth);
-    close_button_ = layout->AddView(std::move(close_button), 1, 2);
-    close_button_->SetVisible(false);
+    table_view.AddChild(
+        views::Builder<views::ImageButton>()
+            .CopyAddressTo(&close_button_)
+            .SetCallback(base::BindRepeating(
+                &TryChromeDialog::ButtonPressed, base::Unretained(this),
+                installer::ExperimentMetrics::kSelectedClose))
+            .SetVisible(false)
+            // TODO(crbug.com/1218186): Check this. This is in place to pass
+            // accessibility checks.
+            .SetAccessibleName(l10n_util::GetStringUTF16(IDS_CLOSE))
+            .SetProperty(views::kTableColAndRowSpanKey, gfx::Size(1, 2))
+            .CustomConfigure(
+                base::BindOnce([](views::ImageButton* image_button) {
+                  image_button->SetImage(
+                      views::Button::STATE_NORMAL,
+                      gfx::CreateVectorIcon(kInactiveToastCloseIcon,
+                                            kBodyColor));
+                  DCHECK_EQ(image_button->GetPreferredSize().width(),
+                            kCloseButtonWidth);
+                })));
   } else {
-    layout->SkipColumns(1);
+    table_view.AddChild(views::Builder<views::View>().SetProperty(
+        views::kTableColAndRowSpanKey, gfx::Size(1, 2)));
   }
 
-  // Second row.
-  layout->StartRow(views::GridLayout::kFixedSize, 0);
-  layout->AddView(std::move(logo));
-  // All variants have a main header.
-  auto header = std::make_unique<views::Label>(
-      l10n_util::GetStringUTF16(kExperiments[group_].heading_id),
-      CONTEXT_WINDOWS10_NATIVE);
-  header->SetBackgroundColor(kTryChromeBackgroundColor);
-  header->SetEnabledColor(kHeaderColor);
-  header->SetMultiLine(true);
-  header->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  layout->AddView(std::move(header));
-  layout->SkipColumns(1);
+  table_view.AddChildren(
+      views::Builder<views::ImageView>(std::move(logo)),
+      views::Builder<views::Label>()
+          .SetText(l10n_util::GetStringUTF16(kExperiments[group_].heading_id))
+          .SetTextContext(CONTEXT_WINDOWS10_NATIVE)
+          .SetBackgroundColor(kTryChromeBackgroundColor)
+          .SetEnabledColor(kHeaderColor)
+          .SetMultiLine(true)
+          .SetHorizontalAlignment(gfx::ALIGN_LEFT));
 
+  contents_view.AddChild(std::move(table_view));
+
+  // Optional third row: [pad][text].
   // Third row: May have text or may be blank.
-  layout->StartRow(views::GridLayout::kFixedSize, 1);
   const int body_string_id = kExperiments[group_].body_id;
   if (body_string_id) {
-    auto body_text = std::make_unique<views::Label>(
-        l10n_util::GetStringUTF16(body_string_id), CONTEXT_WINDOWS10_NATIVE);
-    body_text->SetBackgroundColor(kTryChromeBackgroundColor);
-    body_text->SetEnabledColor(kBodyColor);
-    body_text->SetMultiLine(true);
-    body_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    layout->AddView(std::move(body_text));
+    const int logo_padding = logo_size.width() + kLogoPadding;
+    contents_view.AddChild(
+        views::Builder<views::Label>()
+            .SetText(l10n_util::GetStringUTF16(body_string_id))
+            .SetTextContext(CONTEXT_WINDOWS10_NATIVE)
+            .SetBackgroundColor(kTryChromeBackgroundColor)
+            .SetMultiLine(true)
+            .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+            .SetProperty(
+                views::kMarginsKey,
+                gfx::Insets(
+                    0, kLogoPadding - kTryChromeBorderThickness + logo_padding,
+                    0, 0)));
   }
 
-  // Fourth row: one or two buttons depending on group.
-  layout->AddPaddingRow(views::GridLayout::kFixedSize, kTextButtonPadding);
-
+  //             [      pad        ].
+  // Fourth row: [pad][buttons][pad].
+  //             [      pad        ].
+  // One or two buttons depending on group.
   static constexpr int kButtonsViewWidth =
       kToastWidth - kTextButtonPadding - kTextButtonPadding;
-  auto buttons = std::make_unique<views::View>();
-  buttons->SetLayoutManager(std::make_unique<ButtonLayout>(kButtonsViewWidth));
-
-  layout->StartRow(views::GridLayout::kFixedSize, 2);
-  auto accept_button = CreateWin10StyleButton(
-      base::BindRepeating(
-          &TryChromeDialog::ButtonPressed, base::Unretained(this),
-          installer::ExperimentMetrics::kSelectedOpenChromeAndNoCrash),
-      l10n_util::GetStringUTF16(IDS_WIN10_TOAST_OPEN_CHROME),
-      TryChromeButtonType::OPEN_CHROME);
-  buttons->AddChildView(accept_button.release());
-
-  if (kExperiments[group_].close_style ==
-          ExperimentVariations::CloseStyle::kNoThanksButton ||
-      kExperiments[group_].close_style ==
-          ExperimentVariations::CloseStyle::kNoThanksButtonAndCloseX) {
-    auto no_thanks_button = CreateWin10StyleButton(
+  auto buttons =
+      views::Builder<views::View>()
+          .SetLayoutManager(std::make_unique<ButtonLayout>(kButtonsViewWidth))
+          .AddChild(CreateWin10StyleButton(
+              base::BindRepeating(
+                  &TryChromeDialog::ButtonPressed, base::Unretained(this),
+                  installer::ExperimentMetrics::kSelectedOpenChromeAndNoCrash),
+              l10n_util::GetStringUTF16(IDS_WIN10_TOAST_OPEN_CHROME),
+              TryChromeButtonType::OPEN_CHROME));
+  const auto style = kExperiments[group_].close_style;
+  if (style == ExperimentVariations::CloseStyle::kNoThanksButton ||
+      style == ExperimentVariations::CloseStyle::kNoThanksButtonAndCloseX) {
+    buttons.AddChild(CreateWin10StyleButton(
         base::BindRepeating(&TryChromeDialog::ButtonPressed,
                             base::Unretained(this),
                             installer::ExperimentMetrics::kSelectedNoThanks),
         l10n_util::GetStringUTF16(IDS_WIN10_TOAST_NO_THANKS),
-        TryChromeButtonType::NO_THANKS);
-    buttons->AddChildView(std::move(no_thanks_button));
+        TryChromeButtonType::NO_THANKS));
   }
 
-  layout->AddView(std::move(buttons));
+  contents_view.AddChild(
+      views::Builder<views::TableLayoutView>()
+          .AddPaddingColumn(views::TableLayout::kFixedSize,
+                            kTextButtonPadding - kTryChromeBorderThickness)
+          .AddColumn(views::LayoutAlignment::kStretch,
+                     views::LayoutAlignment::kStretch,
+                     views::TableLayout::kFixedSize,
+                     views::TableLayout::ColumnSize::kUsePreferred, 0, 0)
+          .AddPaddingColumn(views::TableLayout::kFixedSize,
+                            kTextButtonPadding - kTryChromeBorderThickness)
+          .AddPaddingRow(views::TableLayout::kFixedSize, kTextButtonPadding)
+          .AddRows(1, views::TableLayout::kFixedSize, 0)
+          .AddPaddingRow(views::TableLayout::kFixedSize,
+                         kTextButtonPadding - kTryChromeBorderThickness)
+          .AddChild(std::move(buttons)));
 
-  layout->AddPaddingRow(views::GridLayout::kFixedSize,
-                        kTextButtonPadding - kTryChromeBorderThickness);
-
-  popup_->SetContentsView(std::move(contents_view));
+  popup_->SetContentsView(std::move(contents_view).Build());
 
   // Compute the preferred size after attaching the contents view to the popup,
   // as doing such causes the theme to propagate through the view hierarchy.
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc
index 9b0aa417..86981c9 100644
--- a/chrome/browser/ui/views/uninstall_view.cc
+++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -15,62 +15,28 @@
 #include "chrome/installer/util/shell_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/views/accessibility/accessibility_paint_checks.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
+#include "ui/views/view_class_properties.h"
 #include "ui/views/widget/widget.h"
 
 UninstallView::UninstallView(int* user_selection,
                              const base::RepeatingClosure& quit_closure)
-    : confirm_label_(nullptr),
-      delete_profile_(nullptr),
-      change_default_browser_(nullptr),
-      browsers_combo_(nullptr),
-      user_selection_(*user_selection),
-      quit_closure_(quit_closure) {
-  SetButtonLabel(ui::DIALOG_BUTTON_OK,
-                 l10n_util::GetStringUTF16(IDS_UNINSTALL_BUTTON_TEXT));
-  SetTitle(IDS_UNINSTALL_CHROME);
-  SetAcceptCallback(
-      base::BindOnce(&UninstallView::OnDialogAccepted, base::Unretained(this)));
-  SetCancelCallback(base::BindOnce(&UninstallView::OnDialogCancelled,
-                                   base::Unretained(this)));
-  SetCloseCallback(base::BindOnce(&UninstallView::OnDialogCancelled,
-                                  base::Unretained(this)));
-  set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
-      views::DialogContentType::kText, views::DialogContentType::kText));
+    : user_selection_(*user_selection), quit_closure_(quit_closure) {
   SetupControls();
 }
 
 UninstallView::~UninstallView() {
   // Exit the message loop we were started with so that uninstall can continue.
   quit_closure_.Run();
-
-  // Delete Combobox as it holds a reference to us.
-  delete browsers_combo_;
 }
 
 void UninstallView::SetupControls() {
-  using views::ColumnSet;
-
-  views::GridLayout* layout =
-      SetLayoutManager(std::make_unique<views::GridLayout>());
-
-  // Message to confirm uninstallation.
-  int column_set_id = 0;
-  ColumnSet* column_set = layout->AddColumnSet(column_set_id);
-  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                        views::GridLayout::kFixedSize,
-                        views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  layout->StartRow(views::GridLayout::kFixedSize, column_set_id);
-  auto confirm_label = std::make_unique<views::Label>(
-      l10n_util::GetStringUTF16(IDS_UNINSTALL_VERIFY));
-  confirm_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  confirm_label_ = layout->AddView(std::move(confirm_label));
-
   ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
-
   const int checkbox_indent = provider->GetDistanceMetric(
       DISTANCE_SUBSECTION_HORIZONTAL_INDENT);
   const int unrelated_vertical_spacing =
@@ -82,19 +48,36 @@
   const int related_vertical_small = provider->GetDistanceMetric(
       DISTANCE_RELATED_CONTROL_VERTICAL_SMALL);
 
-  layout->AddPaddingRow(views::GridLayout::kFixedSize,
-                        unrelated_vertical_spacing);
-
-  // The "delete profile" check box.
-  ++column_set_id;
-  column_set = layout->AddColumnSet(column_set_id);
-  column_set->AddPaddingColumn(views::GridLayout::kFixedSize, checkbox_indent);
-  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                        views::GridLayout::kFixedSize,
-                        views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-  layout->StartRow(views::GridLayout::kFixedSize, column_set_id);
-  delete_profile_ = layout->AddView(std::make_unique<views::Checkbox>(
-      l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE)));
+  auto builder =
+      views::Builder<UninstallView>(this)
+          .SetButtonLabel(ui::DIALOG_BUTTON_OK,
+                          l10n_util::GetStringUTF16(IDS_UNINSTALL_BUTTON_TEXT))
+          .SetTitle(IDS_UNINSTALL_CHROME)
+          .SetAcceptCallback(base::BindOnce(&UninstallView::OnDialogAccepted,
+                                            base::Unretained(this)))
+          .SetCancelCallback(base::BindOnce(&UninstallView::OnDialogCancelled,
+                                            base::Unretained(this)))
+          .SetCloseCallback(base::BindOnce(&UninstallView::OnDialogCancelled,
+                                           base::Unretained(this)))
+          .set_margins(provider->GetDialogInsetsForContentType(
+              views::DialogContentType::kText, views::DialogContentType::kText))
+          .SetLayoutManager(std::make_unique<views::BoxLayout>(
+              views::BoxLayout::Orientation::kVertical))
+          .AddChildren(
+              // Message to confirm uninstallation.
+              views::Builder<views::Label>()
+                  .SetText(l10n_util::GetStringUTF16(IDS_UNINSTALL_VERIFY))
+                  .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+                  .SetProperty(
+                      views::kMarginsKey,
+                      gfx::Insets(0, 0, unrelated_vertical_spacing, 0)),
+              // The "delete profile" check box.
+              views::Builder<views::Checkbox>()
+                  .CopyAddressTo(&delete_profile_)
+                  .SetText(
+                      l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE))
+                  .SetProperty(views::kMarginsKey,
+                               gfx::Insets(0, checkbox_indent, 0, 0)));
 
   // Set default browser combo box. If the default should not or cannot be
   // changed, widgets are not shown. We assume here that if Chrome cannot
@@ -105,40 +88,37 @@
     browsers_ = std::make_unique<BrowsersMap>();
     ShellUtil::GetRegisteredBrowsers(browsers_.get());
     if (!browsers_->empty()) {
-      layout->AddPaddingRow(views::GridLayout::kFixedSize,
-                            related_vertical_spacing);
-
-      ++column_set_id;
-      column_set = layout->AddColumnSet(column_set_id);
-      column_set->AddPaddingColumn(views::GridLayout::kFixedSize,
-                                   checkbox_indent);
-      column_set->AddColumn(views::GridLayout::LEADING,
-                            views::GridLayout::CENTER,
-                            views::GridLayout::kFixedSize,
-                            views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-      column_set->AddPaddingColumn(views::GridLayout::kFixedSize,
-                                   related_horizontal_spacing);
-      column_set->AddColumn(views::GridLayout::LEADING,
-                            views::GridLayout::CENTER,
-                            views::GridLayout::kFixedSize,
-                            views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
-      layout->StartRow(views::GridLayout::kFixedSize, column_set_id);
-      change_default_browser_ =
-          layout->AddView(std::make_unique<views::Checkbox>(
-              l10n_util::GetStringUTF16(IDS_UNINSTALL_SET_DEFAULT_BROWSER),
-              base::BindRepeating(
-                  [](UninstallView* view) {
-                    view->browsers_combo_->SetEnabled(
-                        view->change_default_browser_->GetChecked());
-                  },
-                  this)));
-      browsers_combo_ =
-          layout->AddView(std::make_unique<views::Combobox>(this));
-      browsers_combo_->SetEnabled(false);
+      builder.AddChildren(
+          views::Builder<views::View>().SetProperty(
+              views::kMarginsKey,
+              gfx::Insets(related_vertical_spacing, 0, 0, 0)),
+          views::Builder<views::BoxLayoutView>()
+              .SetOrientation(views::BoxLayout::Orientation::kHorizontal)
+              .SetBetweenChildSpacing(related_horizontal_spacing)
+              .AddChildren(
+                  views::Builder<views::Checkbox>()
+                      .CopyAddressTo(&change_default_browser_)
+                      .SetText(l10n_util::GetStringUTF16(
+                          IDS_UNINSTALL_SET_DEFAULT_BROWSER))
+                      .SetCallback(base::BindRepeating(
+                          [](UninstallView* view) {
+                            view->browsers_combo_->SetEnabled(
+                                view->change_default_browser_->GetChecked());
+                          },
+                          base::Unretained(this)))
+                      .SetProperty(views::kMarginsKey,
+                                   gfx::Insets(0, checkbox_indent, 0, 0)),
+                  views::Builder<views::Combobox>()
+                      .CopyAddressTo(&browsers_combo_)
+                      .SetModel(this)
+                      .SetEnabled(false)));
     }
   }
 
-  layout->AddPaddingRow(views::GridLayout::kFixedSize, related_vertical_small);
+  std::move(builder)
+      .AddChild(views::Builder<views::View>().SetProperty(
+          views::kMarginsKey, gfx::Insets(related_vertical_small, 0, 0, 0)))
+      .BuildChildren();
 }
 
 void UninstallView::OnDialogAccepted() {
diff --git a/chrome/browser/ui/views/uninstall_view.h b/chrome/browser/ui/views/uninstall_view.h
index fd40fc11..ec5089c 100644
--- a/chrome/browser/ui/views/uninstall_view.h
+++ b/chrome/browser/ui/views/uninstall_view.h
@@ -11,12 +11,12 @@
 #include "base/callback.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/base/models/combobox_model.h"
+#include "ui/views/metadata/view_factory.h"
 #include "ui/views/window/dialog_delegate.h"
 
 namespace views {
 class Checkbox;
 class Combobox;
-class Label;
 }
 
 // UninstallView implements the dialog that confirms Chrome uninstallation
@@ -45,13 +45,17 @@
   void OnDialogAccepted();
   void OnDialogCancelled();
 
-  views::Label* confirm_label_;
-  views::Checkbox* delete_profile_;
-  views::Checkbox* change_default_browser_;
-  views::Combobox* browsers_combo_;
+  views::Checkbox* delete_profile_ = nullptr;
+  views::Checkbox* change_default_browser_ = nullptr;
+  views::Combobox* browsers_combo_ = nullptr;
   std::unique_ptr<BrowsersMap> browsers_;
   int& user_selection_;
   base::RepeatingClosure quit_closure_;
 };
 
+BEGIN_VIEW_BUILDER(, UninstallView, views::DialogDelegateView)
+END_VIEW_BUILDER
+
+DEFINE_VIEW_BUILDER(, UninstallView)
+
 #endif  // CHROME_BROWSER_UI_VIEWS_UNINSTALL_VIEW_H_
diff --git a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
index 9a44c90..f9563707 100644
--- a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/startup/startup_types.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
@@ -498,7 +499,7 @@
 
   // The app should open as a window.
   EXPECT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
   app_loaded_observer.Wait();
 
@@ -549,7 +550,7 @@
 
   // The app should open as a window.
   EXPECT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
   app_loaded_observer.Wait();
 
@@ -604,7 +605,7 @@
 
   // The app should open as a tab.
   EXPECT_TRUE(StartupBrowserCreator().ProcessCmdLineImpl(
-      command_line, base::FilePath(), /*process_startup=*/false,
+      command_line, base::FilePath(), chrome::startup::IsProcessStartup::kNo,
       browser()->profile(), {}));
   app_loaded_observer.Wait();
 
diff --git a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
index 8718a991..3ed2be5 100644
--- a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
@@ -662,27 +662,23 @@
 // The origin trial migration is not needed in Lacros as it will be removed
 // long before Lacros ships.
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_OriginTrialMigration DISABLED_CaptureLinksNewClient
+#define MAYBE_OriginTrialDisabled DISABLED_OriginTrialDisabled
 #else
-#define MAYBE_OriginTrialMigration OriginTrialMigration
+#define MAYBE_OriginTrialDisabled OriginTrialDisabled
 #endif
 // Tests that the DLC origin trial works and that we can migrate off it into
 // the intent handling persistence user preference model seamlessly.
 IN_PROC_BROWSER_TEST_F(WebAppDeclarativeLinkCapturingOriginTrialBrowserTest,
-                       MAYBE_OriginTrialMigration) {
+                       MAYBE_OriginTrialDisabled) {
   ManifestUpdateTask::BypassWindowCloseWaitingForTesting() = true;
 
-  bool serve_token = true;
   content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
-      [&serve_token](
-          content::URLLoaderInterceptor::RequestParams* params) -> bool {
-
+      [](content::URLLoaderInterceptor::RequestParams* params) -> bool {
         if (params->url_request.url.spec() == kTestWebAppUrl) {
           content::URLLoaderInterceptor::WriteResponse(
               kTestWebAppHeaders,
-              base::ReplaceStringPlaceholders(
-                  kTestWebAppBody, {serve_token ? kOriginTrialToken : ""},
-                  nullptr),
+              base::ReplaceStringPlaceholders(kTestWebAppBody,
+                                              {kOriginTrialToken}, nullptr),
               params->client.get());
           return true;
         }
@@ -704,41 +700,10 @@
 
   InstallTestApp(GURL(kTestWebAppUrl), /*await_metric=*/false);
 
-#if !defined(OS_CHROMEOS)
-  // The origin trial is not available outside of Chrome OS.
+  // The origin trial is not available as of M98:
+  // https://groups.google.com/a/chromium.org/g/blink-dev/c/2c4bul4V3GQ/m/Anluh1txBQAJ
   EXPECT_EQ(provider().registrar().GetAppCaptureLinks(app_id_),
             blink::mojom::CaptureLinks::kUndefined);
-  return;
-#endif  // !defined(OS_CHROMEOS)
-
-  // Origin trial should grant the app access.
-  EXPECT_EQ(provider().registrar().GetAppCaptureLinks(app_id_),
-            blink::mojom::CaptureLinks::kNewClient);
-
-  // Open app with the token missing.
-  {
-    WebAppTestManifestUpdatedObserver update_awaiter(&provider().registrar());
-    update_awaiter.BeginListening();
-
-    serve_token = false;
-
-    Browser* app_browser =
-        GetNewBrowserFromNavigation(browser(), GURL(kTestWebAppUrl));
-    // Automatic link capturing should be triggered because DLC is enabled.
-    EXPECT_TRUE(AppBrowserController::IsForWebApp(app_browser, app_id_));
-
-    update_awaiter.Wait();
-  }
-
-  // The app should update to no longer have capture_links defined without the
-  // origin trial.
-  EXPECT_EQ(provider().registrar().GetAppCaptureLinks(app_id_),
-            blink::mojom::CaptureLinks::kUndefined);
-
-  // Automatic link capturing should continue to be enabled.
-  Browser* app_browser =
-      GetNewBrowserFromNavigation(browser(), GURL(kTestWebAppUrl));
-  EXPECT_TRUE(AppBrowserController::IsForWebApp(app_browser, app_id_));
 }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index af1f138..6b10068 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -64,12 +64,14 @@
 #include "base/base64.h"
 #include "base/cxx17_backports.h"
 #include "base/strings/strcat.h"
+#include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/customization/customization_document.h"
 #include "chrome/browser/ash/login/demo_mode/demo_setup_controller.h"
 #include "chrome/browser/ash/login/wizard_controller.h"
 #include "chrome/browser/browser_process_platform_part_chromeos.h"
 #include "chrome/browser/component_updater/cros_component_manager.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/language/core/common/locale_util.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -522,30 +524,73 @@
       chrome::kChromeHostURLs,
       chrome::kChromeHostURLs + chrome::kNumberOfChromeHostURLs);
   std::sort(hosts.begin(), hosts.end());
-  for (const std::string& host : hosts) {
-    html +=
-        "<li><a href='chrome://" + host + "/'>chrome://" + host + "</a></li>\n";
-  }
 
-  html +=
-      "</ul><a id=\"internals\"><h2>List of chrome://internals "
-      "pages</h2></a>\n<ul>\n";
-  std::vector<std::string> internals_paths(
-      chrome::kChromeInternalsPathURLs,
-      chrome::kChromeInternalsPathURLs +
-          chrome::kNumberOfChromeInternalsPathURLs);
-  std::sort(internals_paths.begin(), internals_paths.end());
-  for (const std::string& path : internals_paths) {
-    html += "<li><a href='chrome://internals/" + path +
-            "'>chrome://internals/" + path + "</a></li>\n";
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // If Lacros is active, the user can navigate by hand to os:// URL's but
+  // internally we will still navigate to chrome:// URL's. Note also that
+  // only a subset of URLs might be available in this mode - so we have to
+  // make sure that only allowed URLs are being presented.
+  if (crosapi::browser_util::IsLacrosPrimaryBrowser()) {
+    auto* WebUiControllerFactory = ChromeWebUIControllerFactory::GetInstance();
+    for (const std::string& host : hosts) {
+      // TODO(crbug/1271718): The refactor should make sure that the provided
+      // list can be shown as is without filtering.
+      if (WebUiControllerFactory->CanHandleUrl(GURL("os://" + host)) ||
+          WebUiControllerFactory->CanHandleUrl(GURL("chrome://" + host))) {
+        html +=
+            "<li><a href='chrome://" + host + "/'>os://" + host + "</a></li>\n";
+      }
+    }
+  } else {
+#else
+  {
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+    for (const std::string& host : hosts) {
+      html += "<li><a href='chrome://" + host + "/'>chrome://" + host +
+              "</a></li>\n";
+    }
+
+    html +=
+        "</ul><a id=\"internals\"><h2>List of chrome://internals "
+        "pages</h2></a>\n<ul>\n";
+    std::vector<std::string> internals_paths(
+        chrome::kChromeInternalsPathURLs,
+        chrome::kChromeInternalsPathURLs +
+            chrome::kNumberOfChromeInternalsPathURLs);
+    std::sort(internals_paths.begin(), internals_paths.end());
+    for (const std::string& path : internals_paths) {
+      html += "<li><a href='chrome://internals/" + path +
+              "'>chrome://internals/" + path + "</a></li>\n";
+    }
   }
 
   html += "</ul>\n<h2>For Debug</h2>\n"
       "<p>The following pages are for debugging purposes only. Because they "
       "crash or hang the renderer, they're not linked directly; you can type "
       "them into the address bar if you need them.</p>\n<ul>";
-  for (size_t i = 0; i < chrome::kNumberOfChromeDebugURLs; i++)
-    html += "<li>" + std::string(chrome::kChromeDebugURLs[i]) + "</li>\n";
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // If Lacros is active, the user can navigate by hand to os:// URL's but
+  // internally we will still navigate to chrome:// URL's. Note also that
+  // only a subset of URLs might be available in this mode - so we have to
+  // make sure that only allowed URLs are being presented.
+  if (crosapi::browser_util::IsLacrosPrimaryBrowser()) {
+    auto* WebUiControllerFactory = ChromeWebUIControllerFactory::GetInstance();
+    for (size_t i = 0; i < chrome::kNumberOfChromeDebugURLs; i++) {
+      // TODO(crbug/1271718): The refactor should make sure that the provided
+      // list can be shown as is without filtering.
+      const std::string host = GURL(chrome::kChromeDebugURLs[i]).host();
+      if (WebUiControllerFactory->CanHandleUrl(GURL("os://" + host)) ||
+          WebUiControllerFactory->CanHandleUrl(GURL("chrome://" + host))) {
+        html += "<li>os://" + host + "</li>\n";
+      }
+    }
+  } else {
+#else
+  {
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+    for (size_t i = 0; i < chrome::kNumberOfChromeDebugURLs; i++)
+      html += "<li>" + std::string(chrome::kChromeDebugURLs[i]) + "</li>\n";
+  }
   html += "</ul>\n";
 
   AppendFooter(&html);
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
index 574a6ac..3e447716 100644
--- a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
+++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
@@ -34,8 +34,8 @@
 #include "mojo/public/cpp/bindings/remote.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/components/arc/session/connection_holder.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "components/arc/session/connection_holder.h"
 #endif
 
 using apps::mojom::OptionalBool;
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 da0de68..c9aa286 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -1378,7 +1378,7 @@
       GURL(chrome::kChromeUIOsCroshAppURL), GURL(chrome::kOsUICroshURL),
       GURL(ash::file_manager::kChromeUIFileManagerUntrustedURL),
       GURL(chrome::kChromeUIUntrustedTerminalURL),
-      GURL(chrome::kOsUITerminalURL),
+      GURL(chrome::kOsUITerminalURL), GURL(chrome::kOsUIAboutURL),
       GURL(chrome::kChromeUIAccountManagerErrorURL),
       GURL(chrome::kOsUIAccountManagerErrorURL),
       GURL(chrome::kChromeUIAccountManagerWelcomeURL),
diff --git a/chrome/browser/ui/webui/chromeos/arc_power_control/arc_power_control_handler.cc b/chrome/browser/ui/webui/chromeos/arc_power_control/arc_power_control_handler.cc
index ec2b8644..bdf2fc0 100644
--- a/chrome/browser/ui/webui/chromeos/arc_power_control/arc_power_control_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/arc_power_control/arc_power_control_handler.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/chromeos/arc_power_control/arc_power_control_handler.h"
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/linux_util.h"
 #include "base/process/launch.h"
@@ -19,8 +21,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/arc/mojom/power.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc
index 8d5ea02a..ebd735d 100644
--- a/chrome/browser/ui/webui/inspect_ui.cc
+++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -372,10 +372,8 @@
     return;
 
   const auto& list = args->GetList();
-  const bool enabled =
-      list.size() == 1 && list[0].is_bool() && list[0].GetBool();
-  if (enabled)
-    profile->GetPrefs()->SetBoolean(pref_name, enabled);
+  if (list.size() == 1 && list[0].is_bool())
+    profile->GetPrefs()->SetBoolean(pref_name, list[0].GetBool());
 }
 
 void InspectMessageHandler::HandlePortForwardingConfigCommand(
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index d2142cc..cfe3a3e7 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -33,7 +33,6 @@
 #include "components/security_interstitials/content/blocked_interception_blocking_page.h"
 #include "components/security_interstitials/content/https_only_mode_blocking_page.h"
 #include "components/security_interstitials/content/insecure_form_blocking_page.h"
-#include "components/security_interstitials/content/legacy_tls_blocking_page.h"
 #include "components/security_interstitials/content/mitm_software_blocking_page.h"
 #include "components/security_interstitials/content/origin_policy_ui.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
@@ -203,18 +202,6 @@
       web_contents, cert_error, request_url, nullptr, ssl_info);
 }
 
-std::unique_ptr<LegacyTLSBlockingPage> CreateLegacyTLSBlockingPage(
-    content::WebContents* web_contents) {
-  const int cert_error = net::ERR_SSL_OBSOLETE_VERSION;
-  const GURL request_url("https://example.com");
-
-  net::SSLInfo ssl_info;
-  ssl_info.cert = ssl_info.unverified_cert = CreateFakeCert();
-  ChromeSecurityBlockingPageFactory blocking_page_factory;
-  return blocking_page_factory.CreateLegacyTLSBlockingPage(
-      web_contents, cert_error, request_url, nullptr, ssl_info);
-}
-
 std::unique_ptr<BadClockBlockingPage> CreateBadClockBlockingPage(
     content::WebContents* web_contents) {
   // Set up a fake clock error.
@@ -505,8 +492,6 @@
     interstitial_delegate = CreateMITMSoftwareBlockingPage(web_contents);
   } else if (path_without_query == "/blocked-interception") {
     interstitial_delegate = CreateBlockedInterceptionBlockingPage(web_contents);
-  } else if (path_without_query == "/legacy-tls") {
-    interstitial_delegate = CreateLegacyTLSBlockingPage(web_contents);
   } else if (path_without_query == "/safebrowsing") {
     interstitial_delegate = CreateSafeBrowsingBlockingPage(web_contents);
   } else if (path_without_query == "/clock") {
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
index 994d456..625ca4f89 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
@@ -191,11 +191,6 @@
                    u"Anything you type");
 }
 
-IN_PROC_BROWSER_TEST_F(InterstitialUITest, LegacyTLSInterstitial) {
-  TestInterstitial(GURL("chrome://interstitials/legacy-tls"), "Privacy error",
-                   u"outdated security configuration");
-}
-
 // Tests that back button works after opening an interstitial from
 // chrome://interstitials.
 IN_PROC_BROWSER_TEST_F(InterstitialUITest, InterstitialBackButton) {
diff --git a/chrome/browser/ui/webui/profile_helper.cc b/chrome/browser/ui/webui/profile_helper.cc
index b8b82b51..ae3ab25b 100644
--- a/chrome/browser/ui/webui/profile_helper.cc
+++ b/chrome/browser/ui/webui/profile_helper.cc
@@ -54,8 +54,8 @@
   }
 
   profiles::FindOrCreateNewWindowForProfile(
-      profile, chrome::startup::IS_PROCESS_STARTUP,
-      chrome::startup::IS_FIRST_RUN, false);
+      profile, chrome::startup::IsProcessStartup::kYes,
+      chrome::startup::IsFirstRun::kYes, false);
 }
 
 void DeleteProfileAtPath(base::FilePath file_path,
diff --git a/chrome/browser/ui/webui/read_later/BUILD.gn b/chrome/browser/ui/webui/read_later/BUILD.gn
index 69989e2..ead1ac2 100644
--- a/chrome/browser/ui/webui/read_later/BUILD.gn
+++ b/chrome/browser/ui/webui/read_later/BUILD.gn
@@ -6,7 +6,7 @@
 
 mojom("mojo_bindings") {
   sources = [ "read_later.mojom" ]
-
+  webui_module_path = "/"
   public_deps = [
     "//mojo/public/mojom/base",
     "//ui/base/mojom",
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
index 3ea9c8d9..7c93c30 100644
--- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
@@ -322,6 +322,8 @@
        IDS_BLUETOOTH_DEVICE_LIST_CURRENTLY_CONNECTED},
       {"bluetoothDeviceListPreviouslyConnected",
        IDS_BLUETOOTH_DEVICE_LIST_PREVIOUSLY_CONNECTED},
+      {"bluetoothDeviceListNoConnectedDevices",
+       IDS_BLUETOOTH_DEVICE_LIST_NO_CONNECTED_DEVICES},
   };
   html_source->AddLocalizedStrings(kLocalizedStrings);
   html_source->AddBoolean("enableFastPairFlag", features::IsFastPairEnabled());
diff --git a/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc b/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc
index 95954612..3a3bca821 100644
--- a/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc
@@ -6,6 +6,8 @@
 
 #include <numeric>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/storage_manager/arc_storage_manager.h"
 #include "base/callback_helpers.h"
 #include "base/memory/scoped_refptr.h"
@@ -21,8 +23,6 @@
 #include "chromeos/cryptohome/userdataauth_util.h"
 #include "chromeos/dbus/spaced/spaced_client.h"
 #include "chromeos/dbus/userdataauth/userdataauth_client.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.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/calculator/size_calculator.h b/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h
index 1dec48e1..e061453 100644
--- a/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h
+++ b/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include "ash/components/arc/session/connection_observer.h"
 #include "ash/components/arc/storage_manager/arc_storage_manager.h"
 #include "base/files/file_util.h"
 #include "base/memory/weak_ptr.h"
@@ -19,7 +20,6 @@
 #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "components/arc/mojom/storage_manager.mojom.h"
-#include "components/arc/session/connection_observer.h"
 #include "components/user_manager/user.h"
 
 class Profile;
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
index 892e715..b3f7190 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/fake_arc_session.h"
 #include "base/files/file.h"
 #include "base/files/file_util.h"
@@ -27,7 +28,6 @@
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/spaced/spaced_client.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_web_ui.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
index 4e6d4d6d..24d39de 100644
--- a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "ash/components/arc/arc_prefs.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/audio/cras_audio_handler.h"
 #include "ash/public/cpp/assistant/assistant_setup.h"
 #include "ash/public/cpp/assistant/controller/assistant_controller.h"
@@ -15,7 +16,6 @@
 #include "base/values.h"
 #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h"
 #include "chromeos/services/assistant/public/cpp/assistant_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "content/public/browser/browser_context.h"
 #include "ui/gfx/geometry/rect.h"
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
index ffedf36..d878efc 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -7,6 +7,8 @@
 #include <memory>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/constants/ash_pref_names.h"
 #include "base/bind.h"
 #include "base/values.h"
@@ -22,8 +24,6 @@
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/arc/mojom/net.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/onc/onc_constants.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/search_section.cc b/chrome/browser/ui/webui/settings/chromeos/search_section.cc
index 84fc403..7742cac 100644
--- a/chrome/browser/ui/webui/settings/chromeos/search_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/search_section.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include <vector>
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/assistant/assistant_state.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_util.h"
@@ -21,6 +20,7 @@
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
 #include "chromeos/services/assistant/public/cpp/features.h"
 #include "components/language/core/browser/pref_names.h"
@@ -194,11 +194,12 @@
 
   html_source->AddLocalizedStrings(kLocalizedStrings);
 
-  html_source->AddBoolean("quickAnswersTranslationDisabled",
-                          ash::features::IsQuickAnswersV2TranslationDisabled());
+  html_source->AddBoolean(
+      "quickAnswersTranslationDisabled",
+      chromeos::features::IsQuickAnswersV2TranslationDisabled());
   html_source->AddBoolean(
       "quickAnswersSubToggleEnabled",
-      ash::features::IsQuickAnswersV2SettingsSubToggleEnabled());
+      chromeos::features::IsQuickAnswersV2SettingsSubToggleEnabled());
 }
 
 void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) {
@@ -442,7 +443,7 @@
   SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate();
   updater.RemoveSearchTags(GetQuickAnswersOnSearchConcepts());
 
-  if (ash::features::IsQuickAnswersV2SettingsSubToggleEnabled() &&
+  if (chromeos::features::IsQuickAnswersV2SettingsSubToggleEnabled() &&
       ash::QuickAnswersState::Get()->settings_enabled()) {
     updater.AddSearchTags(GetQuickAnswersOnSearchConcepts());
   }
diff --git a/chrome/browser/ui/webui/version/version_handler.cc b/chrome/browser/ui/webui/version/version_handler.cc
index 764ee9b1..1c04aa8 100644
--- a/chrome/browser/ui/webui/version/version_handler.cc
+++ b/chrome/browser/ui/webui/version/version_handler.cc
@@ -57,6 +57,10 @@
 
 VersionHandler::~VersionHandler() {}
 
+void VersionHandler::OnJavascriptDisallowed() {
+  weak_ptr_factory_.InvalidateWeakPtrs();
+}
+
 void VersionHandler::RegisterMessages() {
   web_ui()->RegisterDeprecatedMessageCallback(
       version_ui::kRequestVersionInfo,
diff --git a/chrome/browser/ui/webui/version/version_handler.h b/chrome/browser/ui/webui/version/version_handler.h
index 811cfb54..7b528b8 100644
--- a/chrome/browser/ui/webui/version/version_handler.h
+++ b/chrome/browser/ui/webui/version/version_handler.h
@@ -22,6 +22,7 @@
   ~VersionHandler() override;
 
   // content::WebUIMessageHandler implementation.
+  void OnJavascriptDisallowed() override;
   void RegisterMessages() override;
 
   // Callback for the "requestVersionInfo" message sent by |chrome.send| in JS.
diff --git a/chrome/browser/ui/webui/whats_new/whats_new_handler.cc b/chrome/browser/ui/webui/whats_new/whats_new_handler.cc
index 193a001..ec7374e6 100644
--- a/chrome/browser/ui/webui/whats_new/whats_new_handler.cc
+++ b/chrome/browser/ui/webui/whats_new/whats_new_handler.cc
@@ -31,71 +31,15 @@
                                         base::Unretained(this)));
 }
 
-void WhatsNewHandler::OnJavascriptAllowed() {}
-
-void WhatsNewHandler::OnJavascriptDisallowed() {
-  weak_ptr_factory_.InvalidateWeakPtrs();
-}
-
 void WhatsNewHandler::HandleInitialize(const base::ListValue* args) {
   const auto& list = args->GetList();
-  CHECK_EQ(2U, list.size());
+  CHECK_EQ(1U, list.size());
   const std::string& callback_id = list[0].GetString();
-  const bool is_auto = list[1].GetBool();
 
   AllowJavascript();
-  if (whats_new::IsRemoteContentDisabled()) {
-    // Just resolve with failure. This shows the error page which is all local
-    // content, so that we don't trigger potentially flaky network requests in
-    // tests.
-    ResolveJavascriptCallback(base::Value(callback_id), base::Value());
-    return;
-  }
-
-  std::string url = whats_new::GetURLForVersion(CHROME_VERSION_MAJOR);
-  // Send back the initial URL for preload, to reduce delay loading the page.
-  FireWebUIListener("preload-url", base::Value(url));
-  fetcher_ = std::make_unique<whats_new::WhatsNewFetcher>(
-      CHROME_VERSION_MAJOR, is_auto,
-      base::BindOnce(&WhatsNewHandler::OnFetchResult,
-                     weak_ptr_factory_.GetWeakPtr(), callback_id));
-}
-
-void WhatsNewHandler::OnFetchResult(const std::string& callback_id,
-                                    bool is_auto,
-                                    bool success,
-                                    bool page_not_found,
-                                    std::unique_ptr<std::string> body) {
-  if (!success && is_auto) {
-    Browser* browser = chrome::FindLastActive();
-    if (!browser)
-      return;
-
-    if (browser->tab_strip_model()->count() == 1) {
-      // Don't close the tab if this is the only tab as doing so will close the
-      // browser right after the user tried to start it. Instead, load the NTP
-      // as a fallback startup experience if What's New failed to load when
-      // being shown automatically.
-      whats_new::LogLoadEvent(whats_new::LoadEvent::kLoadFailAndFallbackToNtp);
-      content::OpenURLParams params(GURL(chrome::kChromeUINewTabPageURL),
-                                    content::Referrer(),
-                                    WindowOpenDisposition::CURRENT_TAB,
-                                    ui::PAGE_TRANSITION_AUTO_BOOKMARK, false);
-      browser->OpenURL(params);
-    } else {
-      // If other startup tabs already exist, close the tab in order to show
-      // them. This destroys the handler so don't do anything else after this.
-      whats_new::LogLoadEvent(whats_new::LoadEvent::kLoadFailAndCloseTab);
-      content::WebContents* contents = web_ui()->GetWebContents();
-      chrome::CloseWebContents(browser, contents, /* add_to_history= */ false);
-    }
-  } else {
-    whats_new::LogLoadEvent(success
-                                ? whats_new::LoadEvent::kLoadSuccess
-                                : whats_new::LoadEvent::kLoadFailAndShowError);
-    ResolveJavascriptCallback(
-        base::Value(callback_id),
-        success ? base::Value(whats_new::GetURLForVersion(CHROME_VERSION_MAJOR))
-                : base::Value());
-  }
+  ResolveJavascriptCallback(
+      base::Value(callback_id),
+      whats_new::IsRemoteContentDisabled()
+          ? base::Value()
+          : base::Value(whats_new::GetServerURL(true).spec()));
 }
diff --git a/chrome/browser/ui/webui/whats_new/whats_new_handler.h b/chrome/browser/ui/webui/whats_new/whats_new_handler.h
index aeeb654..6efa0b1 100644
--- a/chrome/browser/ui/webui/whats_new/whats_new_handler.h
+++ b/chrome/browser/ui/webui/whats_new/whats_new_handler.h
@@ -5,17 +5,12 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_WHATS_NEW_WHATS_NEW_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_WHATS_NEW_WHATS_NEW_HANDLER_H_
 
-#include "base/memory/weak_ptr.h"
 #include "content/public/browser/web_ui_message_handler.h"
 
 namespace base {
 class ListValue;
 }
 
-namespace whats_new {
-class WhatsNewFetcher;
-}
-
 // Page handler for chrome://whats-new.
 class WhatsNewHandler : public content::WebUIMessageHandler {
  public:
@@ -26,19 +21,9 @@
 
  private:
   void HandleInitialize(const base::ListValue* args);
-  void OnFetchResult(const std::string& callback_id,
-                     bool is_auto,
-                     bool success,
-                     bool page_not_found,
-                     std::unique_ptr<std::string> body);
 
   // content::WebUIMessageHandler:
   void RegisterMessages() override;
-  void OnJavascriptAllowed() override;
-  void OnJavascriptDisallowed() override;
-
-  std::unique_ptr<whats_new::WhatsNewFetcher> fetcher_;
-  base::WeakPtrFactory<WhatsNewHandler> weak_ptr_factory_{this};
 };
 
 #endif  // CHROME_BROWSER_UI_WEBUI_WHATS_NEW_WHATS_NEW_HANDLER_H_
diff --git a/chrome/browser/ui/webui/whats_new/whats_new_util.cc b/chrome/browser/ui/webui/whats_new/whats_new_util.cc
index 56b0677..64de306c 100644
--- a/chrome/browser/ui/webui/whats_new/whats_new_util.cc
+++ b/chrome/browser/ui/webui/whats_new/whats_new_util.cc
@@ -3,16 +3,32 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/webui/whats_new/whats_new_util.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/check.h"
 #include "base/feature_list.h"
+#include "base/location.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/common/chrome_version.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/webui_url_constants.h"
 #include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/url_util.h"
 #include "net/http/http_util.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
@@ -42,17 +58,10 @@
   if (!base::FeatureList::IsEnabled(features::kChromeWhatsNewUI))
     return false;
 
-  // M97 does not have a What's New page. Handling this separately here, to
-  // enable early removal of retry logic in the handler and to allow time to
-  // figure out how to query the server side before opening the tab.
-  // To keep consistency for tests, don't follow this special case if remote
-  // content is disabled for testing.
-  if (CHROME_VERSION_MAJOR == 97 && !IsRemoteContentDisabled())
-    return false;
-
   // Show What's New if the page hasn't yet been shown for the current
   // milestone.
   int last_version = local_state->GetInteger(prefs::kLastWhatsNewVersion);
+
   return CHROME_VERSION_MAJOR > last_version;
 }
 
@@ -64,92 +73,153 @@
   local_state->SetInteger(prefs::kLastWhatsNewVersion, CHROME_VERSION_MAJOR);
 }
 
-void LogLoadEvent(whats_new::LoadEvent event) {
-  base::UmaHistogramEnumeration("WhatsNew.LoadEvent", event);
+GURL GetServerURL(bool may_redirect) {
+  return may_redirect
+             ? net::AppendQueryParameter(
+                   GURL(kChromeWhatsNewURL), "version",
+                   base::NumberToString(CHROME_VERSION_MAJOR))
+             : GURL(kChromeWhatsNewURL)
+                   .Resolve(base::StringPrintf("m%d", CHROME_VERSION_MAJOR));
 }
 
-std::string GetURLForVersion(int version) {
-  // Versions prior to m98 don't respect the query parameter. There is no
-  // version for M97. We should never be automatically loading the page for M97,
-  // see ShouldShowForState() in whats_new_util.cc.
-  // TODO (https://crbug.com/1219381): Remove this logic in M98.
-  return version < 98
-             ? base::StringPrintf("%sm%d", whats_new::kChromeWhatsNewURL, 96)
-             : base::StringPrintf("%s/?version=m%d",
-                                  whats_new::kChromeWhatsNewURL, version);
+GURL GetWebUIStartupURL() {
+  return net::AppendQueryParameter(GURL(chrome::kChromeUIWhatsNewURL), "auto",
+                                   "true");
 }
 
-// TODO (https://crbug.com/1255463): Run this logic before opening the tab at
-// all.
-WhatsNewFetcher::WhatsNewFetcher(int version,
-                                 bool is_auto,
-                                 OnFetchResultCallback on_result)
-    : is_auto_(is_auto), callback_(std::move(on_result)) {
-  LogLoadEvent(whats_new::LoadEvent::kLoadStart);
-  auto traffic_annotation =
-      net::DefineNetworkTrafficAnnotation("whats_new_handler", R"(
-        semantics {
-          sender: "What's New Page"
-          description: "Attempts to fetch the content for the What's New page "
-            "to ensure it loads successfully."
-          trigger:
-            "Restarting Chrome after an update. Desktop only."
-          data:
-            "No data sent, other than URL of What's New. "
-            "Data does not contain PII."
-          destination: GOOGLE_OWNED_SERVICE
-        }
-        policy {
-          cookies_allowed: NO
-          setting:
-            "None"
-          chrome_policy {
-            PromotionalTabsEnabled {
-              PromotionalTabsEnabled: false
-            }
+namespace {
+
+void AddWhatsNewTab(Browser* browser) {
+  chrome::AddTabAt(browser, GetWebUIStartupURL(), 0, true);
+  browser->tab_strip_model()->ActivateTabAt(0);
+}
+
+class WhatsNewFetcher : public BrowserListObserver {
+ public:
+  explicit WhatsNewFetcher(Browser* browser) : browser_(browser) {
+    BrowserList::AddObserver(this);
+    LogLoadEvent(LoadEvent::kLoadStart);
+    auto traffic_annotation =
+        net::DefineNetworkTrafficAnnotation("whats_new_handler", R"(
+          semantics {
+            sender: "What's New Page"
+            description: "Attempts to fetch the content for the What's New "
+              "page to ensure it loads successfully."
+            trigger:
+              "Restarting Chrome after an update. Desktop only."
+            data:
+              "No data sent, other than URL of What's New. "
+              "Data does not contain PII."
+            destination: GOOGLE_OWNED_SERVICE
           }
-        })");
-  network::mojom::URLLoaderFactory* loader_factory =
-      g_browser_process->system_network_context_manager()
-          ->GetURLLoaderFactory();
-  auto request = std::make_unique<network::ResourceRequest>();
-  request->url = GURL(GetURLForVersion(version));
-  simple_loader_ =
-      network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
-  simple_loader_->DownloadToString(
-      loader_factory,
-      base::BindOnce(&WhatsNewFetcher::OnResponseLoaded,
-                     base::Unretained(this)),
-      kMaxDownloadBytes);
-}
-
-WhatsNewFetcher::~WhatsNewFetcher() = default;
-
-void WhatsNewFetcher::OnResponseLoaded(std::unique_ptr<std::string> body) {
-  int response_code = simple_loader_->NetError();
-  const auto& headers = simple_loader_->ResponseInfo()
-                            ? simple_loader_->ResponseInfo()->headers
-                            : nullptr;
-  bool success = response_code == net::OK && headers;
-  if (headers) {
-    response_code =
-        net::HttpUtil::MapStatusCodeForHistogram(headers->response_code());
+          policy {
+            cookies_allowed: NO
+            setting:
+              "None"
+            chrome_policy {
+              PromotionalTabsEnabled {
+                PromotionalTabsEnabled: false
+              }
+            }
+          })");
+    network::mojom::URLLoaderFactory* loader_factory =
+        g_browser_process->system_network_context_manager()
+            ->GetURLLoaderFactory();
+    auto request = std::make_unique<network::ResourceRequest>();
+    // Don't allow redirects when checking if the page is valid for the current
+    // milestone.
+    request->url = GetServerURL(false);
+    simple_loader_ = network::SimpleURLLoader::Create(std::move(request),
+                                                      traffic_annotation);
+    // base::Unretained is safe here because only OnResponseLoaded deletes
+    // |this|.
+    simple_loader_->DownloadToString(
+        loader_factory,
+        base::BindOnce(&WhatsNewFetcher::OnResponseLoaded,
+                       base::Unretained(this)),
+        kMaxDownloadBytes);
   }
 
-  base::UmaHistogramSparse("WhatsNew.LoadResponseCode", response_code);
-  success = success && response_code >= 200 && response_code <= 299 && body;
-  bool page_not_found = !success && headers && headers->response_code() == 404;
+  ~WhatsNewFetcher() override { BrowserList::RemoveObserver(this); }
 
-  // Update pref if shown automatically. Do this even if the load failed - we
-  // only want to try once, so that we don't have to re-query for What's New
-  // every time the browser opens.
-  if (is_auto_) {
+  // BrowserListObserver:
+  void OnBrowserRemoved(Browser* browser) override {
+    if (browser != browser_)
+      return;
+
+    browser_closed_or_inactive_ = true;
+    BrowserList::RemoveObserver(this);
+    browser_ = nullptr;
+  }
+
+  void OnBrowserNoLongerActive(Browser* browser) override {
+    if (browser == browser_)
+      browser_closed_or_inactive_ = true;
+  }
+
+  void OnBrowserSetLastActive(Browser* browser) override {
+    if (browser == browser_)
+      browser_closed_or_inactive_ = false;
+  }
+
+ private:
+  static void LogLoadEvent(LoadEvent event) {
+    base::UmaHistogramEnumeration("WhatsNew.LoadEvent", event);
+  }
+
+  void OnResponseLoaded(std::unique_ptr<std::string> body) {
+    int error_or_response_code = simple_loader_->NetError();
+    const auto& headers = simple_loader_->ResponseInfo()
+                              ? simple_loader_->ResponseInfo()->headers
+                              : nullptr;
+    bool success = error_or_response_code == net::OK && headers;
+    if (headers) {
+      error_or_response_code =
+          net::HttpUtil::MapStatusCodeForHistogram(headers->response_code());
+    }
+
+    base::UmaHistogramSparse("WhatsNew.LoadResponseCode",
+                             error_or_response_code);
+    success = success && error_or_response_code >= 200 &&
+              error_or_response_code <= 299 && body;
+
+    // If the browser was closed or moved to the background while What's New was
+    // loading, return early before recording that the user saw the page.
+    if (browser_closed_or_inactive_)
+      return;
+
+    DCHECK(browser_);
+
+    // Update pref if shown automatically. Do this even if the load failed - we
+    // only want to try once, so that the network request only occurs once per
+    // version and not every time the browser opens.
     SetLastVersion(g_browser_process->local_state());
+
+    LogLoadEvent(success ? LoadEvent::kLoadSuccess
+                         : LoadEvent::kLoadFailAndDoNotShow);
+    if (success)
+      AddWhatsNewTab(browser_);
+    delete this;
   }
 
-  // Running this callback might destroy |this| so don't do anything else
-  // afterward.
-  std::move(callback_).Run(is_auto_, success, page_not_found, std::move(body));
+  std::unique_ptr<network::SimpleURLLoader> simple_loader_;
+  Browser* browser_;
+  bool browser_closed_or_inactive_ = false;
+};
+
+}  // namespace
+
+void StartWhatsNewFetch(Browser* browser) {
+  if (IsRemoteContentDisabled()) {
+    // Don't fetch network content if this is the case, just pretend the tab was
+    // retrieved successfully. Do so asynchronously to simulate the production
+    // code better.
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(AddWhatsNewTab, browser));
+    return;
+  }
+
+  new WhatsNewFetcher(browser);
 }
 
 }  // namespace whats_new
diff --git a/chrome/browser/ui/webui/whats_new/whats_new_util.h b/chrome/browser/ui/webui/whats_new/whats_new_util.h
index 489b19f1..4c341af 100644
--- a/chrome/browser/ui/webui/whats_new/whats_new_util.h
+++ b/chrome/browser/ui/webui/whats_new/whats_new_util.h
@@ -5,16 +5,12 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_WHATS_NEW_WHATS_NEW_UTIL_H_
 #define CHROME_BROWSER_UI_WEBUI_WHATS_NEW_WHATS_NEW_UTIL_H_
 
-#include <memory>
-
 #include "base/callback.h"
+#include "url/gurl.h"
 
+class Browser;
 class PrefService;
 
-namespace network {
-class SimpleURLLoader;
-}
-
 namespace whats_new {
 extern const char kChromeWhatsNewURL[];
 extern const char kChromeWhatsNewURLShort[];
@@ -27,11 +23,10 @@
   kLoadFailAndShowError = 2,
   kLoadFailAndFallbackToNtp = 3,
   kLoadFailAndCloseTab = 4,
-  kMaxValue = kLoadFailAndCloseTab,
+  kLoadFailAndDoNotShow = 5,
+  kMaxValue = kLoadFailAndDoNotShow,
 };
 
-void LogLoadEvent(LoadEvent event);
-
 // Disables loading remote content for tests, because this can lead to a
 // redirect if it fails. Most tests don't expect redirects to occur.
 void DisableRemoteContentForTests();
@@ -46,31 +41,18 @@
 // Sets the last What's New version in |local_state| to the current version.
 void SetLastVersion(PrefService* local_state);
 
-// Get the URL for the What's New page for |version|.
-std::string GetURLForVersion(int version);
+// Gets the server side URL for the What's New page for the current version of
+// Chrome. If |may_redirect| is true, return a server URL that will redirect to
+// the closest milestone page. Otherwise, return the direct URL of the current
+// version, which may return 404 if there is no page for this milestone.
+GURL GetServerURL(bool may_redirect);
 
-typedef base::OnceCallback<void(bool is_auto,
-                                bool success,
-                                bool page_not_found,
-                                std::unique_ptr<std::string> body)>
-    OnFetchResultCallback;
+// Return the startup URL for the WebUI page.
+GURL GetWebUIStartupURL();
 
-class WhatsNewFetcher {
- public:
-  WhatsNewFetcher(int version, bool is_auto, OnFetchResultCallback on_result);
-  WhatsNewFetcher(const WhatsNewFetcher&) = delete;
-  WhatsNewFetcher& operator=(const WhatsNewFetcher&) = delete;
-
-  ~WhatsNewFetcher();
-
- private:
-  // Called with the result.
-  void OnResponseLoaded(std::unique_ptr<std::string> body);
-
-  bool is_auto_;
-  OnFetchResultCallback callback_;
-  std::unique_ptr<network::SimpleURLLoader> simple_loader_;
-};
+// Starts fetching the What's New page and will open the page in |browser| if
+// it exists.
+void StartWhatsNewFetch(Browser* browser);
 
 }  // namespace whats_new
 
diff --git a/chrome/browser/web_applications/os_integration_manager.cc b/chrome/browser/web_applications/os_integration_manager.cc
index 4a10300..0f85bb6b 100644
--- a/chrome/browser/web_applications/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration_manager.cc
@@ -257,16 +257,39 @@
     const AppId& app_id,
     base::StringPiece old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
-    const WebApplicationInfo& web_app_info) {
-  if (g_suppress_os_hooks_for_testing_)
+    const WebApplicationInfo& web_app_info,
+    UpdateOsHooksCallback callback) {
+  if (g_suppress_os_hooks_for_testing_) {
+    OsHooksErrors os_hooks_errors;
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), os_hooks_errors));
     return;
+  }
 
-  UpdateFileHandlers(app_id, file_handlers_need_os_update, base::DoNothing());
-  UpdateShortcuts(app_id, old_name, base::DoNothing());
+  OsHooksErrors os_hooks_errors;
+  scoped_refptr<OsHooksBarrier> barrier = base::MakeRefCounted<OsHooksBarrier>(
+      os_hooks_errors, std::move(callback));
+
+  UpdateFileHandlers(app_id, file_handlers_need_os_update,
+                     base::BindOnce(barrier->CreateBarrierCallbackForType(
+                                        OsHookType::kFileHandlers),
+                                    Result::kOk));
+  UpdateShortcuts(app_id, old_name,
+                  base::BindOnce(barrier->CreateBarrierCallbackForType(
+                                     OsHookType::kShortcuts),
+                                 Result::kOk));
   UpdateShortcutsMenu(app_id, web_app_info);
-  UpdateUrlHandlers(app_id, base::DoNothing());
+  UpdateUrlHandlers(
+      app_id,
+      base::BindOnce(
+          [](ResultCallback callback, bool success) {
+            std::move(callback).Run(success ? Result::kOk : Result::kError);
+          },
+          barrier->CreateBarrierCallbackForType(OsHookType::kUrlHandlers)));
   UpdateProtocolHandlers(app_id, /*force_shortcut_updates_if_needed=*/false,
-                         base::DoNothing());
+                         base::BindOnce(barrier->CreateBarrierCallbackForType(
+                                            OsHookType::kProtocolHandlers),
+                                        Result::kOk));
 }
 
 void OsIntegrationManager::GetAppExistingShortCutLocation(
diff --git a/chrome/browser/web_applications/os_integration_manager.h b/chrome/browser/web_applications/os_integration_manager.h
index b6b5fd2..8d4986a 100644
--- a/chrome/browser/web_applications/os_integration_manager.h
+++ b/chrome/browser/web_applications/os_integration_manager.h
@@ -67,6 +67,10 @@
 using UninstallOsHooksCallback =
     base::OnceCallback<void(OsHooksErrors os_hooks_errors)>;
 
+// Callback made after UpdateOsHooks is finished.
+using UpdateOsHooksCallback =
+    base::OnceCallback<void(OsHooksErrors os_hooks_errors)>;
+
 // Used to suppress OS hooks within this object's lifetime.
 using ScopedOsHooksSuppress = std::unique_ptr<base::AutoReset<bool>>;
 
@@ -124,7 +128,8 @@
       const AppId& app_id,
       base::StringPiece old_name,
       FileHandlerUpdateAction file_handlers_need_os_update,
-      const WebApplicationInfo& web_app_info);
+      const WebApplicationInfo& web_app_info,
+      UpdateOsHooksCallback callback);
 
   // Proxy calls for WebAppShortcutManager.
   // virtual for testing
diff --git a/chrome/browser/web_applications/os_integration_manager_unittest.cc b/chrome/browser/web_applications/os_integration_manager_unittest.cc
index fcaf3cf..e4df46b 100644
--- a/chrome/browser/web_applications/os_integration_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration_manager_unittest.cc
@@ -207,7 +207,7 @@
       .Times(1);
 
   manager.UpdateOsHooks(app_id, old_name, FileHandlerUpdateAction::kUpdate,
-                        web_app_info);
+                        web_app_info, base::DoNothing());
 }
 
 TEST_F(OsIntegrationManagerTest, UpdateProtocolHandlers) {
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.cc b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
index 1a91d69e..f964bf26 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.cc
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
@@ -117,9 +117,14 @@
     const AppId& app_id,
     base::StringPiece old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
-    const WebApplicationInfo& web_app_info) {
+    const WebApplicationInfo& web_app_info,
+    UninstallOsHooksCallback callback) {
   if (file_handlers_need_os_update != FileHandlerUpdateAction::kNoUpdate)
     ++num_update_file_handlers_calls_;
+
+  OsHooksErrors os_hooks_errors;
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), os_hooks_errors));
 }
 
 void FakeOsIntegrationManager::SetFileHandlerManager(
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.h b/chrome/browser/web_applications/test/fake_os_integration_manager.h
index 0de6a7d..02360b9 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.h
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.h
@@ -41,7 +41,8 @@
   void UpdateOsHooks(const AppId& app_id,
                      base::StringPiece old_name,
                      FileHandlerUpdateAction file_handlers_need_os_update,
-                     const WebApplicationInfo& web_app_info) override;
+                     const WebApplicationInfo& web_app_info,
+                     UpdateOsHooksCallback callback) override;
 
   size_t num_create_shortcuts_calls() const {
     return num_create_shortcuts_calls_;
diff --git a/chrome/browser/web_applications/web_app_constants.cc b/chrome/browser/web_applications/web_app_constants.cc
index 25a9c31..4ab079df 100644
--- a/chrome/browser/web_applications/web_app_constants.cc
+++ b/chrome/browser/web_applications/web_app_constants.cc
@@ -127,6 +127,8 @@
       return os << "kSuccessOfflineOnlyInstall";
     case InstallResultCode::kSuccessOfflineFallbackInstall:
       return os << "kSuccessOfflineFallbackInstall";
+    case InstallResultCode::kUpdateTaskFailed:
+      return os << "kUpdateTaskFailed";
   }
 }
 
diff --git a/chrome/browser/web_applications/web_app_constants.h b/chrome/browser/web_applications/web_app_constants.h
index 126f984..b10145a 100644
--- a/chrome/browser/web_applications/web_app_constants.h
+++ b/chrome/browser/web_applications/web_app_constants.h
@@ -120,7 +120,10 @@
   // shutdown.
   kInstallTaskDestroyed = 25,
 
-  kMaxValue = kInstallTaskDestroyed,
+  // Web App update due to manifest change failed.
+  kUpdateTaskFailed = 26,
+
+  kMaxValue = kUpdateTaskFailed,
 };
 
 // Checks if InstallResultCode is not a failure.
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index b826013..34645ce1 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -541,10 +541,9 @@
                      std::move(web_app)));
 }
 
-void WebAppInstallFinalizer::OnIconsDataWritten(
-    CommitCallback commit_callback,
-    std::unique_ptr<WebApp> web_app,
-    bool success) {
+void WebAppInstallFinalizer::OnIconsDataWritten(CommitCallback commit_callback,
+                                                std::unique_ptr<WebApp> web_app,
+                                                bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success) {
     std::move(commit_callback).Run(success);
@@ -610,10 +609,27 @@
 
   if (should_update_os_hooks) {
     os_integration_manager().UpdateOsHooks(
-        app_id, old_name, file_handlers_need_os_update, web_app_info);
+        app_id, old_name, file_handlers_need_os_update, web_app_info,
+        base::BindOnce(&WebAppInstallFinalizer::OnUpdateHooksFinished,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+                       app_id, old_name));
+  } else {
+    std::move(callback).Run(app_id,
+                            InstallResultCode::kSuccessAlreadyInstalled);
   }
+}
+
+void WebAppInstallFinalizer::OnUpdateHooksFinished(
+    InstallFinalizedCallback callback,
+    AppId app_id,
+    std::string old_name,
+    web_app::OsHooksErrors os_hooks_errors) {
   registrar().NotifyWebAppManifestUpdated(app_id, old_name);
-  std::move(callback).Run(app_id, InstallResultCode::kSuccessAlreadyInstalled);
+
+  std::move(callback).Run(app_id,
+                          os_hooks_errors.any()
+                              ? InstallResultCode::kUpdateTaskFailed
+                              : InstallResultCode::kSuccessAlreadyInstalled);
 }
 
 WebAppRegistrar& WebAppInstallFinalizer::GetWebAppRegistrar() const {
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index 7605178..47b7cf9 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -197,6 +197,11 @@
       const WebApplicationInfo& web_app_info,
       bool success);
 
+  void OnUpdateHooksFinished(InstallFinalizedCallback callback,
+                             AppId app_id,
+                             std::string old_name,
+                             web_app::OsHooksErrors os_hooks_errors);
+
   WebAppRegistrar* registrar_ = nullptr;
   WebAppSyncBridge* sync_bridge_ = nullptr;
   WebAppUiManager* ui_manager_ = nullptr;
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc
index 73587da3..f3dd5ca 100644
--- a/chrome/browser/web_applications/web_app_install_task.cc
+++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -37,12 +37,12 @@
 #include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/arc/mojom/app.mojom.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "net/base/url_util.h"
 #endif
 
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index d0e69a5..81518954 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -65,13 +65,13 @@
 #include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/components/arc/test/connection_holder_util.h"
 #include "ash/components/arc/test/fake_app_instance.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/arc/test/fake_intent_helper_instance.h"
 #endif
 
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java
index 53342a40..208e591a 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java
@@ -13,10 +13,12 @@
 
     /** Returns the account name to be used when logging. */
     String accountName();
-    /** Returns the session ID to be used when logging without an account. */
-    String signedOutSessionId();
     /** Returns the client instance ID used for reliability logging. */
     String clientInstanceId();
     /** Returns whether this has the same parameters as `other`. */
     boolean loggingParametersEquals(LoggingParameters other);
+    /** Whether attention / interaction logging is enabled. */
+    boolean loggingEnabled();
+    /** Whether view actions may be recorded. */
+    boolean viewActionsEnabled();
 }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
index c03ea0c7..63bf2dbe 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
@@ -31,11 +31,13 @@
     }
 
     /** Returns the account name of the signed-in user, or the empty string. */
+    @Deprecated
     default String getAccountName() {
         return "";
     }
 
     /** Returns the client instance id for this chrome. */
+    @Deprecated
     default String getClientInstanceId() {
         return "";
     }
@@ -130,6 +132,8 @@
      * Stores a view FeedAction for eventual upload. 'data' is a serialized FeedAction protobuf
      * message.
      */
+    default void processViewAction(byte[] data, LoggingParameters loggingParameters) {}
+    @Deprecated
     default void processViewAction(byte[] data) {}
 
     /**
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index f2b40a07..bad8dcb 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1637582157-6d0aca8725f5f30f6f064a070e4e9c9598832cfd.profdata
+chrome-linux-main-1637625527-a7e11685c237070e3140520064a7db5d9ecc3703.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index d2e35a1..176aad9b 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1637582157-9e01b98de0eefd02bfda0fdfe631c48c81b16a28.profdata
+chrome-mac-main-1637625527-12c7d399419ff4b20a5904b629e2fd421dedc654.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 6ba09863..3be8acb 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1637592674-f179fea10c20097c9e2b6d38b8f286f2112b4c09.profdata
+chrome-win32-main-1637636343-2889ed990553da4b25cf3c77d1104fc4900820de.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 772fb5e..feb9cc3 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1637592674-ac9df9e163cdad5c33df0ca85f2887fffd3ed6b6.profdata
+chrome-win64-main-1637636343-14da4c21b5ab5893b91a9454f15f86e69190d4ee.profdata
diff --git a/chrome/common/media/cdm_registration.cc b/chrome/common/media/cdm_registration.cc
index a4d968d1..3db33ba 100644
--- a/chrome/common/media/cdm_registration.cc
+++ b/chrome/common/media/cdm_registration.cc
@@ -57,7 +57,7 @@
   return std::make_unique<content::CdmInfo>(
       kWidevineKeySystem, Robustness::kSoftwareSecure, std::move(capability),
       /*supports_sub_key_systems=*/false, kWidevineCdmDisplayName,
-      kWidevineCdmGuid, version, cdm_library_path, kWidevineCdmFileSystemId);
+      kWidevineCdmType, version, cdm_library_path, kWidevineCdmFileSystemId);
 }
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -309,9 +309,9 @@
   // External Clear Key (ECK) related information.
   // Normal External Clear Key key system.
   const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey";
-  // A variant of ECK key system that has a different GUID.
-  const char kExternalClearKeyDifferentGuidTestKeySystem[] =
-      "org.chromium.externalclearkey.differentguid";
+  // A variant of ECK key system that has a different CDM type.
+  const char kkExternalClearKeyDifferentCdmTypeTestKeySystem[] =
+      "org.chromium.externalclearkey.differentcdmtype";
 
   // Supported codecs are hard-coded in ExternalClearKeyProperties.
   media::CdmCapability capability(
@@ -319,21 +319,21 @@
       {media::CdmSessionType::kTemporary,
        media::CdmSessionType::kPersistentLicense});
 
-  // Register kExternalClearKeyDifferentGuidTestKeySystem first separately.
+  // Register kkExternalClearKeyDifferentCdmTypeTestKeySystem first separately.
   // Otherwise, it'll be treated as a sub-key-system of normal
   // kExternalClearKeyKeySystem. See MultipleCdmTypes test in
   // ECKEncryptedMediaTest.
   cdms->push_back(content::CdmInfo(
-      kExternalClearKeyDifferentGuidTestKeySystem, Robustness::kSoftwareSecure,
-      capability,
+      kkExternalClearKeyDifferentCdmTypeTestKeySystem,
+      Robustness::kSoftwareSecure, capability,
       /*supports_sub_key_systems=*/false, media::kClearKeyCdmDisplayName,
-      media::kClearKeyCdmDifferentGuid, base::Version("0.1.0.0"),
+      media::kClearKeyCdmDifferentCdmType, base::Version("0.1.0.0"),
       clear_key_cdm_path, media::kClearKeyCdmFileSystemId));
 
   cdms->push_back(content::CdmInfo(
       kExternalClearKeyKeySystem, Robustness::kSoftwareSecure, capability,
       /*supports_sub_key_systems=*/true, media::kClearKeyCdmDisplayName,
-      media::kClearKeyCdmGuid, base::Version("0.1.0.0"), clear_key_cdm_path,
+      media::kClearKeyCdmType, base::Version("0.1.0.0"), clear_key_cdm_path,
       media::kClearKeyCdmFileSystemId));
 }
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 3762e64..7d1796c 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -349,6 +349,7 @@
 const char kOsUICroshURL[] = "os://crosh";
 const char kOsUIFileManagerURL[] = "os://file-manager";
 const char kOsUITerminalURL[] = "os://terminal";
+const char kOsUIAboutURL[] = "os://about";
 const char kOsUIAccountManagerErrorURL[] = "os://account-manager-error";
 const char kOsUIAccountManagerWelcomeURL[] = "os://account-manager-welcome";
 const char kOsUIAccountMigrationWelcomeURL[] = "os://account-migration-welcome";
@@ -370,7 +371,6 @@
 const char kOsUIDiagnosticsAppURL[] = "os://diagnostics";
 const char kOsUIDriveInternalsUrl[] = "os://drive-internals";
 const char kOsUIEmojiPickerURL[] = "os://emoji-picker";
-const char kOsUIFlagsURL[] = "os://flags";
 const char kOsUIGpuURL[] = "os://gpu";
 const char kOsUIHistogramsURL[] = "os://histograms";
 const char kOsUIIntenetConfigDialogURL[] = "os://internet-config-dialog";
@@ -449,6 +449,7 @@
 const char kChromeUIAppDisabledHost[] = "app-disabled";
 const char kChromeUIOSSettingsHost[] = "os-settings";
 const char kChromeUIOSSettingsURL[] = "chrome://os-settings/";
+const char kOsUIFlagsURL[] = "os://flags";
 #endif
 
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 30d9a87..539ca6b 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -332,6 +332,7 @@
 extern const char kOsUICroshURL[];
 extern const char kOsUIFileManagerURL[];
 extern const char kOsUITerminalURL[];
+extern const char kOsUIAboutURL[];
 extern const char kOsUIAccountManagerErrorURL[];
 extern const char kOsUIAccountManagerWelcomeURL[];
 extern const char kOsUIAccountMigrationWelcomeURL[];
@@ -353,7 +354,6 @@
 extern const char kOsUIDiagnosticsAppURL[];
 extern const char kOsUIDriveInternalsUrl[];
 extern const char kOsUIEmojiPickerURL[];
-extern const char kOsUIFlagsURL[];
 extern const char kOsUIGpuURL[];
 extern const char kOsUIHistogramsURL[];
 extern const char kOsUIIntenetConfigDialogURL[];
@@ -393,6 +393,7 @@
 extern const char kChromeUIAppDisabledHost[];
 extern const char kChromeUIOSSettingsHost[];
 extern const char kChromeUIOSSettingsURL[];
+extern const char kOsUIFlagsURL[];
 #endif
 
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chrome/credential_provider/test/BUILD.gn b/chrome/credential_provider/test/BUILD.gn
index ec588ce..0ed87ec 100644
--- a/chrome/credential_provider/test/BUILD.gn
+++ b/chrome/credential_provider/test/BUILD.gn
@@ -69,6 +69,5 @@
   data = [
     "//net/tools/testserver/",
     "//third_party/pywebsocket3/src/mod_pywebsocket/",
-    "//third_party/tlslite/",
   ]
 }
diff --git a/chrome/gpu/BUILD.gn b/chrome/gpu/BUILD.gn
index a21e801..d670cbb 100644
--- a/chrome/gpu/BUILD.gn
+++ b/chrome/gpu/BUILD.gn
@@ -30,8 +30,8 @@
   }
   if (is_chromeos_ash) {
     deps += [
+      "//ash/components/arc/video_accelerator",
       "//components/arc/mojom:media",
-      "//components/arc/video_accelerator",
       "//gpu/command_buffer/service",
       "//services/service_manager/public/cpp",
       "//ui/ozone",
diff --git a/chrome/gpu/DEPS b/chrome/gpu/DEPS
index 5e1bd66..ce0b4c1 100644
--- a/chrome/gpu/DEPS
+++ b/chrome/gpu/DEPS
@@ -1,7 +1,7 @@
 include_rules = [
+  "+ash/components/arc/video_accelerator",
   "+chromeos/components/cdm_factory_daemon",
   "+components/arc/mojom",
-  "+components/arc/video_accelerator",
   "+components/metrics",
   "+content/public/child",
   "+content/public/gpu",
diff --git a/chrome/gpu/OWNERS b/chrome/gpu/OWNERS
index 015071a1..4417dc4 100644
--- a/chrome/gpu/OWNERS
+++ b/chrome/gpu/OWNERS
@@ -1,7 +1,7 @@
-file://components/arc/video_accelerator/OWNERS
+file://ash/components/arc/video_accelerator/OWNERS
 file://media/OWNERS
 
-per-file chrome_content_gpu_client*=file://components/arc/video_accelerator/OWNERS
+per-file chrome_content_gpu_client*=file://ash/components/arc/video_accelerator/OWNERS
 
 # For security review
 per-file browser_exposed_gpu_interfaces.cc=set noparent
diff --git a/chrome/gpu/browser_exposed_gpu_interfaces.cc b/chrome/gpu/browser_exposed_gpu_interfaces.cc
index 6546ed50..3443cda7 100644
--- a/chrome/gpu/browser_exposed_gpu_interfaces.cc
+++ b/chrome/gpu/browser_exposed_gpu_interfaces.cc
@@ -14,15 +14,15 @@
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager_proxy.h"
 #include "components/arc/mojom/protected_buffer_manager.mojom.h"
 #include "components/arc/mojom/video_decode_accelerator.mojom.h"
 #include "components/arc/mojom/video_encode_accelerator.mojom.h"
 #include "components/arc/mojom/video_protected_buffer_allocator.mojom.h"
-#include "components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
-#include "components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
-#include "components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
-#include "components/arc/video_accelerator/protected_buffer_manager_proxy.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace {
diff --git a/chrome/gpu/chrome_content_gpu_client.cc b/chrome/gpu/chrome_content_gpu_client.cc
index 065a53ff..c9c97eb 100644
--- a/chrome/gpu/chrome_content_gpu_client.cc
+++ b/chrome/gpu/chrome_content_gpu_client.cc
@@ -19,7 +19,7 @@
 #include "media/media_buildflags.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
 #include "ui/ozone/public/ozone_platform.h"         // nogncheck
 #include "ui/ozone/public/surface_factory_ozone.h"  // nogncheck
 #endif
diff --git a/chrome/installer/linux/common/apt.include b/chrome/installer/linux/common/apt.include
index 1d1a82a5..a9bfd76 100644
--- a/chrome/installer/linux/common/apt.include
+++ b/chrome/installer/linux/common/apt.include
@@ -150,7 +150,40 @@
 G4wjQ+qsWo+wDI9WMdtpNG1toJrSUL4OYa4oX3YogSv5hGrbYIaP4HwO6O2oTMnS
 0lRIGJOqbEQcmKUa/nWT/3NipTnYzyMjMlEQe89YKjd+32tjMfOSdIOvwCGaTizd
 WnKPF77qB9D0v8C/7AdHmEFqf2ZX8vK31aaY+ZpPWG5IHlf6f/buIMBalJOxIBev
-eBqxcHwQ
+eBqxcHwQuQINBGF4DJ8BEACk2Gwau+s/pKmOTnGLMnB3ybQsiVGLRhsw2SqSTvSy
+BthAyW1UAqdRqNA8/FdMlvVuppG8+vCLXPmpP63C+9M2tyQeOR2aVQp+u1EIwN4l
+Pu4wrh6vdtgSRim8uxBdLIHG16z0xxVhE2rM/Ot/gucfkpoEw289VaR7sPmIxfVT
+m1QcqCGiFQl3rZnma6Bz8UOXJoE8wO+LK5WkcdmFz6+Z3BLSb5IL9lhsArFToNq5
+dN2SSTbCTdHRzrRuoCdefYHdxoLCM4kJfggRRgWhKoEJro+ZipESq1T5yHV/iAJy
++3DuC8LbYLvsjt9VZYARw8xIGb90Vj3ThWuMoVr/IVmKT7foC5Whe0PTI/b2frNa
+WCxxC4cRVxMusiBX66mclQ4Mvzwj50G1WKygULYcvPQ81Tg0pvgTKqgxwL9luN9M
+iDVtkn9CZx7NFlszVr+ic7nVJjANnJebFHCEZfJbQo4uIwKfYbhopUkCa41iXpes
+bVzAKqNwePgyNTAMFyYnjAUE8FVUmx7ZJVb15iEbMs38gJKJ/Wb8wtJRflAfkhrE
+zh1M/43WUAU3RfPmXTrGeyDCYKTHiXTnj748uH6U40sB9q+qeEhZdTj0KufjgtWa
+FWsZTkVrtGOaI6xfX6py/k3hjU3es+7ddElxhPBcqNE3pkPRqb9wz+exSdM7hiUz
+NwARAQABiQREBBgBCAAPBQJheAyfAhsCBQkFo5qAAikJEHch9jvTi0eWwV0gBBkB
+CAAGBQJheAyfAAoJEE6yfbKjuIuLggkP/1INRyRToLmY1ms9DTWMQ0lwbBL8J3xu
+/neKIOKVGOdw9zcWlGugUoOthSbT8bjvuybH1Vjx4wFM+cnuMVfjD58Xu6ZpgCHN
+1wXYMuzYweBFKaMg4oSwTKuAJBJ2IhfEm/cAryVvKY2zY+uyzgizx3vAg3sjkAPD
+crSCJP2nkuHcJ3nzUbKNAjmdMsnWDrqqZVwP99nuyMk8bAtueZ0SKvIpCv2wIeYO
+7zkj61vuQOFOGhl98OBui5wUhtgQw//esTWYiGNKSmD3derd2JHVA01tBmCWV4KM
+LDbg3CcMMQ1x3V1me6EG3giwBL1I9xTsBUbEa6eEN9U0zdKvoMbSogON5wCuxAzO
+/CXGMreJtBUupHEc69oTuwe426Ihi3AbRrPAg3tnGGFCt11HoQFNnRPWb3unF8Ul
+A2rSytvwFyQi3pzBYt5VsTIA7NEHGuJs+/Oor6AOInzht1cp7AfmDGfGy2N5ow+4
+GI6FPe2UqIg2+nFiGr9hRZOvXRgLQL8dlDnFChymldxm/J/UFdJGSWRldEDsPrzH
+QESKvsV9EjnJQR5p5zkQK6jx0zqSlDgiNG2GT3/CSvwIdCih6Cl9HThHtYNm3ZYN
+0bU9W2jeoLh3AINNTcrp0tAHZuQLFxukbj56O5eB+nfk67/X2iNii46ZdJQNwbT9
+YN6CstQz+Cnqg7YP/3G6Y6NHIQggXnlYIi3iwN72hEgEqz6vIRK87lBGW2r3eQ0c
+DZuE3+5Q4FYciw+B2RKeDhjdmPHypA5o+RiAyI7JOZwJalqHO3nwJG5sr0rRzcJs
+bGvpbzso2JuTyTURv4tBNq45b9y0Qdzt5PpNrPJbQADJWn+HWsbVJB5gWBTdoQYg
+pyTr84nQyscWAUFTRbmHvtjCCfLdvU8wM7ubAQ5Dwi1pABRttRAMuPA94HzaBF5y
+XkghxHpnW0IcXGiwgch9LQyaO9VSRhiPH6r5Zuk7KvGhHph7SC5JgUn9vJmmp1zc
+d0mXQ2Zh8M81J3Ri3iGPHM2CqplAxXNbIrnztbEJhN2I+77m73Z4d+K1ivg6xQht
+eSZhwhx7/Z3Tl+U2jYOEFIn/UFmV3UxRSJa/jQRcjvMKprSp4tAZ2yJI3babjRbi
+xgUEtlK105/JepxcAdw9vosxO/rR7VqCzu0copdxC0GAH8og+A9/3LPhlRGy3Qhf
+zjy9JHWHj4EIsol02BS8+dWvAoYerkve9O9+h6/B5wM/Yng9BjT+OrNvkfmqK2cs
+pBXwYedOrC4uWcUmueEVrv5P4FF36wJ+ejvPS6vdTxVTdLXjouUHwTQQZVlNjWY3
+cIyj03nZ19c+b30+2FzG/uSnb/ePWsRLY7Iyz4ygr8etweBPnEIvjwpAZxOu
 KEYDATA
 }
 
diff --git a/chrome/installer/linux/common/rpm.include b/chrome/installer/linux/common/rpm.include
index 7b0962f..4931afe 100644
--- a/chrome/installer/linux/common/rpm.include
+++ b/chrome/installer/linux/common/rpm.include
@@ -205,8 +205,41 @@
 G4wjQ+qsWo+wDI9WMdtpNG1toJrSUL4OYa4oX3YogSv5hGrbYIaP4HwO6O2oTMnS
 0lRIGJOqbEQcmKUa/nWT/3NipTnYzyMjMlEQe89YKjd+32tjMfOSdIOvwCGaTizd
 WnKPF77qB9D0v8C/7AdHmEFqf2ZX8vK31aaY+ZpPWG5IHlf6f/buIMBalJOxIBev
-eBqxcHwQ
-=4zaS
+eBqxcHwQuQINBGF4DJ8BEACk2Gwau+s/pKmOTnGLMnB3ybQsiVGLRhsw2SqSTvSy
+BthAyW1UAqdRqNA8/FdMlvVuppG8+vCLXPmpP63C+9M2tyQeOR2aVQp+u1EIwN4l
+Pu4wrh6vdtgSRim8uxBdLIHG16z0xxVhE2rM/Ot/gucfkpoEw289VaR7sPmIxfVT
+m1QcqCGiFQl3rZnma6Bz8UOXJoE8wO+LK5WkcdmFz6+Z3BLSb5IL9lhsArFToNq5
+dN2SSTbCTdHRzrRuoCdefYHdxoLCM4kJfggRRgWhKoEJro+ZipESq1T5yHV/iAJy
++3DuC8LbYLvsjt9VZYARw8xIGb90Vj3ThWuMoVr/IVmKT7foC5Whe0PTI/b2frNa
+WCxxC4cRVxMusiBX66mclQ4Mvzwj50G1WKygULYcvPQ81Tg0pvgTKqgxwL9luN9M
+iDVtkn9CZx7NFlszVr+ic7nVJjANnJebFHCEZfJbQo4uIwKfYbhopUkCa41iXpes
+bVzAKqNwePgyNTAMFyYnjAUE8FVUmx7ZJVb15iEbMs38gJKJ/Wb8wtJRflAfkhrE
+zh1M/43WUAU3RfPmXTrGeyDCYKTHiXTnj748uH6U40sB9q+qeEhZdTj0KufjgtWa
+FWsZTkVrtGOaI6xfX6py/k3hjU3es+7ddElxhPBcqNE3pkPRqb9wz+exSdM7hiUz
+NwARAQABiQREBBgBCAAPBQJheAyfAhsCBQkFo5qAAikJEHch9jvTi0eWwV0gBBkB
+CAAGBQJheAyfAAoJEE6yfbKjuIuLggkP/1INRyRToLmY1ms9DTWMQ0lwbBL8J3xu
+/neKIOKVGOdw9zcWlGugUoOthSbT8bjvuybH1Vjx4wFM+cnuMVfjD58Xu6ZpgCHN
+1wXYMuzYweBFKaMg4oSwTKuAJBJ2IhfEm/cAryVvKY2zY+uyzgizx3vAg3sjkAPD
+crSCJP2nkuHcJ3nzUbKNAjmdMsnWDrqqZVwP99nuyMk8bAtueZ0SKvIpCv2wIeYO
+7zkj61vuQOFOGhl98OBui5wUhtgQw//esTWYiGNKSmD3derd2JHVA01tBmCWV4KM
+LDbg3CcMMQ1x3V1me6EG3giwBL1I9xTsBUbEa6eEN9U0zdKvoMbSogON5wCuxAzO
+/CXGMreJtBUupHEc69oTuwe426Ihi3AbRrPAg3tnGGFCt11HoQFNnRPWb3unF8Ul
+A2rSytvwFyQi3pzBYt5VsTIA7NEHGuJs+/Oor6AOInzht1cp7AfmDGfGy2N5ow+4
+GI6FPe2UqIg2+nFiGr9hRZOvXRgLQL8dlDnFChymldxm/J/UFdJGSWRldEDsPrzH
+QESKvsV9EjnJQR5p5zkQK6jx0zqSlDgiNG2GT3/CSvwIdCih6Cl9HThHtYNm3ZYN
+0bU9W2jeoLh3AINNTcrp0tAHZuQLFxukbj56O5eB+nfk67/X2iNii46ZdJQNwbT9
+YN6CstQz+Cnqg7YP/3G6Y6NHIQggXnlYIi3iwN72hEgEqz6vIRK87lBGW2r3eQ0c
+DZuE3+5Q4FYciw+B2RKeDhjdmPHypA5o+RiAyI7JOZwJalqHO3nwJG5sr0rRzcJs
+bGvpbzso2JuTyTURv4tBNq45b9y0Qdzt5PpNrPJbQADJWn+HWsbVJB5gWBTdoQYg
+pyTr84nQyscWAUFTRbmHvtjCCfLdvU8wM7ubAQ5Dwi1pABRttRAMuPA94HzaBF5y
+XkghxHpnW0IcXGiwgch9LQyaO9VSRhiPH6r5Zuk7KvGhHph7SC5JgUn9vJmmp1zc
+d0mXQ2Zh8M81J3Ri3iGPHM2CqplAxXNbIrnztbEJhN2I+77m73Z4d+K1ivg6xQht
+eSZhwhx7/Z3Tl+U2jYOEFIn/UFmV3UxRSJa/jQRcjvMKprSp4tAZ2yJI3babjRbi
+xgUEtlK105/JepxcAdw9vosxO/rR7VqCzu0copdxC0GAH8og+A9/3LPhlRGy3Qhf
+zjy9JHWHj4EIsol02BS8+dWvAoYerkve9O9+h6/B5wM/Yng9BjT+OrNvkfmqK2cs
+pBXwYedOrC4uWcUmueEVrv5P4FF36wJ+ejvPS6vdTxVTdLXjouUHwTQQZVlNjWY3
+cIyj03nZ19c+b30+2FzG/uSnb/ePWsRLY7Iyz4ygr8etweBPnEIvjwpAZxOu
+=ilBW
 -----END PGP PUBLIC KEY BLOCK-----
 KEYDATA
     rpm --import "$TMPKEY"
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc
index aaf7b72..ad2411d3 100644
--- a/chrome/renderer/cart/commerce_hint_agent.cc
+++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -75,7 +75,7 @@
     "(^https?://cart\\.)"
     "|"
     "(/("
-      "(((my|co|shopping)[-_]?)?(cart|bag)(view|display)?)"
+      "(((my|co|shopping|view)[-_]?)?(cart|bag)(view|display)?)"
       "|"
       "(checkout/([^/]+/)?(basket|bag))"
       "|"
diff --git a/chrome/renderer/cart/commerce_hint_agent_unittest.cc b/chrome/renderer/cart/commerce_hint_agent_unittest.cc
index 390fc6b..06fef2c 100644
--- a/chrome/renderer/cart/commerce_hint_agent_unittest.cc
+++ b/chrome/renderer/cart/commerce_hint_agent_unittest.cc
@@ -214,6 +214,7 @@
     "https://www.wayfair.com/session/public/basket.php",
     "https://www.wayfair.com/v/checkout/basket/add_and_show",
     "https://www.wayfair.com/v/checkout/basket/show",
+    "https://www.webstaurantstore.com/viewcart.cfm",
     "https://www.weightwatchers.com/us/shop/checkout/cart",
     "https://www.westelm.com/shoppingcart/",
     "https://www.wiley.com/en-us/cart",
diff --git a/chrome/renderer/resources/cart/cart_domain_cart_url_regex.json b/chrome/renderer/resources/cart/cart_domain_cart_url_regex.json
index 76bc771..57cb1c9 100644
--- a/chrome/renderer/resources/cart/cart_domain_cart_url_regex.json
+++ b/chrome/renderer/resources/cart/cart_domain_cart_url_regex.json
@@ -49,6 +49,7 @@
 "hmhco.com": "^https://www.hmhco.com/hmhstorefront/cart/?$",
 "homedepot.com": "^https://[^/]+.homedepot.com/mycart/home$",
 "hottopic.com": "^https://www.hottopic.com/cart/?$",
+"houseofbeautyworld.com": "^https://secure.houseofbeautyworld.com/([\\w|-]+/)?cgi-bin",
 "hsn.com": "^https://www.hsn.com/checkout/bag/?$",
 "ikea.com": "^https://[^/]+.ikea.com/(([^/]+/)+)(shoppingcart|checkout/shoppinglist)(/?)",
 "jcpenney.com": "^https://www.jcpenney.com/cart/?$",
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index d8463fa3..f4bbc390 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1418,7 +1418,6 @@
       "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js",
       "//third_party/pywebsocket3/src/mod_pywebsocket/",
       "//third_party/simplejson/",
-      "//third_party/tlslite/",
       "//ui/webui/resources/",
     ]
     data += js2gtest_js_libraries
@@ -2841,7 +2840,6 @@
         "../browser/ui/views/extensions/extension_install_friction_dialog_view_browsertest.cc",
         "../browser/ui/views/extensions/extension_installed_bubble_view_browsertest.cc",
         "../browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc",
-        "../browser/ui/views/extensions/extensions_side_panel_controller_browsertest.cc",
         "../browser/ui/views/extensions/extensions_toolbar_browsertest.cc",
         "../browser/ui/views/extensions/extensions_toolbar_browsertest.h",
         "../browser/ui/views/extensions/media_galleries_dialog_views_browsertest.cc",
@@ -3423,7 +3421,7 @@
         "../browser/ui/ash/capture_mode/recording_service_browsertest.cc",
         "../browser/ui/ash/chrome_new_window_client_browsertest.cc",
         "../browser/ui/ash/clipboard_history_browsertest.cc",
-        "../browser/ui/ash/desks_client_browsertest.cc",
+        "../browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc",
         "../browser/ui/ash/keyboard/keyboard_controller_browsertest.cc",
         "../browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc",
         "../browser/ui/ash/multi_user/test_multi_user_window_manager.cc",
@@ -3604,6 +3602,7 @@
         "//ash/app_list:test_support",
         "//ash/app_list/model:app_list_model",
         "//ash/components/arc:arc_test_support",
+        "//ash/components/arc/enterprise",
         "//ash/components/attestation",
         "//ash/components/attestation:test_support",
         "//ash/components/audio",
@@ -3699,7 +3698,6 @@
         "//chromeos/ui/wm",
         "//components/app_restore",
         "//components/arc:arc_test_support",
-        "//components/arc/enterprise",
         "//components/crash/content/browser/error_reporting:mock_crash_endpoint",
         "//components/device_event_log",
         "//components/drive",
@@ -4091,17 +4089,24 @@
       "../browser/lacros/screen_manager_lacros_browsertest.cc",
       "../browser/lacros/web_contents_can_go_back_observer_browsertest.cc",
       "../browser/metrics/structured/lacros_structured_metrics_recorder_browsertest.cc",
+      "../browser/ui/browser_navigator_browsertest.cc",
+      "../browser/ui/browser_navigator_browsertest.h",
+      "../browser/ui/browser_navigator_browsertest_chromeos.cc",
     ]
 
     deps = [
       ":browser_tests_runner",
       ":test_support",
+      "//chrome/app:command_ids",
       "//chrome/browser/metrics/structured",
       "//chromeos/crosapi/mojom",
       "//chromeos/lacros",
+      "//chromeos/lacros:test_support",
       "//chromeos/services/machine_learning/public/cpp",
       "//chromeos/services/machine_learning/public/cpp:stub",
       "//chromeos/services/machine_learning/public/mojom",
+      "//components/captive_portal/content:content",
+      "//components/captive_portal/core:buildflags",
       "//components/metrics/structured",
       "//components/metrics/structured:structured_events",
       "//components/proxy_config:proxy_config",
@@ -5204,7 +5209,6 @@
     "//google_apis/test/data/",
     "//net/tools/testserver/",
     "//third_party/pywebsocket3/src/mod_pywebsocket/",
-    "//third_party/tlslite/",
     "//tools/metrics/histograms/enums.xml",
   ]
 
@@ -7730,6 +7734,7 @@
       "../browser/ui/views/extensions/expandable_container_view_unittest.cc",
       "../browser/ui/views/extensions/extensions_menu_item_unittest.cc",
       "../browser/ui/views/extensions/extensions_menu_view_unittest.cc",
+      "../browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc",
       "../browser/ui/views/extensions/extensions_toolbar_controls_unittest.cc",
       "../browser/ui/views/extensions/media_galleries_dialog_views_unittest.cc",
       "../browser/ui/views/extensions/settings_overridden_dialog_view_unittest.cc",
@@ -8398,7 +8403,6 @@
       "//third_party/mocha/mocha.js",
       "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js",
       "//third_party/pywebsocket3/src/mod_pywebsocket/",
-      "//third_party/tlslite/",
       "//tools/metrics/histograms/enums.xml",
       "//ui/webui/resources/html/test_loader.html",
       "//ui/webui/resources/js/",
@@ -9089,7 +9093,6 @@
       "//chrome/test/data/banners/",
       "//net/tools/testserver/",
       "//third_party/pywebsocket3/src/mod_pywebsocket/",
-      "//third_party/tlslite/",
     ]
 
     # TODO(phajdan.jr): Only temporary, to make transition easier.
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
index 381443aa..4eddbb6c 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
@@ -24,6 +24,7 @@
 import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.gms.ChromiumPlayServicesAvailability;
+import org.chromium.ui.test.util.DisableAnimationsTestRule;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -56,7 +57,8 @@
 
     @Override
     protected List<TestRule> getDefaultTestRules() {
-        return addToList(super.getDefaultTestRules(), new Features.InstrumentationProcessor());
+        return addToList(super.getDefaultTestRules(), new Features.InstrumentationProcessor(),
+                new DisableAnimationsTestRule());
     }
 
     private static class ChromeRestrictionSkipCheck extends RestrictionSkipCheck {
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_merge.html b/chrome/test/data/client_hints/meta_name_accept_ch_merge.html
new file mode 100644
index 0000000..b298da9
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_merge.html
@@ -0,0 +1,9 @@
+<html>
+<!-- This is split in two since data from header may round trip quickly
+  enough from browser to be used, so this makes sure we actually merge -->
+<meta name="Accept-CH" content="sec-ch-ua-arch,sec-ch-ua-platform">
+<meta name="Accept-CH" content="sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness,sec-ch-viewport-height,sec-ch-ua-full-version-list">
+<link rel="icon" href="data:;base64,=">
+<!-- A subresource! -->
+<img src="non-existing-image.jpg"></img>
+</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_merge.html.mock-http-headers b/chrome/test/data/client_hints/meta_name_accept_ch_merge.html.mock-http-headers
new file mode 100644
index 0000000..756a1c46
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_merge.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Accept-CH: dpr,sec-ch-dpr,device-memory,sec-ch-device-memory,viewport-width,sec-ch-viewport-width,rtt,downlink,ect
+Accept-CH-Lifetime: 3600
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_with_lifetime.html b/chrome/test/data/client_hints/meta_name_accept_ch_with_lifetime.html
new file mode 100644
index 0000000..8000ab1
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_with_lifetime.html
@@ -0,0 +1,5 @@
+<html>
+<meta name="Accept-CH" content="dpr,sec-ch-dpr,device-memory,sec-ch-device-memory,viewport-width,sec-ch-viewport-width,rtt,downlink,ect,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-ua-bitness,sec-ch-ua-full-version-list">
+<meta http-equiv="Accept-CH-Lifetime" content="3600">
+<link rel="icon" href="data:;base64,=">
+</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime.html b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime.html
new file mode 100644
index 0000000..f17e494
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime.html
@@ -0,0 +1,7 @@
+<html>
+<meta name="Accept-CH" content="dpr,sec-ch-dpr,device-memory,sec-ch-device-memory,viewport-width,sec-ch-viewport-width,rtt,downlink,ect,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-ua-bitness,sec-ch-ua-full-version-list">
+<link rel="icon" href="data:;base64,=">
+<head></head>
+Empty file which uses link-rel to disable favicon fetches. The corresponding
+.mock-http-headers sets client hints.
+</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_img_localhost.html b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_img_localhost.html
new file mode 100644
index 0000000..47dbd4a
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_img_localhost.html
@@ -0,0 +1,9 @@
+<html>
+<meta name="Accept-CH" content="dpr,sec-ch-dpr,device-memory,sec-ch-device-memory,viewport-width,sec-ch-viewport-width,rtt,downlink,ect,sec-ch-ua-arch,sec-ch-ua-platform,sec-ch-ua-platform-version,sec-ch-ua-model,sec-ch-ua-full-version,sec-ch-prefers-color-scheme,sec-ch-ua-bitness,sec-ch-viewport-height,sec-ch-ua-full-version-list">
+<link rel="icon" href="data:;base64,=">
+<head></head>
+Empty file which uses link-rel to disable favicon fetches. The corresponding
+.mock-http-headers sets client hints.
+<img src="non-existing-image.jpg"></img>
+<img src="https://foo.com/non-existing-image.jpg"></img>
+</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_iframe.html b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_iframe.html
new file mode 100644
index 0000000..f736b4e
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_iframe.html
@@ -0,0 +1,7 @@
+<html>
+<link rel="icon" href="data:;base64,=">
+<head></head>
+Empty file which uses link-rel to disable favicon fetches. The corresponding
+.mock-http-headers sets client hints.
+<iframe src="meta_name_accept_ch_with_lifetime.html"></iframe>
+</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_subresource.html b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_subresource.html
new file mode 100644
index 0000000..53bd47dd
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_subresource.html
@@ -0,0 +1,6 @@
+<html>
+<link rel="icon" href="data:;base64,=">
+<head></head>
+Empty file which uses link-rel to disable favicon fetches.
+<img src="meta_name_accept_ch_with_lifetime.html"></img>
+</html>
diff --git a/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_subresource_iframe.html b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_subresource_iframe.html
new file mode 100644
index 0000000..bf14dac4
--- /dev/null
+++ b/chrome/test/data/client_hints/meta_name_accept_ch_without_lifetime_with_subresource_iframe.html
@@ -0,0 +1,6 @@
+<html>
+<link rel="icon" href="data:;base64,=">
+<head></head>
+Empty file which uses link-rel to disable favicon fetches.
+<iframe src="meta_name_accept_ch_without_lifetime_with_subresource.html"></iframe>
+</html>
diff --git a/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html b/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html
index 0737f4e..fe26283 100644
--- a/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html
+++ b/chrome/test/data/extensions/api_test/desktop_capture_delegate/example.com.html
@@ -11,6 +11,11 @@
   domAutomationController.send(msg);
 }
 
+function onMediaStreamError(mediaStreamError) {
+  console.log(mediaStreamError.message);
+  sendToBrowser(false);
+}
+
 function requestStreamId(callback) {
   function onResponse(response) {
     if (chrome.runtime.lastError) {
@@ -35,7 +40,7 @@
       audio:false,
       video: { mandatory: { chromeMediaSource: "desktop",
                             chromeMediaSourceId: id } }
-    }, sendToBrowser.bind(null, true), sendToBrowser.bind(null, false));
+    }, sendToBrowser.bind(null, true), onMediaStreamError);
   };
   requestStreamId(onStreamId);
 }
diff --git a/chrome/test/data/extensions/api_test/desktop_capture_delegate/manifest.json b/chrome/test/data/extensions/api_test/desktop_capture_delegate/manifest.json
index 8fa5c7e9..be77078 100644
--- a/chrome/test/data/extensions/api_test/desktop_capture_delegate/manifest.json
+++ b/chrome/test/data/extensions/api_test/desktop_capture_delegate/manifest.json
@@ -12,6 +12,6 @@
     "desktopCapture"
   ],
   "externally_connectable": {
-    "matches": ["*://*.example.com:*/*"]
+    "matches": ["*://localhost/*"]
   }
 }
diff --git a/chrome/test/data/extensions/api_test/speech/speech_recognition_private/start_result_stop/test.js b/chrome/test/data/extensions/api_test/speech/speech_recognition_private/start_result_stop/test.js
index e9b7b170..80c958a1 100644
--- a/chrome/test/data/extensions/api_test/speech/speech_recognition_private/start_result_stop/test.js
+++ b/chrome/test/data/extensions/api_test/speech/speech_recognition_private/start_result_stop/test.js
@@ -6,26 +6,37 @@
   // This test has a few steps, which are outlined in order below:
   // 1. Start speech recognition.
   // 2. Once speech recognition has started, send a message to C++, which
-  // will trigger a fake speech result to be sent.
-  // 3. Once we get a speech result, let C++ know.
-  // 4. Once C++ acknowledges our message, stop speech recognition.
-  // 5. Pass this test once speech recognition has stopped.
+  // will trigger a non-final speech result to be sent.
+  // 3. Once we get a non-final speech result, let C++ know. A final speech
+  // result will be sent after C++ knows that the non-final-result was received.
+  // 4. Once we get a final speech result, let C++ know.
+  // 5. C++ stops speech recognition.
+  // 6. Pass this test once speech recognition has stopped.
 
   const clientId = 4;
+  const interimResults = true;
   chrome.speechRecognitionPrivate.onResult.addListener((event) => {
-    // Step 3.
     chrome.test.assertEq(clientId, event.clientId);
-    chrome.test.assertEq('Testing', event.transcript);
-    chrome.test.assertTrue(event.isFinal);
-    chrome.test.sendMessage('Received result', async (proceed) => {
-      // Steps 4 and 5.
-      await chrome.speechRecognitionPrivate.stop({clientId});
-      chrome.test.assertNoLastError();
-      chrome.test.notifyPass();
-    });
+    const transcript = event.transcript;
+    const isFinal = event.isFinal;
+    if (transcript === 'First result') {
+      // Step 3.
+      chrome.test.assertFalse(isFinal);
+      chrome.test.sendMessage('Received first result');
+    } else if (transcript === 'Second result') {
+      // Steps 4, 5, and 6.
+      chrome.test.assertTrue(isFinal);
+      chrome.test.sendMessage('Received second result', async (proceed) => {
+        await chrome.speechRecognitionPrivate.stop({clientId});
+        chrome.test.assertNoLastError();
+        chrome.test.notifyPass();
+      });
+    } else {
+      chrome.test.fail();
+    }
   });
 
   // Steps 1 and 2.
-  await chrome.speechRecognitionPrivate.start({clientId});
+  await chrome.speechRecognitionPrivate.start({clientId, interimResults});
   chrome.test.sendMessage('Started');
 })();
diff --git a/chrome/test/data/extensions/api_test/tabs/basics/crud.js b/chrome/test/data/extensions/api_test/tabs/basics/crud.js
index b2dce09..e3f0312 100644
--- a/chrome/test/data/extensions/api_test/tabs/basics/crud.js
+++ b/chrome/test/data/extensions/api_test/tabs/basics/crud.js
@@ -142,18 +142,4 @@
       }));
     }));
   }
-
-  /* Disabled -- see http://crbug.com/58229.
-  function windowSetFocused() {
-    chrome.windows.getCurrent(function(oldWin) {
-      chrome.windows.create({}, function(newWin) {
-        assertTrue(newWin.focused);
-        chrome.windows.update(oldWin.id, {focused:true});
-        chrome.windows.get(oldWin.id, pass(function(oldWin2) {
-          assertTrue(oldWin2.focused);
-        }));
-      });
-    });
-  },
-  */
 ]);
diff --git a/chrome/test/data/extensions/api_test/window_update/set_focus/manifest.json b/chrome/test/data/extensions/api_test/window_update/set_focus/manifest.json
new file mode 100644
index 0000000..7c49cb4d
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/window_update/set_focus/manifest.json
@@ -0,0 +1,10 @@
+{
+  "name": "chrome.windows.update set focus",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "Tests the chrome.windows.update focus parameter.",
+  "background": {
+    "scripts": ["test.js"],
+    "persistent": false
+  }
+}
diff --git a/chrome/test/data/extensions/api_test/window_update/set_focus/test.js b/chrome/test/data/extensions/api_test/window_update/set_focus/test.js
new file mode 100644
index 0000000..53d9635
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/window_update/set_focus/test.js
@@ -0,0 +1,40 @@
+// 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.
+
+chrome.test.runTests([
+  function windowSetFocused() {
+    chrome.windows.getCurrent(function(oldWin) {
+      chrome.test.assertTrue(oldWin.focused);
+      var focusIds = [];
+      var newWindowId;
+      // Listen to verify the change events come in the order expected.
+      chrome.windows.onFocusChanged.addListener(function listener(windowId) {
+        // Events may be sent when all Chrome windows have lost focus,
+        // so ignore those.
+        if (windowId == chrome.windows.WINDOW_ID_NONE)
+          return;
+        focusIds.push(windowId);
+        if (focusIds.length == 2) {
+          chrome.windows.onFocusChanged.removeListener(listener);
+          chrome.test.assertEq(newWindowId, focusIds[0]);
+          chrome.test.assertEq(oldWin.id, focusIds[1]);
+          chrome.test.succeed();
+        }
+      });
+      // Create a new window, update its focus, then return focus to the
+      // original window.
+      chrome.windows.create({}, function(newWin) {
+        newWindowId = newWin.id;
+        chrome.windows.update(newWin.id, {focused:true}, function(win) {
+          chrome.test.assertEq(newWin.id, win.id);
+          chrome.test.assertTrue(win.focused);
+          chrome.windows.update(oldWin.id, {focused:true}, function(win) {
+            chrome.test.assertEq(oldWin.id, win.id);
+            chrome.test.assertTrue(win.focused);
+          });
+        });
+      });
+    });
+  },
+]);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 141267de..5ddc483 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -407,7 +407,6 @@
       "media/media_engagement_browsertest.js",
       "media/media_history_webui_browsertest.js",
       "new_tab_page/new_tab_page_browsertest.js",
-      "read_later/read_later_browsertest.js",
       "read_later/side_panel/side_panel_browsertest.js",
     ]
 
@@ -439,6 +438,7 @@
       "cr_components/cr_components_mojo_browsertest.js",
       "downloads/downloads_browsertest.js",
       "engagement/site_engagement_browsertest.js",
+      "read_later/read_later_browsertest.js",
       "usb_internals_browsertest.js",
     ]
     if (is_chromeos_ash) {
@@ -505,7 +505,6 @@
     "new_tab_page:closure_compile",
     "read_later:closure_compile",
     "tab_search:closure_compile",
-    "tab_strip:closure_compile",
 
     # TODO(crbug.com/1000989): Add page specific targets here.
   ]
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/google_photos_element_test.js
index d2206d2..22ebe04 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_element_test.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {GooglePhotos} from 'chrome://personalization/trusted/google_photos_element.js';
+import {GooglePhotos} from 'chrome://personalization/trusted/wallpaper/google_photos_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {waitAfterNextRender} from '../../test_util.js';
+
 import {baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
 
diff --git a/chrome/test/data/webui/chromeos/personalization_app/local_images_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/local_images_element_test.js
index 20d9c6dc..2211fcd 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/local_images_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/local_images_element_test.js
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {LocalImages} from 'chrome://personalization/trusted/local_images_element.js';
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {LocalImages} from 'chrome://personalization/trusted/wallpaper/local_images_element.js';
+
+import {assertEquals, assertTrue} from '../../chai_assert.js';
 import {flushTasks, waitAfterNextRender} from '../../test_util.js';
+
 import {baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 export function LocalImagesTest() {
   /** @type {?HTMLElement} */
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_test.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_test.js
index 2e4da02..2f3cbf22 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_test.js
@@ -7,9 +7,9 @@
 
 import {GooglePhotosTest} from './google_photos_element_test.js';
 import {LocalImagesTest} from './local_images_element_test.js';
+import {PersonalizationBreadcrumbTest} from './personalization_breadcrumb_element_test.js';
 import {PersonalizationRouterTest} from './personalization_router_element_test.js';
 import {PersonalizationToastTest} from './personalization_toast_element_test.js';
-import {WallpaperBreadcrumbTest} from './wallpaper_breadcrumb_element_test.js';
 import {WallpaperCollectionsTest} from './wallpaper_collections_element_test.js';
 import {WallpaperFullscreenTest} from './wallpaper_fullscreen_element_test.js';
 import {WallpaperImagesTest} from './wallpaper_images_element_test.js';
@@ -22,9 +22,9 @@
 const testCases = [
   GooglePhotosTest,
   LocalImagesTest,
+  PersonalizationBreadcrumbTest,
   PersonalizationRouterTest,
   PersonalizationToastTest,
-  WallpaperBreadcrumbTest,
   WallpaperCollectionsTest,
   WallpaperFullscreenTest,
   WallpaperImagesTest,
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_controller_test.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_controller_test.js
index 968d6b3..db7c30c 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_controller_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_controller_test.js
@@ -6,11 +6,12 @@
 
 import * as action from 'chrome://personalization/trusted/personalization_actions.js';
 import {WallpaperCollection} from 'chrome://personalization/trusted/personalization_app.mojom-webui.js';
-import {fetchGooglePhotosAlbum, fetchLocalData, initializeBackdropData, initializeGooglePhotosData, selectWallpaper} from 'chrome://personalization/trusted/personalization_controller.js';
+import {fetchGooglePhotosAlbum, fetchLocalData, initializeBackdropData, initializeGooglePhotosData, selectWallpaper} from 'chrome://personalization/trusted/wallpaper/wallpaper_controller.js';
 
 import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
+
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 /**
  * Get a sub-property in obj. Splits on '.'
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.js
index 5e4155f6d..f522de2 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test_utils.js
@@ -7,13 +7,15 @@
  * SWA.
  */
 
-import {setWallpaperProviderForTesting} from 'chrome://personalization/trusted/mojo_interface_provider.js';
 import {emptyState} from 'chrome://personalization/trusted/personalization_state.js';
+import {setWallpaperProviderForTesting} from 'chrome://personalization/trusted/wallpaper/wallpaper_interface_provider.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
 import {assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
+
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 /**
  * Constructs the given element with properties and appends it to body.
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_breadcrumb_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_breadcrumb_element_test.js
similarity index 68%
rename from chrome/test/data/webui/chromeos/personalization_app/wallpaper_breadcrumb_element_test.js
rename to chrome/test/data/webui/chromeos/personalization_app/personalization_breadcrumb_element_test.js
index 92dab99..7083f7b 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_breadcrumb_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_breadcrumb_element_test.js
@@ -5,20 +5,20 @@
 /** @fileoverview Test suite for wallpaper-breadcrumb component.  */
 
 import {WallpaperCollection} from 'chrome://personalization/trusted/personalization_app.mojom-webui.js';
+import {PersonalizationBreadcrumb} from 'chrome://personalization/trusted/personalization_breadcrumb_element.js';
 import {Paths} from 'chrome://personalization/trusted/personalization_router_element.js';
-import {WallpaperBreadcrumb} from 'chrome://personalization/trusted/wallpaper_breadcrumb_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
-import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertEquals, assertTrue} from '../../chai_assert.js';
 import {flushTasks, waitAfterNextRender} from '../../test_util.js';
 
 import {baseSetup, initElement} from './personalization_app_test_utils.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
-export function WallpaperBreadcrumbTest() {
+export function PersonalizationBreadcrumbTest() {
   /** @type {?HTMLElement} */
-  let wallpaperBreadcrumbElement = null;
+  let breadcrumbElement = null;
 
   /** @type {?TestWallpaperProvider} */
   let wallpaperProvider = null;
@@ -62,43 +62,40 @@
   });
 
   teardown(async () => {
-    if (wallpaperBreadcrumbElement) {
-      wallpaperBreadcrumbElement.remove();
+    if (breadcrumbElement) {
+      breadcrumbElement.remove();
     }
-    wallpaperBreadcrumbElement = null;
+    breadcrumbElement = null;
     await flushTasks();
   });
 
   test('shows wallpaper label by default', async () => {
-    wallpaperBreadcrumbElement = initElement(WallpaperBreadcrumb.is);
+    breadcrumbElement = initElement(PersonalizationBreadcrumb.is);
 
     const breadcrumbContainer =
-        wallpaperBreadcrumbElement.shadowRoot.getElementById(
-            'breadcrumbContainer');
+        breadcrumbElement.shadowRoot.getElementById('breadcrumbContainer');
     assertTrue(!!breadcrumbContainer && !breadcrumbContainer.hidden);
-    assertBreadcrumbs(
-        breadcrumbContainer, [wallpaperBreadcrumbElement.i18n('title')]);
+    assertBreadcrumbs(breadcrumbContainer, [breadcrumbElement.i18n('title')]);
   });
 
   test('shows collection name when collection is selected', async () => {
     const collection = wallpaperProvider.collections[0];
-    wallpaperBreadcrumbElement = initElement(
-        WallpaperBreadcrumb.is,
+    breadcrumbElement = initElement(
+        PersonalizationBreadcrumb.is,
         {'path': Paths.CollectionImages, 'collectionId': collection.id});
 
     personalizationStore.data.backdrop.collections =
         wallpaperProvider.collections;
     personalizationStore.notifyObservers();
 
-    await waitAfterNextRender(wallpaperBreadcrumbElement);
+    await waitAfterNextRender(breadcrumbElement);
 
     const breadcrumbContainer =
-        wallpaperBreadcrumbElement.shadowRoot.getElementById(
-            'breadcrumbContainer');
+        breadcrumbElement.shadowRoot.getElementById('breadcrumbContainer');
     assertTrue(!!breadcrumbContainer && !breadcrumbContainer.hidden);
     assertBreadcrumbs(
         breadcrumbContainer,
-        [wallpaperBreadcrumbElement.i18n('title'), collection.name]);
+        [breadcrumbElement.i18n('title'), collection.name]);
   });
 
   test('show album name when Google Photos subpage is loaded', async () => {
@@ -113,19 +110,17 @@
     personalizationStore.data.googlePhotos.albums = [googlePhotosAlbum];
     personalizationStore.notifyObservers();
 
-    wallpaperBreadcrumbElement = initElement(WallpaperBreadcrumb.is, {
+    breadcrumbElement = initElement(PersonalizationBreadcrumb.is, {
       'path': Paths.GooglePhotosCollection,
       'googlePhotosAlbumId': googlePhotosAlbum.id
     });
 
     const breadcrumbContainer =
-        wallpaperBreadcrumbElement.shadowRoot.getElementById(
-            'breadcrumbContainer');
+        breadcrumbElement.shadowRoot.getElementById('breadcrumbContainer');
     assertTrue(!!breadcrumbContainer && !breadcrumbContainer.hidden);
     assertBreadcrumbs(breadcrumbContainer, [
-      wallpaperBreadcrumbElement.i18n('title'),
-      wallpaperBreadcrumbElement.i18n('googlePhotosLabel'),
-      googlePhotosAlbum.name
+      breadcrumbElement.i18n('title'),
+      breadcrumbElement.i18n('googlePhotosLabel'), googlePhotosAlbum.name
     ]);
   });
 
@@ -134,35 +129,32 @@
     // integration feature flag is enabled.
     loadTimeData.overrideValues({'googlePhotosLabel': 'Google Photos'});
 
-    wallpaperBreadcrumbElement = initElement(
-        WallpaperBreadcrumb.is, {'path': Paths.GooglePhotosCollection});
+    breadcrumbElement = initElement(
+        PersonalizationBreadcrumb.is, {'path': Paths.GooglePhotosCollection});
 
     const breadcrumbContainer =
-        wallpaperBreadcrumbElement.shadowRoot.getElementById(
-            'breadcrumbContainer');
+        breadcrumbElement.shadowRoot.getElementById('breadcrumbContainer');
     assertTrue(!!breadcrumbContainer && !breadcrumbContainer.hidden);
     assertBreadcrumbs(breadcrumbContainer, [
-      wallpaperBreadcrumbElement.i18n('title'),
-      wallpaperBreadcrumbElement.i18n('googlePhotosLabel')
+      breadcrumbElement.i18n('title'),
+      breadcrumbElement.i18n('googlePhotosLabel')
     ]);
   });
 
   test('show label when local images subpage is loaded', async () => {
-    wallpaperBreadcrumbElement =
-        initElement(WallpaperBreadcrumb.is, {'path': Paths.LocalCollection});
+    breadcrumbElement = initElement(
+        PersonalizationBreadcrumb.is, {'path': Paths.LocalCollection});
 
     personalizationStore.data.local.images = wallpaperProvider.localImages;
     personalizationStore.notifyObservers();
 
-    await waitAfterNextRender(wallpaperBreadcrumbElement);
+    await waitAfterNextRender(breadcrumbElement);
 
     const breadcrumbContainer =
-        wallpaperBreadcrumbElement.shadowRoot.getElementById(
-            'breadcrumbContainer');
+        breadcrumbElement.shadowRoot.getElementById('breadcrumbContainer');
     assertTrue(!!breadcrumbContainer && !breadcrumbContainer.hidden);
     assertBreadcrumbs(breadcrumbContainer, [
-      wallpaperBreadcrumbElement.i18n('title'),
-      wallpaperBreadcrumbElement.i18n('myImagesLabel')
+      breadcrumbElement.i18n('title'), breadcrumbElement.i18n('myImagesLabel')
     ]);
   });
 }
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_router_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_router_element_test.js
index 8f264d3f..7b2dcd9d 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_router_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_router_element_test.js
@@ -4,6 +4,7 @@
 
 import {PersonalizationRouter} from 'chrome://personalization/trusted/personalization_router_element.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+
 import {initElement} from './personalization_app_test_utils.js';
 
 export function PersonalizationRouterTest() {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_toast_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_toast_element_test.js
index 7e5850c..837e76e 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_toast_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_toast_element_test.js
@@ -4,8 +4,10 @@
 
 import {ActionName} from 'chrome://personalization/trusted/personalization_actions.js';
 import {PersonalizationToastElement} from 'chrome://personalization/trusted/personalization_toast_element.js';
+
 import {assertEquals, assertTrue} from '../../chai_assert.js';
 import {flushTasks, waitAfterNextRender} from '../../test_util.js';
+
 import {baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
 
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_mojo_interface_provider.js b/chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.js
similarity index 100%
rename from chrome/test/data/webui/chromeos/personalization_app/test_mojo_interface_provider.js
rename to chrome/test/data/webui/chromeos/personalization_app/test_wallpaper_interface_provider.js
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.js
index acf842a..99944d5 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_collections_element_test.js
@@ -4,12 +4,14 @@
 
 import {kMaximumLocalImagePreviews} from 'chrome://personalization/common/constants.js';
 import {emptyState} from 'chrome://personalization/trusted/personalization_state.js';
-import {promisifyIframeFunctionsForTesting, WallpaperCollections} from 'chrome://personalization/trusted/wallpaper_collections_element.js';
+import {promisifyIframeFunctionsForTesting, WallpaperCollections} from 'chrome://personalization/trusted/wallpaper/wallpaper_collections_element.js';
+
 import {assertDeepEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {waitAfterNextRender} from '../../test_util.js';
+
 import {assertWindowObjectsEqual, baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 export function WallpaperCollectionsTest() {
   /** @type {?HTMLElement} */
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js
index 58ffa2c..47af9459 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js
@@ -6,14 +6,14 @@
 
 import {WallpaperLayout, WallpaperType} from 'chrome://personalization/trusted/personalization_app.mojom-webui.js';
 import {DisplayableImage} from 'chrome://personalization/trusted/personalization_reducers.js';
-import {WallpaperFullscreen} from 'chrome://personalization/trusted/wallpaper_fullscreen_element.js';
+import {WallpaperFullscreen} from 'chrome://personalization/trusted/wallpaper/wallpaper_fullscreen_element.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {flushTasks, waitAfterNextRender} from '../../test_util.js';
 
 import {baseSetup, initElement} from './personalization_app_test_utils.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 export function WallpaperFullscreenTest() {
   /** @type {?HTMLElement} */
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.js
index 0fbdfc9..e5b718e 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_images_element_test.js
@@ -4,13 +4,14 @@
 
 import {WallpaperLayout, WallpaperType} from 'chrome://personalization/trusted/personalization_app.mojom-webui.js';
 import {PersonalizationRouter} from 'chrome://personalization/trusted/personalization_router_element.js';
-import {getDarkLightImageTiles, getRegularImageTiles, promisifyImagesIframeFunctionsForTesting, WallpaperImages} from 'chrome://personalization/trusted/wallpaper_images_element.js';
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {getDarkLightImageTiles, getRegularImageTiles, promisifyImagesIframeFunctionsForTesting, WallpaperImages} from 'chrome://personalization/trusted/wallpaper/wallpaper_images_element.js';
+
+import {assertDeepEquals, assertEquals, assertFalse} from '../../chai_assert.js';
 import {flushTasks, waitAfterNextRender} from '../../test_util.js';
 
 import {assertWindowObjectsEqual, baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 export function WallpaperImagesTest() {
   /** @type {?HTMLElement} */
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.js
index 4cf2a680d..3beec3a8 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_selected_element_test.js
@@ -7,14 +7,14 @@
 import {ActionName} from 'chrome://personalization/trusted/personalization_actions.js';
 import {Paths} from 'chrome://personalization/trusted/personalization_router_element.js';
 import {emptyState} from 'chrome://personalization/trusted/personalization_state.js';
-import {mockTimeoutForTesting, WallpaperSelected} from 'chrome://personalization/trusted/wallpaper_selected_element.js';
+import {mockTimeoutForTesting, WallpaperSelected} from 'chrome://personalization/trusted/wallpaper/wallpaper_selected_element.js';
 
 import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertNotReached, assertTrue} from '../../chai_assert.js';
 import {flushTasks, waitAfterNextRender} from '../../test_util.js';
 
 import {baseSetup, initElement} from './personalization_app_test_utils.js';
-import {TestWallpaperProvider} from './test_mojo_interface_provider.js';
 import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestWallpaperProvider} from './test_wallpaper_interface_provider.js';
 
 export function WallpaperSelectedTest() {
   /** @type {?HTMLElement} */
diff --git a/chrome/test/data/webui/print_preview/BUILD.gn b/chrome/test/data/webui/print_preview/BUILD.gn
index 9b099d2..b0b83132 100644
--- a/chrome/test/data/webui/print_preview/BUILD.gn
+++ b/chrome/test/data/webui/print_preview/BUILD.gn
@@ -36,8 +36,8 @@
   "cloud_print_interface_stub.ts",
   "copies_settings_test.ts",
   "custom_margins_test.ts",
-  "destination_item_test.js",
-  "destination_list_test.js",
+  "destination_item_test.ts",
+  "destination_list_test.ts",
   "destination_search_test.js",
   "destination_select_test.js",
   "dpi_settings_test.js",
@@ -74,8 +74,8 @@
   non_preprocessed_tests += [
     "destination_dialog_cros_interactive_test.ts",
     "destination_dialog_cros_test.ts",
-    "destination_dropdown_cros_test.js",
-    "destination_item_test_cros.js",
+    "destination_dropdown_cros_test.ts",
+    "destination_item_test_cros.ts",
     "destination_search_test_chromeos.js",
     "destination_select_test_cros.js",
     "destination_settings_test_cros.js",
diff --git a/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js b/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.ts
similarity index 68%
rename from chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js
rename to chrome/test/data/webui/print_preview/destination_dropdown_cros_test.ts
index 14f1e4d6..ab9cd86 100644
--- a/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dropdown_cros_test.ts
@@ -12,98 +12,83 @@
 
 import {getGoogleDriveDestination, getSaveAsPdfDestination} from './print_preview_test_utils.js';
 
-window.destination_dropdown_cros_test = {};
-const destination_dropdown_cros_test = window.destination_dropdown_cros_test;
-destination_dropdown_cros_test.suiteName =
-    'PrintPreviewDestinationDropdownCrosTest';
-/** @enum {string} */
-destination_dropdown_cros_test.TestNames = {
-  CorrectListItems: 'correct list items',
-  ClickCloses: 'click closes dropdown',
-  HighlightedAfterUpDown: 'highlighted after keyboard press up and down',
-  DestinationChangeAfterUpDown:
-      'destination changes after keyboard press up and down',
-  EnterOpensCloses: 'enter opens and closes dropdown',
-  HighlightedFollowsMouse: 'highlighted follows mouse',
-  Disabled: 'disabled',
-  HighlightedWhenOpened: 'highlighted when opened',
+const destination_dropdown_cros_test = {
+  suiteName: 'PrintPreviewDestinationDropdownCrosTest',
+  TestNames: {
+    CorrectListItems: 'correct list items',
+    ClickCloses: 'click closes dropdown',
+    HighlightedAfterUpDown: 'highlighted after keyboard press up and down',
+    DestinationChangeAfterUpDown:
+        'destination changes after keyboard press up and down',
+    EnterOpensCloses: 'enter opens and closes dropdown',
+    HighlightedFollowsMouse: 'highlighted follows mouse',
+    Disabled: 'disabled',
+    HighlightedWhenOpened: 'highlighted when opened',
+  },
 };
 
-suite(destination_dropdown_cros_test.suiteName, function() {
-  /** @type {!PrintPreviewDestinationDropdownCrosElement} */
-  let dropdown;
+Object.assign(
+    window, {destination_dropdown_cros_test: destination_dropdown_cros_test});
 
-  /** @param {!Array<!Destination>} items */
-  function setItemList(items) {
+suite(destination_dropdown_cros_test.suiteName, function() {
+  let dropdown: PrintPreviewDestinationDropdownCrosElement;
+
+  function setItemList(items: Destination[]) {
     dropdown.itemList = items;
     flush();
   }
 
-  /** @return {!NodeList} */
-  function getList() {
-    return dropdown.shadowRoot.querySelectorAll('.list-item');
+  function getList(): HTMLButtonElement[] {
+    return Array.from(
+        dropdown.shadowRoot!.querySelectorAll<HTMLButtonElement>('.list-item'));
   }
 
   function clickDropdown() {
-    dropdown.shadowRoot.querySelector('#destination-dropdown').click();
+    dropdown.$.destinationDropdown.click();
   }
 
   function clickDropdownFocus() {
-    dropdown.shadowRoot.querySelector('#destination-dropdown').click();
-    dropdown.shadowRoot.querySelector('#destination-dropdown').focus();
+    dropdown.$.destinationDropdown.click();
+    dropdown.$.destinationDropdown.focus();
   }
 
   function clickOutsideDropdown() {
     document.body.click();
-    dropdown.shadowRoot.querySelector('#destination-dropdown').blur();
+    dropdown.$.destinationDropdown.blur();
   }
 
   function down() {
-    keyDownOn(
-        dropdown.shadowRoot.querySelector('#destination-dropdown'), 'ArrowDown',
-        [], 'ArrowDown');
+    keyDownOn(dropdown.$.destinationDropdown, 40, [], 'ArrowDown');
   }
 
   function up() {
-    keyDownOn(
-        dropdown.shadowRoot.querySelector('#destination-dropdown'), 'ArrowUp',
-        [], 'ArrowUp');
+    keyDownOn(dropdown.$.destinationDropdown, 38, [], 'ArrowUp');
   }
 
   function enter() {
-    keyDownOn(
-        dropdown.shadowRoot.querySelector('#destination-dropdown'), 'Enter', [],
-        'Enter');
+    keyDownOn(dropdown.$.destinationDropdown, 13, [], 'Enter');
   }
 
-  /** @return {?Element} */
-  function getHighlightedElement() {
-    return dropdown.shadowRoot.querySelector('.highlighted');
+  function getHighlightedElement(): (HTMLElement|null) {
+    return dropdown.shadowRoot!.querySelector('.highlighted');
   }
 
-  /** @return {string} */
-  function getHighlightedElementText() {
-    return getHighlightedElement().textContent.trim();
+  function getHighlightedElementText(): string {
+    return getHighlightedElement()!.textContent!.trim();
   }
 
-  /**
-   * @param {string} displayName
-   * @param {!DestinationOrigin} destinationOrigin
-   * @return {!Destination}
-   */
-  function createDestination(displayName, destinationOrigin) {
+  function createDestination(
+      displayName: string, destinationOrigin: DestinationOrigin): Destination {
     return new Destination(
         displayName, DestinationType.LOCAL, destinationOrigin, displayName,
         DestinationConnectionStatus.ONLINE);
   }
 
-  /** @override */
   setup(function() {
     document.body.innerHTML = '';
 
     dropdown =
-        /** @type {!PrintPreviewDestinationDropdownCrosElement} */
-        (document.createElement('print-preview-destination-dropdown-cros'));
+        document.createElement('print-preview-destination-dropdown-cros');
     document.body.appendChild(dropdown);
     dropdown.noDestinations = false;
     dropdown.driveDestinationKey = getGoogleDriveDestination('account').key;
@@ -121,9 +106,9 @@
 
         const itemList = getList();
         assertEquals(7, itemList.length);
-        assertEquals('One', itemList[0].textContent.trim());
-        assertEquals('Two', itemList[1].textContent.trim());
-        assertEquals('Three', itemList[2].textContent.trim());
+        assertEquals('One', itemList[0]!.textContent!.trim());
+        assertEquals('Two', itemList[1]!.textContent!.trim());
+        assertEquals('Three', itemList[2]!.textContent!.trim());
       });
 
   test(
@@ -131,12 +116,13 @@
         const destinationOne = createDestination('One', DestinationOrigin.CROS);
         setItemList([destinationOne]);
         dropdown.value = destinationOne;
-        const ironDropdown = dropdown.shadowRoot.querySelector('iron-dropdown');
+        const ironDropdown =
+            dropdown.shadowRoot!.querySelector('iron-dropdown')!;
 
         clickDropdownFocus();
         assertTrue(ironDropdown.opened);
 
-        getList()[0].click();
+        getList()[0]!.click();
         assertFalse(ironDropdown.opened);
 
         clickDropdownFocus();
@@ -215,11 +201,13 @@
         setItemList([destinationOne]);
         dropdown.value = destinationOne;
 
-        assertFalse(dropdown.shadowRoot.querySelector('iron-dropdown').opened);
+        assertFalse(
+            dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
         enter();
-        assertTrue(dropdown.shadowRoot.querySelector('iron-dropdown').opened);
+        assertTrue(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
         enter();
-        assertFalse(dropdown.shadowRoot.querySelector('iron-dropdown').opened);
+        assertFalse(
+            dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
       });
 
   test(
@@ -233,9 +221,9 @@
         dropdown.value = destinationOne;
         clickDropdown();
 
-        move(getList()[1], {x: 0, y: 0}, {x: 0, y: 0}, 1);
+        move(getList()[1]!, {x: 0, y: 0}, {x: 0, y: 0}, 1);
         assertEquals('Two', getHighlightedElementText());
-        move(getList()[2], {x: 0, y: 0}, {x: 0, y: 0}, 1);
+        move(getList()[2]!, {x: 0, y: 0}, {x: 0, y: 0}, 1);
         assertEquals('Three', getHighlightedElementText());
 
         // Interacting with the keyboard should update the highlighted element.
@@ -244,7 +232,7 @@
 
         // When the user moves the mouse again, the highlighted element should
         // change.
-        move(getList()[0], {x: 0, y: 0}, {x: 0, y: 0}, 1);
+        move(getList()[0]!, {x: 0, y: 0}, {x: 0, y: 0}, 1);
         assertEquals('One', getHighlightedElementText());
       });
 
@@ -255,19 +243,13 @@
     dropdown.disabled = true;
 
     clickDropdown();
-    assertFalse(dropdown.shadowRoot.querySelector('iron-dropdown').opened);
-    assertEquals(
-        '-1',
-        dropdown.shadowRoot.querySelector('#destination-dropdown')
-            .getAttribute('tabindex'));
+    assertFalse(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
+    assertEquals('-1', dropdown.$.destinationDropdown.getAttribute('tabindex'));
 
     dropdown.disabled = false;
     clickDropdown();
-    assertTrue(dropdown.shadowRoot.querySelector('iron-dropdown').opened);
-    assertEquals(
-        '0',
-        dropdown.shadowRoot.querySelector('#destination-dropdown')
-            .getAttribute('tabindex'));
+    assertTrue(dropdown.shadowRoot!.querySelector('iron-dropdown')!.opened);
+    assertEquals('0', dropdown.$.destinationDropdown.getAttribute('tabindex'));
   });
 
   test(
diff --git a/chrome/test/data/webui/print_preview/destination_item_test.js b/chrome/test/data/webui/print_preview/destination_item_test.ts
similarity index 61%
rename from chrome/test/data/webui/print_preview/destination_item_test.js
rename to chrome/test/data/webui/print_preview/destination_item_test.ts
index 444cf15..d41c2cf 100644
--- a/chrome/test/data/webui/print_preview/destination_item_test.js
+++ b/chrome/test/data/webui/print_preview/destination_item_test.ts
@@ -10,33 +10,29 @@
 
 import {createDestinationWithCertificateStatus} from './print_preview_test_utils.js';
 
-window.destination_item_test = {};
-const destination_item_test = window.destination_item_test;
-destination_item_test.suiteName = 'DestinationItemTest';
-/** @enum {string} */
-destination_item_test.TestNames = {
-  Online: 'online',
-  Offline: 'offline',
-  BadCertificate: 'bad certificate',
-  QueryName: 'query name',
-  QueryDescription: 'query description',
+const destination_item_test = {
+  suiteName: 'DestinationItemTest',
+  TestNames: {
+    Online: 'online',
+    Offline: 'offline',
+    BadCertificate: 'bad certificate',
+    QueryName: 'query name',
+    QueryDescription: 'query description',
+  },
 };
 
+Object.assign(window, {destination_item_test: destination_item_test});
+
 suite(destination_item_test.suiteName, function() {
-  /** @type {!PrintPreviewDestinationListItemElement} */
-  let item;
+  let item: PrintPreviewDestinationListItemElement;
 
-  /** @type {string} */
-  const printerId = 'FooDevice';
+  const printerId: string = 'FooDevice';
 
-  /** @type {string} */
-  const printerName = 'FooName';
+  const printerName: string = 'FooName';
 
-  /** @override */
   setup(function() {
     document.body.innerHTML = '';
-    item = /** @type {!PrintPreviewDestinationListItemElement} */ (
-        document.createElement('print-preview-destination-list-item'));
+    item = document.createElement('print-preview-destination-list-item');
 
     // Create destination
     item.destination = new Destination(
@@ -49,17 +45,21 @@
   // Test that the destination is displayed correctly for the basic case of an
   // online destination with no search query.
   test(assert(destination_item_test.TestNames.Online), function() {
-    const name = item.shadowRoot.querySelector('.name');
+    const name = item.shadowRoot!.querySelector('.name')!;
     assertEquals(printerName, name.textContent);
     assertEquals('1', window.getComputedStyle(name).opacity);
     assertEquals(
-        '', item.shadowRoot.querySelector('.search-hint').textContent.trim());
+        '',
+        item.shadowRoot!.querySelector('.search-hint')!.textContent!.trim());
     assertEquals(
         '',
-        item.shadowRoot.querySelector('.connection-status').textContent.trim());
-    assertTrue(item.shadowRoot.querySelector('.learn-more-link').hidden);
-    assertTrue(item.shadowRoot.querySelector('.extension-controlled-indicator')
-                   .hidden);
+        item.shadowRoot!.querySelector(
+                            '.connection-status')!.textContent!.trim());
+    assertTrue(item.shadowRoot!.querySelector<HTMLElement>(
+                                   '.learn-more-link')!.hidden);
+    assertTrue(item.shadowRoot!
+                   .querySelector<HTMLElement>(
+                       '.extension-controlled-indicator')!.hidden);
   });
 
   // Test that the destination is opaque and the correct status shows up if
@@ -78,17 +78,21 @@
         printerName, DestinationConnectionStatus.OFFLINE,
         {lastAccessTime: twoMonthsAgo.getTime()});
 
-    const name = item.shadowRoot.querySelector('.name');
+    const name = item.shadowRoot!.querySelector('.name')!;
     assertEquals(printerName, name.textContent);
     assertEquals('0.4', window.getComputedStyle(name).opacity);
     assertEquals(
-        '', item.shadowRoot.querySelector('.search-hint').textContent.trim());
+        '',
+        item.shadowRoot!.querySelector('.search-hint')!.textContent!.trim());
     assertEquals(
         loadTimeData.getString('offlineForMonth'),
-        item.shadowRoot.querySelector('.connection-status').textContent.trim());
-    assertTrue(item.shadowRoot.querySelector('.learn-more-link').hidden);
-    assertTrue(item.shadowRoot.querySelector('.extension-controlled-indicator')
-                   .hidden);
+        item.shadowRoot!.querySelector(
+                            '.connection-status')!.textContent!.trim());
+    assertTrue(item.shadowRoot!.querySelector<HTMLElement>(
+                                   '.learn-more-link')!.hidden);
+    assertTrue(item.shadowRoot!
+                   .querySelector<HTMLElement>(
+                       '.extension-controlled-indicator')!.hidden);
   });
 
   // Test that the destination is opaque and the correct status shows up if
@@ -98,17 +102,21 @@
     item.destination =
         createDestinationWithCertificateStatus(printerId, printerName, true);
 
-    const name = item.shadowRoot.querySelector('.name');
+    const name = item.shadowRoot!.querySelector('.name')!;
     assertEquals(printerName, name.textContent);
     assertEquals('0.4', window.getComputedStyle(name).opacity);
     assertEquals(
-        '', item.shadowRoot.querySelector('.search-hint').textContent.trim());
+        '',
+        item.shadowRoot!.querySelector('.search-hint')!.textContent!.trim());
     assertEquals(
         loadTimeData.getString('noLongerSupported'),
-        item.shadowRoot.querySelector('.connection-status').textContent.trim());
-    assertFalse(item.shadowRoot.querySelector('.learn-more-link').hidden);
-    assertTrue(item.shadowRoot.querySelector('.extension-controlled-indicator')
-                   .hidden);
+        item.shadowRoot!.querySelector(
+                            '.connection-status')!.textContent!.trim());
+    assertFalse(item.shadowRoot!.querySelector<HTMLElement>(
+                                    '.learn-more-link')!.hidden);
+    assertTrue(item.shadowRoot!
+                   .querySelector<HTMLElement>(
+                       '.extension-controlled-indicator')!.hidden);
   });
 
   // Test that the destination is displayed correctly when the search query
@@ -116,17 +124,18 @@
   test(assert(destination_item_test.TestNames.QueryName), function() {
     item.searchQuery = /(Foo)/ig;
 
-    const name = item.shadowRoot.querySelector('.name');
+    const name = item.shadowRoot!.querySelector('.name')!;
     assertEquals(printerName + printerName, name.textContent);
 
     // Name should be highlighted.
     const searchHits = name.querySelectorAll('.search-highlight-hit');
     assertEquals(1, searchHits.length);
-    assertEquals('Foo', searchHits[0].textContent);
+    assertEquals('Foo', searchHits[0]!.textContent);
 
     // No hints.
     assertEquals(
-        '', item.shadowRoot.querySelector('.search-hint').textContent.trim());
+        '',
+        item.shadowRoot!.querySelector('.search-hint')!.textContent!.trim());
   });
 
   // Test that the destination is displayed correctly when the search query
@@ -142,16 +151,16 @@
     item.searchQuery = /(ABC)/ig;
 
     // No highlighting on name.
-    const name = item.shadowRoot.querySelector('.name');
+    const name = item.shadowRoot!.querySelector('.name')!;
     assertEquals(printerName, name.textContent);
     assertEquals(0, name.querySelectorAll('.search-highlight-hit').length);
 
     // Search hint should be have the description and be highlighted.
-    const hint = item.shadowRoot.querySelector('.search-hint');
-    assertTrue(hint.textContent.includes(params.description));
-    assertFalse(hint.textContent.includes(params.location));
+    const hint = item.shadowRoot!.querySelector('.search-hint')!;
+    assertTrue(hint.textContent!.includes(params.description));
+    assertFalse(hint.textContent!.includes(params.location));
     const searchHits = hint.querySelectorAll('.search-highlight-hit');
     assertEquals(1, searchHits.length);
-    assertEquals('ABC', searchHits[0].textContent);
+    assertEquals('ABC', searchHits[0]!.textContent);
   });
 });
diff --git a/chrome/test/data/webui/print_preview/destination_item_test_cros.js b/chrome/test/data/webui/print_preview/destination_item_test_cros.ts
similarity index 74%
rename from chrome/test/data/webui/print_preview/destination_item_test_cros.js
rename to chrome/test/data/webui/print_preview/destination_item_test_cros.ts
index c930282..6c7e7dc 100644
--- a/chrome/test/data/webui/print_preview/destination_item_test_cros.js
+++ b/chrome/test/data/webui/print_preview/destination_item_test_cros.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationType, NativeLayerCrosImpl, PrinterState, PrinterStatusReason, PrinterStatusSeverity, PrintPreviewDestinationListItemElement} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationType, NativeLayerCrosImpl, PrinterStatusReason, PrinterStatusSeverity, PrintPreviewDestinationListItemElement} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
@@ -11,44 +11,44 @@
 
 import {NativeLayerCrosStub} from './native_layer_cros_stub.js';
 
-window.destination_item_test_cros = {};
-const destination_item_test_cros = window.destination_item_test_cros;
-destination_item_test_cros.suiteName = 'DestinationItemTestCros';
-/** @enum {string} */
-destination_item_test_cros.TestNames = {
-  NewStatusUpdatesIcon: 'new status updates icon',
-  ChangingDestinationUpdatesIcon: 'changing destination updates icon',
-  OnlyUpdateMatchingDestination: 'only update matching destination',
+const destination_item_test_cros = {
+  suiteName: 'DestinationItemTestCros',
+  TestNames: {
+    NewStatusUpdatesIcon: 'new status updates icon',
+    ChangingDestinationUpdatesIcon: 'changing destination updates icon',
+    OnlyUpdateMatchingDestination: 'only update matching destination',
+  },
 };
 
-suite(destination_item_test_cros.suiteName, function() {
-  /** @type {!PrintPreviewDestinationListItemElement} */
-  let listItem;
+Object.assign(window, {destination_item_test_cros: destination_item_test_cros});
 
-  /** @type {?NativeLayerCrosStub} */
-  let nativeLayerCros = null;
+suite(destination_item_test_cros.suiteName, function() {
+  let listItem: PrintPreviewDestinationListItemElement;
+
+  let nativeLayerCros: NativeLayerCrosStub;
 
   function setNativeLayerPrinterStatusMap() {
     [{
       printerId: 'One',
       statusReasons: [{
         reason: PrinterStatusReason.NO_ERROR,
-        severity: PrinterStatusSeverity.UNKNOWN_SEVERITY
+        severity: PrinterStatusSeverity.UNKNOWN_SEVERITY,
       }],
+      timestamp: 0,
     },
      {
        printerId: 'Two',
        statusReasons: [{
          reason: PrinterStatusReason.OUT_OF_INK,
-         severity: PrinterStatusSeverity.ERROR
+         severity: PrinterStatusSeverity.ERROR,
        }],
+       timestamp: 0,
      }]
         .forEach(
             status => nativeLayerCros.addPrinterStatusToMap(
                 status.printerId, status));
   }
 
-  /** @override */
   setup(function() {
     document.body.innerHTML = `
           <print-preview-destination-list-item id="listItem">
@@ -59,8 +59,9 @@
     NativeLayerCrosImpl.setInstance(nativeLayerCros);
     setNativeLayerPrinterStatusMap();
 
-    listItem = /** @type {!PrintPreviewDestinationListItemElement} */ (
-        document.body.querySelector('#listItem'));
+    listItem =
+        document.body.querySelector<PrintPreviewDestinationListItemElement>(
+            '#listItem')!;
     listItem.destination = new Destination(
         'One', DestinationType.LOCAL, DestinationOrigin.CROS, 'Destination One',
         DestinationConnectionStatus.ONLINE, {description: 'ABC'});
@@ -70,7 +71,7 @@
   test(
       assert(destination_item_test_cros.TestNames.NewStatusUpdatesIcon),
       function() {
-        const icon = listItem.shadowRoot.querySelector('iron-icon');
+        const icon = listItem.shadowRoot!.querySelector('iron-icon')!;
         assertEquals('print-preview:printer-status-grey', icon.icon);
 
         return listItem.destination.requestPrinterStatus().then(() => {
@@ -82,7 +83,7 @@
       assert(
           destination_item_test_cros.TestNames.ChangingDestinationUpdatesIcon),
       function() {
-        const icon = listItem.shadowRoot.querySelector('iron-icon');
+        const icon = listItem.shadowRoot!.querySelector('iron-icon')!;
         assertEquals('print-preview:printer-status-grey', icon.icon);
 
         listItem.destination = new Destination(
@@ -102,7 +103,7 @@
       assert(
           destination_item_test_cros.TestNames.OnlyUpdateMatchingDestination),
       function() {
-        const icon = listItem.shadowRoot.querySelector('iron-icon');
+        const icon = listItem.shadowRoot!.querySelector('iron-icon')!;
         assertEquals('print-preview:printer-status-grey', icon.icon);
         const firstDestinationStatusRequestPromise =
             listItem.destination.requestPrinterStatus();
diff --git a/chrome/test/data/webui/print_preview/destination_list_test.js b/chrome/test/data/webui/print_preview/destination_list_test.ts
similarity index 79%
rename from chrome/test/data/webui/print_preview/destination_list_test.js
rename to chrome/test/data/webui/print_preview/destination_list_test.ts
index ecb30f0..fc48d5c4 100644
--- a/chrome/test/data/webui/print_preview/destination_list_test.js
+++ b/chrome/test/data/webui/print_preview/destination_list_test.ts
@@ -10,20 +10,19 @@
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise} from 'chrome://webui-test/test_util.js';
 
-window.destination_list_test = {};
-const destination_list_test = window.destination_list_test;
-destination_list_test.suiteName = 'DestinationListTest';
-/** @enum {string} */
-destination_list_test.TestNames = {
-  FilterDestinations: 'FilterDestinations',
-  FireDestinationSelected: 'FireDestinationSelected',
+const destination_list_test = {
+  suiteName: 'DestinationListTest',
+  TestNames: {
+    FilterDestinations: 'FilterDestinations',
+    FireDestinationSelected: 'FireDestinationSelected',
+  },
 };
 
-suite(destination_list_test.suiteName, function() {
-  /** @type {!PrintPreviewDestinationListElement} */
-  let list;
+Object.assign(window, {destination_list_test: destination_list_test});
 
-  /** @override */
+suite(destination_list_test.suiteName, function() {
+  let list: PrintPreviewDestinationListElement;
+
   setup(function() {
     // Create destinations
     const destinations = [
@@ -52,8 +51,8 @@
           <print-preview-destination-list id="testList" has-action-link=true
               loading-destinations=false list-name="test">
           </print-preview-destination-list>`;
-    list = /** @type {!PrintPreviewDestinationListElement} */ (
-        document.body.querySelector('#testList'));
+    list = document.body.querySelector<PrintPreviewDestinationListElement>(
+        '#testList')!;
     list.searchQuery = null;
     list.destinations = destinations;
     list.loadingDestinations = false;
@@ -63,16 +62,16 @@
   // Tests that the list correctly shows and hides destinations based on the
   // value of the search query.
   test(assert(destination_list_test.TestNames.FilterDestinations), function() {
-    const items =
-        list.shadowRoot.querySelectorAll('print-preview-destination-list-item');
-    const noMatchHint =
-        list.shadowRoot.querySelector('.no-destinations-message');
+    const items = list.shadowRoot!.querySelectorAll(
+        'print-preview-destination-list-item');
+    const noMatchHint = list.shadowRoot!.querySelector<HTMLElement>(
+        '.no-destinations-message')!;
     const ironList = list.$.list;
 
     // Query is initialized to null. All items are shown and the hint is
     // hidden.
     assertFalse(ironList.hidden);
-    items.forEach(item => assertFalse(item.parentNode.hidden));
+    items.forEach(item => assertFalse((item.parentNode as HTMLElement).hidden));
     assertTrue(noMatchHint.hidden);
 
     // Searching for "e" should show "One", "Three", and "Five".
@@ -80,7 +79,7 @@
     flush();
     assertFalse(ironList.hidden);
     assertEquals(undefined, Array.from(items).find(item => {
-      return !item.parentNode.hidden &&
+      return !(item.parentNode as HTMLElement).hidden &&
           (item.destination.displayName === 'Two' ||
            item.destination.displayName === 'Four');
     }));
@@ -91,7 +90,7 @@
     flush();
     assertFalse(ironList.hidden);
     assertEquals(undefined, Array.from(items).find(item => {
-      return !item.parentNode.hidden &&
+      return !(item.parentNode as HTMLElement).hidden &&
           item.destination.displayName !== 'One' &&
           item.destination.displayName !== 'Three';
     }));
@@ -102,7 +101,7 @@
     flush();
     assertFalse(ironList.hidden);
     assertEquals(undefined, Array.from(items).find(item => {
-      return !item.parentNode.hidden &&
+      return !(item.parentNode as HTMLElement).hidden &&
           item.destination.displayName !== 'Four' &&
           item.destination.displayName !== 'Five';
     }));
@@ -120,7 +119,7 @@
     flush();
     assertFalse(ironList.hidden);
     assertEquals(undefined, Array.from(items).find(item => {
-      return !item.parentNode.hidden &&
+      return !(item.parentNode as HTMLElement).hidden &&
           (item.destination.displayName === 'One' ||
            item.destination.displayName === 'Two');
     }));
@@ -130,7 +129,8 @@
     list.searchQuery = null;
     flush();
     assertFalse(ironList.hidden);
-    items.forEach(item => assertFalse(item.parentNode.hidden));
+    items.forEach(
+        item => assertFalse((item!.parentNode! as HTMLElement).hidden));
     assertTrue(noMatchHint.hidden);
   });
 
@@ -139,21 +139,21 @@
   test(
       assert(destination_list_test.TestNames.FireDestinationSelected),
       function() {
-        const items = list.shadowRoot.querySelectorAll(
+        const items = list.shadowRoot!.querySelectorAll(
             'print-preview-destination-list-item');
         let whenDestinationSelected =
             eventToPromise('destination-selected', list);
-        items[0].click();
+        items[0]!.click();
         return whenDestinationSelected
             .then(event => {
-              assertEquals(items[0], event.detail);
+              assertEquals(items[0]!, event.detail);
               whenDestinationSelected =
                   eventToPromise('destination-selected', list);
-              keyEventOn(items[1], 'keydown', 13, undefined, 'Enter');
+              keyEventOn(items[1]!, 'keydown', 13, undefined, 'Enter');
               return whenDestinationSelected;
             })
             .then(event => {
-              assertEquals(items[1], event.detail);
+              assertEquals(items[1]!, event.detail);
             });
       });
 });
diff --git a/chrome/test/data/webui/read_later/BUILD.gn b/chrome/test/data/webui/read_later/BUILD.gn
index c1cfcdb..13679b29 100644
--- a/chrome/test/data/webui/read_later/BUILD.gn
+++ b/chrome/test/data/webui/read_later/BUILD.gn
@@ -6,10 +6,14 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  closure_flags = default_closure_args + [
+  closure_flags = default_closure_args + mojom_js_args + [
                     "browser_resolver_prefix_replacements=\"chrome://read-later.top-chrome/=../../chrome/browser/resources/read_later/\"",
-                    "js_module_root=../../chrome/test/data/webui/",
-                    "js_module_root=./gen/chrome/test/data/webui/",
+                    "js_module_root=" +
+                        rebase_path("//chrome/browser/resources/read_later",
+                                    root_build_dir),
+                    "js_module_root=" + rebase_path(
+                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/read_later",
+                            root_build_dir),
                   ]
   deps = [
     ":read_later_app_test",
@@ -31,6 +35,6 @@
   deps = [
     "..:test_browser_proxy",
     "//chrome/browser/resources/read_later:read_later_api_proxy",
-    "//chrome/browser/ui/webui/read_later:mojo_bindings_js_library_for_compile",
+    "//chrome/browser/ui/webui/read_later:mojo_bindings_webui_js",
   ]
 }
diff --git a/chrome/test/data/webui/read_later/read_later_app_test.js b/chrome/test/data/webui/read_later/read_later_app_test.js
index 0fd7ebf..889b3e8 100644
--- a/chrome/test/data/webui/read_later/read_later_app_test.js
+++ b/chrome/test/data/webui/read_later/read_later_app_test.js
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import '../mojo_webui_test_support.js';
+
 import {ReadLaterAppElement} from 'chrome://read-later.top-chrome/app.js';
+import {ReadLaterEntriesByStatus} from 'chrome://read-later.top-chrome/read_later.mojom-webui.js';
 import {ReadLaterApiProxy, ReadLaterApiProxyImpl} from 'chrome://read-later.top-chrome/read_later_api_proxy.js';
 import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 
@@ -38,7 +41,7 @@
     readLaterApp.shadowRoot.querySelector(`[data-url="${url}"]`).click();
   }
 
-  /** @return {!readLater.mojom.ReadLaterEntriesByStatus} */
+  /** @return {!ReadLaterEntriesByStatus} */
   function getSampleData() {
     const entries = {
       unreadEntries: [
diff --git a/chrome/test/data/webui/read_later/test_read_later_api_proxy.js b/chrome/test/data/webui/read_later/test_read_later_api_proxy.js
index 4c630e0..43b81b6 100644
--- a/chrome/test/data/webui/read_later/test_read_later_api_proxy.js
+++ b/chrome/test/data/webui/read_later/test_read_later_api_proxy.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://read-later.top-chrome/read_later.mojom-lite.js';
+import {PageCallbackRouter, ReadLaterEntriesByStatus} from 'chrome://read-later.top-chrome/read_later.mojom-webui.js';
 
 import {ReadLaterApiProxy} from 'chrome://read-later.top-chrome/read_later_api_proxy.js';
 import {TestBrowserProxy} from '../test_browser_proxy.js';
@@ -22,10 +22,10 @@
       'closeUI',
     ]);
 
-    /** @type {!readLater.mojom.PageCallbackRouter} */
-    this.callbackRouter = new readLater.mojom.PageCallbackRouter();
+    /** @type {!PageCallbackRouter} */
+    this.callbackRouter = new PageCallbackRouter();
 
-    /** @private {!readLater.mojom.ReadLaterEntriesByStatus} */
+    /** @private {!ReadLaterEntriesByStatus} */
     this.entries_;
   }
 
@@ -80,7 +80,7 @@
     return this.callbackRouter;
   }
 
-  /** @param {!readLater.mojom.ReadLaterEntriesByStatus} entries */
+  /** @param {!ReadLaterEntriesByStatus} entries */
   setEntries(entries) {
     this.entries_ = entries;
   }
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
index ce282c04..e340bca6 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
@@ -351,7 +351,70 @@
           settings.MultiDeviceFeature.PHONE_HUB,
           settings.MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS,
         ]);
+
+        multideviceSubpage.pageContentData =
+            Object.assign({}, multideviceSubpage.pageContentData, {
+              phoneHubNotificationsState:
+                  settings.MultiDeviceFeatureState.ENABLED_BY_USER,
+              isPhoneHubAppsAccessGranted: true,
+              notificationAccessStatus:
+                  settings.PhoneHubNotificationAccessStatus.ACCESS_GRANTED
+            });
+
+        Polymer.dom.flush();
+
         assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
+        assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubAppsItem'));
+
+        multideviceSubpage.pageContentData =
+            Object.assign({}, multideviceSubpage.pageContentData, {
+              phoneHubNotificationsState:
+                  settings.MultiDeviceFeatureState.ENABLED_BY_USER,
+              isPhoneHubAppsAccessGranted: true,
+              notificationAccessStatus:
+                  settings.PhoneHubNotificationAccessStatus
+                      .AVAILABLE_BUT_NOT_GRANTED
+            });
+
+        Polymer.dom.flush();
+
+        assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
+        assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubAppsItem'));
+
+        multideviceSubpage.pageContentData =
+            Object.assign({}, multideviceSubpage.pageContentData, {
+              phoneHubNotificationsState:
+                  settings.MultiDeviceFeatureState.ENABLED_BY_USER,
+              isPhoneHubAppsAccessGranted: false,
+              notificationAccessStatus:
+                  settings.PhoneHubNotificationAccessStatus.ACCESS_GRANTED
+            });
+
+        Polymer.dom.flush();
+
+        assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
+        assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubAppsItem'));
+
+        multideviceSubpage.pageContentData =
+            Object.assign({}, multideviceSubpage.pageContentData, {
+              phoneHubNotificationsState:
+                  settings.MultiDeviceFeatureState.ENABLED_BY_USER,
+              isPhoneHubAppsAccessGranted: false,
+              notificationAccessStatus:
+                  settings.PhoneHubNotificationAccessStatus
+                      .AVAILABLE_BUT_NOT_GRANTED
+            });
+
+        Polymer.dom.flush();
+
+        assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
         assertFalse(!!multideviceSubpage.$$('#phoneHubAppsItem'));
 
@@ -360,7 +423,22 @@
           settings.MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS,
           settings.MultiDeviceFeature.ECHE,
         ]);
+
+        multideviceSubpage.pageContentData =
+            Object.assign({}, multideviceSubpage.pageContentData, {
+              phoneHubNotificationsState:
+                  settings.MultiDeviceFeatureState.ENABLED_BY_USER,
+              phoneHubAppsState:
+                  settings.MultiDeviceFeatureState.ENABLED_BY_USER,
+              isPhoneHubAppsAccessGranted: true,
+              notificationAccessStatus:
+                  settings.PhoneHubNotificationAccessStatus.ACCESS_GRANTED
+            });
+
+        Polymer.dom.flush();
+
         assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
+        assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubAppsItem'));
 
@@ -374,8 +452,10 @@
               notificationAccessStatus:
                   settings.PhoneHubNotificationAccessStatus.ACCESS_GRANTED
             });
+
         Polymer.dom.flush();
 
+        assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
         assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubAppsItem'));
@@ -393,7 +473,7 @@
 
         Polymer.dom.flush();
 
-        assertFalse(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
+        assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubAppsItem'));
         const controllerSelector =
@@ -416,6 +496,7 @@
 
         Polymer.dom.flush();
 
+        assertTrue(!!multideviceSubpage.$$('#phoneHubItem'));
         assertTrue(!!multideviceSubpage.$$('#phoneHubCombinedSetupItem'));
         assertFalse(!!multideviceSubpage.$$('#phoneHubNotificationsItem'));
         assertFalse(!!multideviceSubpage.$$('#phoneHubAppsItem'));
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_devices_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/os_bluetooth_devices_subpage_tests.js
index 1a26f497..1328221d 100644
--- a/chrome/test/data/webui/settings/chromeos/os_bluetooth_devices_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_devices_subpage_tests.js
@@ -124,6 +124,9 @@
   test('Device lists states', async function() {
     init();
 
+    const getNoDeviceText = () =>
+        bluetoothDevicesSubpage.shadowRoot.querySelector('#noDevices');
+
     const getDeviceList = (connected) => {
       return bluetoothDevicesSubpage.shadowRoot.querySelector(
           connected ? '#connectedDeviceList' : '#unconnectedDeviceList');
@@ -131,6 +134,10 @@
     // No lists should be showing at first.
     assertFalse(!!getDeviceList(/*connected=*/ true));
     assertFalse(!!getDeviceList(/*connected=*/ false));
+    assertTrue(!!getNoDeviceText());
+    assertEquals(
+        getNoDeviceText().textContent.trim(),
+        bluetoothDevicesSubpage.i18n('bluetoothDeviceListNoConnectedDevices'));
 
     const connectedDevice = createDefaultBluetoothDevice(
         /*id=*/ '123456789', /*publicName=*/ 'BeatsX',
@@ -148,6 +155,7 @@
     assertTrue(!!getDeviceList(/*connected=*/ true));
     assertEquals(getDeviceList(/*connected=*/ true).devices.length, 1);
     assertFalse(!!getDeviceList(/*connected=*/ false));
+    assertFalse(!!getNoDeviceText());
 
     // Pair unconnected device
     bluetoothConfig.appendToPairedDeviceList([unconnectedDevice]);
@@ -157,5 +165,6 @@
     assertEquals(getDeviceList(/*connected=*/ true).devices.length, 1);
     assertTrue(!!getDeviceList(/*connected=*/ false));
     assertEquals(getDeviceList(/*connected=*/ false).devices.length, 1);
+    assertFalse(!!getNoDeviceText());
   });
 });
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_bluetooth_page_tests.js
index 6a73de3..4231bb92 100644
--- a/chrome/test/data/webui/settings/chromeos/os_bluetooth_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_page_tests.js
@@ -11,6 +11,7 @@
 // #import {assertTrue} from '../../../chai_assert.js';
 // #import {FakeBluetoothConfig} from 'chrome://test/cr_components/chromeos/bluetooth/fake_bluetooth_config.js';
 // #import {setBluetoothConfigForTesting} from 'chrome://resources/cr_components/chromeos/bluetooth/cros_bluetooth_config.js';
+// #import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
 // clang-format on
 
 suite('OsBluetoothPageTest', function() {
@@ -38,6 +39,8 @@
         bluetoothPage.$$('os-settings-bluetooth-pairing-dialog');
     const bluetoothSummary = bluetoothPage.$$('os-settings-bluetooth-summary');
 
+    const getPairNewDevice = () => bluetoothPage.$$('#pairNewDevice');
+
     assertTrue(!!bluetoothSummary);
     assertFalse(!!getBluetoothPairingUi());
 
@@ -50,5 +53,15 @@
 
     await flushAsync();
     assertFalse(!!getBluetoothPairingUi());
+
+    settings.Router.getInstance().navigateTo(
+        settings.routes.BLUETOOTH_DEVICES, null);
+
+    assertTrue(!!getPairNewDevice());
+    getPairNewDevice().click();
+
+    await flushAsync();
+    assertTrue(!!getBluetoothPairingUi());
+
   });
 });
\ No newline at end of file
diff --git a/chrome/test/data/webui/tab_strip/BUILD.gn b/chrome/test/data/webui/tab_strip/BUILD.gn
deleted file mode 100644
index 5128cd65..0000000
--- a/chrome/test/data/webui/tab_strip/BUILD.gn
+++ /dev/null
@@ -1,130 +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/compile_js.gni")
-
-js_type_check("closure_compile") {
-  is_polymer3 = true
-  closure_flags = default_closure_args + mojom_js_args + [
-                    "browser_resolver_prefix_replacements=\"chrome://tab-strip.top-chrome/=./\"",
-                    "js_module_root=" +
-                        rebase_path("//chrome/browser/resources/tab_strip",
-                                    root_build_dir),
-                    "js_module_root=" +
-                        rebase_path("//chrome/test/data/webui", root_build_dir),
-                    "js_module_root=" +
-                        rebase_path("$root_gen_dir/chrome/test/data/webui",
-                                    root_build_dir),
-                    "js_module_root=" + rebase_path(
-                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/tab_strip",
-                            root_build_dir),
-                    "js_module_root=" + rebase_path(
-                            "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/tabs",
-                            root_build_dir),
-                  ]
-  deps = [
-    ":alert_indicator_test",
-    ":alert_indicators_test",
-    ":drag_manager_test",
-    ":tab_group_test",
-
-    # Disable JS type check tab_list_test for simplicity, we will lose this
-    # coverage when convert to typescript anyways.
-    # ":tab_list_test",
-    ":tab_swiper_test",
-    ":tab_test",
-    ":test_tabs_api_proxy",
-  ]
-}
-
-js_library("test_tabs_api_proxy") {
-  deps = [
-    "..:test_browser_proxy",
-    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
-    "//chrome/browser/ui/webui/tab_strip:mojo_bindings_js_library_for_compile",
-  ]
-}
-
-js_library("alert_indicator_test") {
-  deps = [
-    "..:chai_assert",
-    "//chrome/browser/resources/tab_strip:alert_indicator",
-    "//chrome/browser/ui/webui/tabs:mojo_bindings_webui_js",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
-
-js_library("alert_indicators_test") {
-  deps = [
-    "..:chai_assert",
-    "//chrome/browser/resources/tab_strip:alert_indicator",
-    "//chrome/browser/resources/tab_strip:alert_indicators",
-    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
-
-js_library("drag_manager_test") {
-  deps = [
-    ":test_tabs_api_proxy",
-    "..:chai_assert",
-    "//chrome/browser/resources/tab_strip:drag_manager",
-    "//chrome/browser/resources/tab_strip:tab",
-    "//chrome/browser/resources/tab_strip:tab_group",
-    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
-    "//ui/webui/resources/js:cr.m",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
-
-js_library("tab_group_test") {
-  deps = [
-    "..:chai_assert",
-    "//chrome/browser/resources/tab_strip:tab",
-    "//chrome/browser/resources/tab_strip:tab_group",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
-
-js_library("tab_list_test") {
-  deps = [
-    ":test_tabs_api_proxy",
-    "..:chai_assert",
-    "..:test_util",
-    "//chrome/browser/resources/tab_strip:tab",
-    "//chrome/browser/resources/tab_strip:tab_group",
-    "//chrome/browser/resources/tab_strip:tab_list",
-    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
-    "//ui/webui/resources/js:cr.m",
-    "//ui/webui/resources/js:load_time_data.m",
-    "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
-  ]
-  externs_list = [
-    "$externs_path/mocha-2.5.js",
-    "$externs_path/pending.js",
-  ]
-}
-
-js_library("tab_swiper_test") {
-  deps = [
-    ":test_tabs_api_proxy",
-    "..:chai_assert",
-    "..:test_util",
-    "//chrome/browser/resources/tab_strip:tab_swiper",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
-
-js_library("tab_test") {
-  deps = [
-    ":test_tabs_api_proxy",
-    "..:chai_assert",
-    "//chrome/browser/resources/tab_strip:tab",
-    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
-    "//ui/webui/resources/js:icon",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-  externs_list = [ "$externs_path/mocha-2.5.js" ]
-}
diff --git a/chrome/test/data/webui/tab_strip/drag_manager_test.js b/chrome/test/data/webui/tab_strip/drag_manager_test.js
index 99e9a97..81f0e413 100644
--- a/chrome/test/data/webui/tab_strip/drag_manager_test.js
+++ b/chrome/test/data/webui/tab_strip/drag_manager_test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 import {isChromeOS} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {DragManager, DragManagerDelegate, PLACEHOLDER_GROUP_ID, PLACEHOLDER_TAB_ID} from 'chrome://tab-strip.top-chrome/drag_manager.js';
+import {DragManager, PLACEHOLDER_GROUP_ID, PLACEHOLDER_TAB_ID} from 'chrome://tab-strip.top-chrome/drag_manager.js';
 import {TabElement} from 'chrome://tab-strip.top-chrome/tab.js';
 import {TabGroupElement} from 'chrome://tab-strip.top-chrome/tab_group.js';
 import {Tab} from 'chrome://tab-strip.top-chrome/tab_strip.mojom-webui.js';
@@ -137,7 +137,7 @@
   setup(() => {
     loadTimeData.overrideValues(strings);
     testTabsApiProxy = new TestTabsApiProxy();
-    TabsApiProxyImpl.instance_ = testTabsApiProxy;
+    TabsApiProxyImpl.setInstance(testTabsApiProxy);
 
     delegate = new MockDelegate();
     tabs.forEach(tab => {
diff --git a/chrome/test/data/webui/tab_strip/tab_group_test.js b/chrome/test/data/webui/tab_strip/tab_group_test.js
index 0b068311..1cae7c5 100644
--- a/chrome/test/data/webui/tab_strip/tab_group_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_group_test.js
@@ -22,7 +22,7 @@
 
   setup(() => {
     testTabsApiProxy = new TestTabsApiProxy();
-    TabsApiProxyImpl.instance_ = testTabsApiProxy;
+    TabsApiProxyImpl.setInstance(testTabsApiProxy);
 
     document.body.innerHTML = '';
     tabGroupElement = /** @type {!TabGroupElement} */ (
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.js b/chrome/test/data/webui/tab_strip/tab_list_test.js
index 90884abc..bcec405 100644
--- a/chrome/test/data/webui/tab_strip/tab_list_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_list_test.js
@@ -125,7 +125,7 @@
 
     testTabsApiProxy = new TestTabsApiProxy();
     testTabsApiProxy.setTabs(tabs);
-    TabsApiProxyImpl.instance_ = testTabsApiProxy;
+    TabsApiProxyImpl.setInstance(testTabsApiProxy);
     callbackRouter = testTabsApiProxy.getCallbackRouterRemote();
 
     testTabsApiProxy.setColors({
diff --git a/chrome/test/data/webui/tab_strip/tab_test.js b/chrome/test/data/webui/tab_strip/tab_test.js
index 4841a4b6..1b995be 100644
--- a/chrome/test/data/webui/tab_strip/tab_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_test.js
@@ -63,7 +63,7 @@
     document.body.style.setProperty('--tabstrip-tab-spacing', '20px');
 
     testTabsApiProxy = new TestTabsApiProxy();
-    TabsApiProxyImpl.instance_ = testTabsApiProxy;
+    TabsApiProxyImpl.setInstance(testTabsApiProxy);
 
     tabElement =
         /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
diff --git a/chrome/test/data/webui/tab_strip/test_tab_strip_embedder_proxy.js b/chrome/test/data/webui/tab_strip/test_tab_strip_embedder_proxy.js
deleted file mode 100644
index 4a4231f..0000000
--- a/chrome/test/data/webui/tab_strip/test_tab_strip_embedder_proxy.js
+++ /dev/null
@@ -1,110 +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 {TabStripEmbedderProxy} from 'chrome://tab-strip.top-chrome/tab_strip_embedder_proxy.js';
-
-import {TestBrowserProxy} from '../test_browser_proxy.js';
-
-/** @implements {TabStripEmbedderProxy} */
-export class TestTabStripEmbedderProxy extends TestBrowserProxy {
-  constructor() {
-    super([
-      'closeContainer',
-      'getColors',
-      'getLayout',
-      'isVisible',
-      'observeThemeChanges',
-      'showBackgroundContextMenu',
-      'showEditDialogForGroup',
-      'showTabContextMenu',
-      'reportTabActivationDuration',
-      'reportTabDataReceivedDuration',
-      'reportTabCreationDuration',
-    ]);
-
-    /** @private {!Object<string, string>} */
-    this.colors_ = {};
-
-    /** @private {!Object<string, string>} */
-    this.layout_ = {};
-
-    /** @private {boolean} */
-    this.visible_ = false;
-  }
-
-  /** @override */
-  getColors() {
-    this.methodCalled('getColors');
-    return Promise.resolve(this.colors_);
-  }
-
-  /** @override */
-  getLayout() {
-    this.methodCalled('getLayout');
-    return Promise.resolve(this.layout_);
-  }
-
-  /** @override */
-  isVisible() {
-    this.methodCalled('isVisible');
-    return this.visible_;
-  }
-
-  /** @param {!Object<string, string>} colors */
-  setColors(colors) {
-    this.colors_ = colors;
-  }
-
-  /** @param {!Object<string, string>} layout */
-  setLayout(layout) {
-    this.layout_ = layout;
-  }
-
-  /** @param {boolean} visible */
-  setVisible(visible) {
-    this.visible_ = visible;
-  }
-
-  /** @override */
-  observeThemeChanges() {
-    this.methodCalled('observeThemeChanges');
-  }
-
-  /** @override */
-  closeContainer() {
-    this.methodCalled('closeContainer');
-  }
-
-  /** @override */
-  showBackgroundContextMenu(locationX, locationY) {
-    this.methodCalled('showBackgroundContextMenu', [locationX, locationY]);
-  }
-
-  /** @override */
-  showEditDialogForGroup(groupId, locationX, locationY, width, height) {
-    this.methodCalled(
-        'showEditDialogForGroup',
-        [groupId, locationX, locationY, width, height]);
-  }
-
-  /** @override */
-  showTabContextMenu(tabId, locationX, locationY) {
-    this.methodCalled('showTabContextMenu', [tabId, locationX, locationY]);
-  }
-
-  /** @override */
-  reportTabActivationDuration(durationMs) {
-    this.methodCalled('reportTabActivationDuration', [durationMs]);
-  }
-
-  /** @override */
-  reportTabDataReceivedDuration(tabCount, durationMs) {
-    this.methodCalled('reportTabDataReceivedDuration', [tabCount, durationMs]);
-  }
-
-  /** @override */
-  reportTabCreationDuration(tabCount, durationMs) {
-    this.methodCalled('reportTabCreationDuration', [tabCount, durationMs]);
-  }
-}
diff --git a/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js b/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
index 1d155b0..2fbb90f 100644
--- a/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
+++ b/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
@@ -4,7 +4,6 @@
 
 import {PageCallbackRouter, PageRemote} from 'chrome://tab-strip.top-chrome/tab_strip.mojom-webui.js';
 import {Tab, TabGroupVisualData} from 'chrome://tab-strip.top-chrome/tab_strip.mojom-webui.js';
-import {ExtensionsApiTab, TabsApiProxy} from 'chrome://tab-strip.top-chrome/tabs_api_proxy.js';
 
 import {TestBrowserProxy} from '../test_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/whats_new/whats_new_app_test.js b/chrome/test/data/webui/whats_new/whats_new_app_test.js
index cb6f4cd3..77af1ff 100644
--- a/chrome/test/data/webui/whats_new/whats_new_app_test.js
+++ b/chrome/test/data/webui/whats_new/whats_new_app_test.js
@@ -30,11 +30,8 @@
   }
 
   /** @override */
-  initialize(isAuto) {
-    this.methodCalled('initialize', isAuto);
-    // Even in the case of failure, the preload URL will still be the What's New
-    // URL. It is then updated when the promise resolves.
-    webUIListenerCallback('preload-url', this.url_ ? this.url_ : whatsNewURL);
+  initialize() {
+    this.methodCalled('initialize');
     return Promise.resolve(this.url_);
   }
 }
@@ -54,21 +51,16 @@
     window.history.replaceState({}, '', '?auto=true');
     const whatsNewApp = document.createElement('whats-new-app');
     document.body.appendChild(whatsNewApp);
-    const isAuto = await proxy.whenCalled('initialize');
-    assertEquals(!isChromeOS, isAuto);
+    await proxy.whenCalled('initialize');
     await flushTasks();
 
     const iframe = whatsNewApp.shadowRoot.querySelector('#content');
     assertTrue(!!iframe);
-    assertFalse(iframe.hidden);
     // iframe has latest=true URL query parameter except on CrOS
     assertEquals(
         whatsNewURL + (isChromeOS ? '?latest=false' : '?latest=true') +
             '&feedback=true',
         iframe.src);
-    const errorPage =
-        whatsNewApp.shadowRoot.querySelector('whats-new-error-page');
-    assertFalse(!!errorPage);
   });
 
   test('with version as query parameter', async () => {
@@ -78,13 +70,11 @@
     window.history.replaceState({}, '', '?auto=true');
     const whatsNewApp = document.createElement('whats-new-app');
     document.body.appendChild(whatsNewApp);
-    const isAuto = await proxy.whenCalled('initialize');
-    assertEquals(!isChromeOS, isAuto);
+    await proxy.whenCalled('initialize');
     await flushTasks();
 
     const iframe = whatsNewApp.shadowRoot.querySelector('#content');
     assertTrue(!!iframe);
-    assertFalse(iframe.hidden);
     // iframe has latest=true URL query parameter except on CrOS
     assertEquals(
         whatsNewURL + '?version=m98' +
@@ -99,36 +89,12 @@
     window.history.replaceState({}, '', '/');
     const whatsNewApp = document.createElement('whats-new-app');
     document.body.appendChild(whatsNewApp);
-    const isAuto = await proxy.whenCalled('initialize');
-    assertFalse(isAuto);
+    await proxy.whenCalled('initialize');
     await flushTasks();
 
     const iframe = whatsNewApp.shadowRoot.querySelector('#content');
     assertTrue(!!iframe);
-    assertFalse(iframe.hidden);
     assertEquals(whatsNewURL + '?latest=false&feedback=false', iframe.src);
-    const errorPage =
-        whatsNewApp.shadowRoot.querySelector('whats-new-error-page');
-    assertFalse(!!errorPage);
-  });
-
-  test('no query parameter failure', async () => {
-    // Simulate a failure to load the remote content.
-    const proxy = new TestWhatsNewProxy(null);
-    WhatsNewProxyImpl.setInstance(proxy);
-    window.history.replaceState({}, '', '/');
-    const whatsNewApp = document.createElement('whats-new-app');
-    document.body.appendChild(whatsNewApp);
-    const isAuto = await proxy.whenCalled('initialize');
-    assertFalse(isAuto);
-    await flushTasks();
-
-    // Shows the error page in place of the iframe.
-    const iframe = whatsNewApp.shadowRoot.querySelector('#content');
-    assertTrue(iframe.hidden);
-    const errorPage =
-        whatsNewApp.shadowRoot.querySelector('whats-new-error-page');
-    assertTrue(!!errorPage);
   });
 
   test('with command', async () => {
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 40ae4bd..b8b11e0 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -248,6 +248,7 @@
     "//components/cast/message_port:message_port_cast",
     "//components/cdm/browser",
     "//components/download/public/common:public",
+    "//components/heap_profiling/multi_process",
     "//components/media_control/browser",
     "//components/memory_pressure",
     "//components/metrics",
@@ -267,6 +268,9 @@
     "//components/proxy_config",
     "//components/safe_search_api",
     "//components/safe_search_api:safe_search_client",
+    "//components/services/heap_profiling",
+    "//components/services/heap_profiling/public/cpp",
+    "//components/services/heap_profiling/public/mojom",
     "//components/viz/service",
     "//content/public/browser",
     "//content/public/common",
@@ -364,15 +368,6 @@
       "//components/crash/content/browser",
       "//components/crash/core/app",
     ]
-
-    # TODO(crbug.com/933142): Fuchsia needs its own methods to bridge with heap
-    # profiling service
-    deps += [
-      "//components/heap_profiling/multi_process",
-      "//components/services/heap_profiling",
-      "//components/services/heap_profiling/public/cpp",
-      "//components/services/heap_profiling/public/mojom",
-    ]
   }
 
   if (use_ozone) {
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index ad5e57f3..6a2b6bb4 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/cxx17_backports.h"
 #include "base/files/file_util.h"
@@ -41,14 +42,21 @@
 #include "chromecast/browser/cast_feature_list_creator.h"
 #include "chromecast/browser/cast_system_memory_pressure_evaluator.h"
 #include "chromecast/browser/cast_system_memory_pressure_evaluator_adjuster.h"
+#include "chromecast/browser/cast_web_service.h"
 #include "chromecast/browser/devtools/remote_debugging_server.h"
 #include "chromecast/browser/media/media_caps_impl.h"
 #include "chromecast/browser/metrics/cast_browser_metrics.h"
 #include "chromecast/browser/metrics/metrics_helper_impl.h"
+#include "chromecast/browser/mojom/cast_web_service.mojom.h"
 #include "chromecast/browser/service_connector.h"
 #include "chromecast/browser/service_manager_connection.h"
 #include "chromecast/browser/service_manager_context.h"
 #include "chromecast/chromecast_buildflags.h"
+#include "chromecast/common/mojom/constants.mojom.h"
+#include "chromecast/common/mojom/identification_settings.mojom.h"
+#include "chromecast/external_mojo/broker_service/broker_service.h"
+#include "chromecast/external_mojo/external_service_support/external_connector.h"
+#include "chromecast/external_mojo/external_service_support/external_service.h"
 #include "chromecast/graphics/cast_window_manager.h"
 #include "chromecast/media/base/key_systems_common.h"
 #include "chromecast/media/base/video_plane_controller.h"
@@ -58,6 +66,8 @@
 #include "chromecast/net/connectivity_checker.h"
 #include "chromecast/public/cast_media_shlib.h"
 #include "chromecast/service/cast_service.h"
+#include "components/heap_profiling/multi_process/client_connection_manager.h"
+#include "components/heap_profiling/multi_process/supervisor.h"
 #include "components/prefs/pref_service.h"
 #include "components/viz/common/switches.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -142,11 +152,8 @@
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
 #if !defined(OS_FUCHSIA)
-#include "base/callback_helpers.h"
 #include "chromecast/base/cast_sys_info_util.h"
 #include "chromecast/public/cast_sys_info.h"
-#include "components/heap_profiling/multi_process/client_connection_manager.h"  // nogncheck
-#include "components/heap_profiling/multi_process/supervisor.h"  // nogncheck
 #endif  // !defined(OS_FUCHSIA)
 
 namespace {
@@ -248,8 +255,6 @@
 
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
-#if !defined(OS_FUCHSIA)
-
 std::unique_ptr<heap_profiling::ClientConnectionManager>
 CreateClientConnectionManager(
     base::WeakPtr<heap_profiling::Controller> controller_weak_ptr,
@@ -258,8 +263,6 @@
       std::move(controller_weak_ptr), mode);
 }
 
-#endif
-
 #if defined(USE_AURA)
 
 // Provide a basic implementation. No need to override anything since we're not
@@ -404,7 +407,6 @@
       cast_browser_process_(new CastBrowserProcess()),
       parameters_(std::move(parameters)),
       cast_content_browser_client_(cast_content_browser_client),
-
       media_caps_(std::make_unique<media::MediaCapsImpl>()),
       metrics_helper_(std::make_unique<metrics::MetricsHelperImpl>()),
       cast_system_memory_pressure_evaluator_adjuster_(nullptr) {
@@ -459,6 +461,22 @@
   return cast_browser_process_->browser_context();
 }
 
+external_mojo::BrokerService* CastBrowserMainParts::broker_service() {
+  CHECK(broker_service_);
+  return broker_service_.get();
+}
+
+external_service_support::ExternalConnector* CastBrowserMainParts::connector() {
+  CHECK(connector_);
+  return connector_.get();
+}
+
+external_service_support::ExternalConnector*
+CastBrowserMainParts::media_connector() {
+  CHECK(media_connector_);
+  return media_connector_.get();
+}
+
 void CastBrowserMainParts::PreCreateMainMessageLoop() {
   // GroupedHistograms needs to be initialized before any threads are created
   // to prevent race conditions between calls to Preregister and those threads
@@ -527,6 +545,23 @@
   return 0;
 }
 
+void CastBrowserMainParts::PostCreateThreads() {
+  auto* service_manager_connector =
+      ServiceManagerConnection::GetForProcess()->GetConnector();
+  broker_service_ =
+      std::make_unique<external_mojo::BrokerService>(service_manager_connector);
+  connector_ = external_service_support::ExternalConnector::Create(
+      broker_service_->CreateConnector());
+  media_connector_ = connector_->Clone();
+  browser_service_ =
+      std::make_unique<external_service_support::ExternalService>();
+  heap_profiling::Supervisor* supervisor =
+      heap_profiling::Supervisor::GetInstance();
+  supervisor->SetClientConnectionManagerConstructor(
+      &CreateClientConnectionManager);
+  supervisor->Start(base::NullCallback());
+}
+
 int CastBrowserMainParts::PreMainMessageLoopRun() {
 #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
   memory_pressure_monitor_.reset(
@@ -638,12 +673,22 @@
   ::media::InitializeMediaLibrary();
   media_caps_->Initialize();
 
+  web_service_ = std::make_unique<CastWebService>(
+      cast_browser_process_->browser_context(), window_manager_.get());
+  browser_service_->AddInterface<::chromecast::mojom::CastWebService>(
+      web_service_.get());
+  browser_service_
+      ->AddInterface<::chromecast::mojom::BrowserIdentificationSettingsManager>(
+          web_service_.get());
+  connector()->RegisterService(::chromecast::mojom::kCastBrowserServiceName,
+                               browser_service_.get());
+
   cast_browser_process_->SetCastService(
       cast_browser_process_->browser_client()->CreateCastService(
           cast_browser_process_->browser_context(),
           cast_system_memory_pressure_evaluator_adjuster_,
-          cast_browser_process_->pref_service(),
-          video_plane_controller_.get(), window_manager_.get()));
+          cast_browser_process_->pref_service(), video_plane_controller_.get(),
+          window_manager_.get(), web_service_.get()));
   cast_browser_process_->cast_service()->Initialize();
 
 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
@@ -803,17 +848,6 @@
   service_manager_context_.reset();
 }
 
-void CastBrowserMainParts::PostCreateThreads() {
-  cast_content_browser_client_->InitializeExternalConnector();
-#if !defined(OS_FUCHSIA)
-  heap_profiling::Supervisor* supervisor =
-      heap_profiling::Supervisor::GetInstance();
-  supervisor->SetClientConnectionManagerConstructor(
-      &CreateClientConnectionManager);
-  supervisor->Start(base::NullCallback());
-#endif  // !defined(OS_FUCHSIA)
-}
-
 void CastBrowserMainParts::PostDestroyThreads() {
 #if !defined(OS_ANDROID)
   cast_content_browser_client_->ResetMediaResourceTracker();
diff --git a/chromecast/browser/cast_browser_main_parts.h b/chromecast/browser/cast_browser_main_parts.h
index 97662b4..d9d2de35 100644
--- a/chromecast/browser/cast_browser_main_parts.h
+++ b/chromecast/browser/cast_browser_main_parts.h
@@ -36,6 +36,7 @@
 
 namespace chromecast {
 class CastSystemMemoryPressureEvaluatorAdjuster;
+class CastWebService;
 class ServiceConnector;
 class ServiceManagerContext;
 class WaylandServerController;
@@ -51,6 +52,15 @@
 class CastWindowManager;
 #endif  // #if defined(USE_AURA)
 
+namespace external_mojo {
+class BrokerService;
+}  // namespace external_mojo
+
+namespace external_service_support {
+class ExternalConnector;
+class ExternalService;
+}  // namespace external_service_support
+
 namespace media {
 class MediaCapsImpl;
 class MediaPipelineBackendManager;
@@ -86,17 +96,20 @@
   media::MediaCapsImpl* media_caps();
   metrics::MetricsHelperImpl* metrics_helper();
   content::BrowserContext* browser_context();
+  external_mojo::BrokerService* broker_service();
+  external_service_support::ExternalConnector* connector();
+  external_service_support::ExternalConnector* media_connector();
 
   // content::BrowserMainParts implementation:
   void PreCreateMainMessageLoop() override;
   void PostCreateMainMessageLoop() override;
   void ToolkitInitialized() override;
   int PreCreateThreads() override;
+  void PostCreateThreads() override;
   int PreMainMessageLoopRun() override;
   void WillRunMainMessageLoop(
       std::unique_ptr<base::RunLoop>& run_loop) override;
   void PostMainMessageLoopRun() override;
-  void PostCreateThreads() override;
   void PostDestroyThreads() override;
 
  private:
@@ -110,6 +123,14 @@
   std::unique_ptr<metrics::MetricsHelperImpl> metrics_helper_;
   std::unique_ptr<ServiceConnector> service_connector_;
 
+  // Created in CastBrowserMainParts::PostCreateThreads():
+  std::unique_ptr<external_mojo::BrokerService> broker_service_;
+  std::unique_ptr<external_service_support::ExternalService> browser_service_;
+  // ExternalConnectors should be destroyed before registered services.
+  std::unique_ptr<external_service_support::ExternalConnector> connector_;
+  // ExternalConnector for running on the media task runner.
+  std::unique_ptr<external_service_support::ExternalConnector> media_connector_;
+
 #if defined(USE_AURA)
   std::unique_ptr<views::ViewsDelegate> views_delegate_;
   std::unique_ptr<CastScreen> cast_screen_;
@@ -119,6 +140,7 @@
 #else
   std::unique_ptr<CastWindowManager> window_manager_;
 #endif  //  defined(USE_AURA)
+  std::unique_ptr<CastWebService> web_service_;
 
 #if defined(OS_ANDROID)
   void StartPeriodicCrashReportUpload();
diff --git a/chromecast/browser/cast_browser_process.cc b/chromecast/browser/cast_browser_process.cc
index c01cb84..56a62582 100644
--- a/chromecast/browser/cast_browser_process.cc
+++ b/chromecast/browser/cast_browser_process.cc
@@ -11,6 +11,7 @@
 #include "chromecast/browser/cast_browser_context.h"
 #include "chromecast/browser/cast_content_browser_client.h"
 #include "chromecast/browser/cast_network_contexts.h"
+#include "chromecast/browser/cast_web_service.h"
 #include "chromecast/browser/devtools/remote_debugging_server.h"
 #include "chromecast/browser/metrics/cast_browser_metrics.h"
 #include "chromecast/metrics/cast_metrics_service_client.h"
@@ -41,13 +42,7 @@
   return g_instance;
 }
 
-CastBrowserProcess::CastBrowserProcess()
-    :
-#if defined(USE_AURA)
-      cast_screen_(nullptr),
-#endif
-      web_view_factory_(nullptr),
-      cast_content_browser_client_(nullptr) {
+CastBrowserProcess::CastBrowserProcess() {
   DCHECK(!g_instance);
   g_instance = this;
 }
@@ -138,12 +133,6 @@
   connectivity_checker_.swap(connectivity_checker);
 }
 
-void CastBrowserProcess::SetWebViewFactory(
-    CastWebViewFactory* web_view_factory) {
-  DCHECK(!web_view_factory_);
-  web_view_factory_ = web_view_factory;
-}
-
 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
 void CastBrowserProcess::AccessibilityStateChanged(bool enabled) {
   cast_service_->AccessibilityStateChanged(enabled);
diff --git a/chromecast/browser/cast_browser_process.h b/chromecast/browser/cast_browser_process.h
index 00366a8..15067543 100644
--- a/chromecast/browser/cast_browser_process.h
+++ b/chromecast/browser/cast_browser_process.h
@@ -16,7 +16,7 @@
 namespace chromecast {
 class CastService;
 class CastScreen;
-class CastWebViewFactory;
+class CastWindowManager;
 class ConnectivityChecker;
 
 namespace metrics {
@@ -48,6 +48,8 @@
 
   virtual ~CastBrowserProcess();
 
+  void PreMainMessageLoopRun(CastWindowManager* window_manager);
+
   void SetBrowserContext(std::unique_ptr<CastBrowserContext> browser_context);
   void SetCastContentBrowserClient(CastContentBrowserClient* browser_client);
   void SetCastService(std::unique_ptr<CastService> cast_service);
@@ -73,7 +75,6 @@
       std::unique_ptr<RemoteDebuggingServer> remote_debugging_server);
   void SetConnectivityChecker(
       scoped_refptr<ConnectivityChecker> connectivity_checker);
-  void SetWebViewFactory(CastWebViewFactory* web_view_factory);
 
   CastContentBrowserClient* browser_client() const {
     return cast_content_browser_client_;
@@ -103,28 +104,31 @@
   RemoteDebuggingServer* remote_debugging_server() const {
     return remote_debugging_server_.get();
   }
-  CastWebViewFactory* web_view_factory() const { return web_view_factory_; }
 
  private:
-  // Note: The following order should match the order they are set in
-  // CastBrowserMainParts.
-#if defined(USE_AURA)
-  CastScreen* cast_screen_;
-  std::unique_ptr<CastDisplayConfigurator> display_configurator_;
+  // Note: The following objects should be declared in the same order as they
+  // are set in CastBrowserMainParts.
 
-#if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
-  std::unique_ptr<AccessibilityManager> accessibility_manager_;
-#endif  // BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
+  // Created just after CastBrowserMainParts ctor:
+  CastContentBrowserClient* cast_content_browser_client_ = nullptr;
 
-#endif  // defined(USE_AURA)
+  // Created in CastBrowserMainParts::PreCreateThreads:
   std::unique_ptr<PrefService> pref_service_;
-  scoped_refptr<ConnectivityChecker> connectivity_checker_;
+#if defined(USE_AURA)
+  CastScreen* cast_screen_ = nullptr;
+  std::unique_ptr<CastDisplayConfigurator> display_configurator_;
+#endif  // defined(USE_AURA)
+
+  // Created in CastBrowserMainParts::PreMainMessageLoopRun:
   std::unique_ptr<CastBrowserContext> browser_context_;
+  scoped_refptr<ConnectivityChecker> connectivity_checker_;
   std::unique_ptr<metrics::CastBrowserMetrics> cast_browser_metrics_;
   std::unique_ptr<RemoteDebuggingServer> remote_debugging_server_;
-
-  CastWebViewFactory* web_view_factory_;
-  CastContentBrowserClient* cast_content_browser_client_;
+#if defined(USE_AURA) && BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
+  // Destroyed in PostMainMessageLoopRun, just after CastService::Stop(). It's
+  // not clear why this has to be destroyed before CastService.
+  std::unique_ptr<AccessibilityManager> accessibility_manager_;
+#endif  // defined(USE_AURA) && BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
 
   // Note: CastService must be destroyed before others.
   std::unique_ptr<CastService> cast_service_;
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 06e0c9f..0577227 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -53,6 +53,7 @@
 #include "chromecast/browser/service_manager_context.h"
 #include "chromecast/common/global_descriptors.h"
 #include "chromecast/common/user_agent.h"
+#include "chromecast/external_mojo/broker_service/broker_service.h"
 #include "chromecast/media/audio/cast_audio_manager.h"
 #include "chromecast/media/cdm/cast_cdm_factory.h"
 #include "chromecast/media/cdm/cast_cdm_origin_provider.h"
@@ -187,16 +188,6 @@
   cast_network_contexts_.reset();
 }
 
-void CastContentBrowserClient::InitializeExternalConnector() {
-  auto* service_manager_connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-  broker_service_ =
-      std::make_unique<external_mojo::BrokerService>(service_manager_connector);
-  connector_ = external_service_support::ExternalConnector::Create(
-      broker_service_->CreateConnector());
-  media_connector_ = connector_->Clone();
-}
-
 std::unique_ptr<ServiceConnector>
 CastContentBrowserClient::CreateServiceConnector() {
   return std::make_unique<ServiceConnector>();
@@ -208,8 +199,9 @@
         cast_system_memory_pressure_evaluator_adjuster,
     PrefService* pref_service,
     media::VideoPlaneController* video_plane_controller,
-    CastWindowManager* window_manager) {
-  return std::make_unique<CastServiceSimple>(browser_context, window_manager);
+    CastWindowManager* window_manager,
+    CastWebService* web_service) {
+  return std::make_unique<CastServiceSimple>(web_service);
 }
 
 media::VideoModeSwitcher* CastContentBrowserClient::GetVideoModeSwitcher() {
@@ -286,7 +278,8 @@
       std::move(audio_thread), audio_log_factory, cast_session_id_map,
       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
                           base::Unretained(this)),
-      content::GetUIThreadTaskRunner({}), GetMediaTaskRunner(), connector(),
+      content::GetUIThreadTaskRunner({}), GetMediaTaskRunner(),
+      browser_main_parts()->connector(),
       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
 #elif defined(OS_ANDROID)
   if (base::FeatureList::IsEnabled(kEnableChromeAudioManagerAndroid)) {
@@ -299,13 +292,14 @@
       std::move(audio_thread), audio_log_factory, cast_session_id_map,
       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
                           base::Unretained(this)),
-      GetMediaTaskRunner(), connector());
+      GetMediaTaskRunner(), browser_main_parts()->connector());
 #else
   return std::make_unique<media::CastAudioManager>(
       std::move(audio_thread), audio_log_factory, cast_session_id_map,
       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
                           base::Unretained(this)),
-      content::GetUIThreadTaskRunner({}), GetMediaTaskRunner(), connector(),
+      content::GetUIThreadTaskRunner({}), GetMediaTaskRunner(),
+      browser_main_parts()->connector(),
       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
 #endif
 }
@@ -963,7 +957,7 @@
   DCHECK(!general_audience_browsing_service_);
   general_audience_browsing_service_ =
       std::make_unique<GeneralAudienceBrowsingService>(
-          connector(),
+          browser_main_parts()->connector(),
           cast_network_contexts_->GetSystemSharedURLLoaderFactory());
 }
 
@@ -983,7 +977,7 @@
           GetCmaBackendFactory(), std::move(media_task_runner),
           GetVideoModeSwitcher(), GetVideoResolutionPolicy(),
           base::UnguessableToken::Create(), nullptr /* frame_interfaces */,
-          connector()),
+          browser_main_parts()->connector()),
       std::move(receiver));
 }
 
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index c4b7894..96be8f7e 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -15,8 +15,6 @@
 #include "build/build_config.h"
 #include "build/buildflag.h"
 #include "chromecast/chromecast_buildflags.h"
-#include "chromecast/external_mojo/broker_service/broker_service.h"
-#include "chromecast/external_mojo/external_service_support/external_connector.h"
 #include "chromecast/metrics/cast_metrics_service_client.h"
 #include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/content_browser_client.h"
@@ -62,6 +60,7 @@
 namespace chromecast {
 class CastService;
 class CastSystemMemoryPressureEvaluatorAdjuster;
+class CastWebService;
 class CastWindowManager;
 class CastFeatureListCreator;
 class GeneralAudienceBrowsingService;
@@ -102,14 +101,6 @@
 
   ~CastContentBrowserClient() override;
 
-  // Generally we discourage Initialize methods. Unfortunately, we can't do
-  // total RAII in ContentBrowserClient subclasses because we're missing a lot
-  // of foundational browser state/context at creation time, such as task
-  // runners. The earliest time that we can create most Cast objects is in
-  // CastBrowserMainParts::PostCreateThreads(), which is when this method is
-  // called.
-  void InitializeExternalConnector();
-
   // Creates a ServiceConnector for routing Cast-related service interface
   // binding requests.
   virtual std::unique_ptr<chromecast::ServiceConnector>
@@ -122,7 +113,8 @@
           cast_system_memory_pressure_evaluator_adjuster,
       PrefService* pref_service,
       media::VideoPlaneController* video_plane_controller,
-      CastWindowManager* window_manager);
+      CastWindowManager* window_manager,
+      CastWebService* web_service);
 
   virtual media::VideoModeSwitcher* GetVideoModeSwitcher();
 
@@ -289,23 +281,15 @@
   CastNetworkContexts* cast_network_contexts() {
     return cast_network_contexts_.get();
   }
-  external_mojo::BrokerService* broker_service() {
-    CHECK(broker_service_);
-    return broker_service_.get();
-  }
-  external_service_support::ExternalConnector* connector() {
-    CHECK(connector_);
-    return connector_.get();
-  }
-  external_service_support::ExternalConnector* media_connector() {
-    CHECK(media_connector_);
-    return media_connector_.get();
-  }
 
  protected:
   explicit CastContentBrowserClient(
       CastFeatureListCreator* cast_feature_list_creator);
 
+  CastBrowserMainParts* browser_main_parts() {
+    return cast_browser_main_parts_;
+  }
+
   void BindMediaRenderer(
       mojo::PendingReceiver<::media::mojom::Renderer> receiver);
 
@@ -379,14 +363,6 @@
   std::unique_ptr<GeneralAudienceBrowsingService>
       general_audience_browsing_service_;
 
-  // These need to be accessible from internal code, so they live here instead
-  // of CastBrowserMainParts.
-  std::unique_ptr<external_mojo::BrokerService> broker_service_;
-  std::unique_ptr<external_service_support::ExternalConnector> connector_;
-
-  // ExternalConnector for running on the media task runner.
-  std::unique_ptr<external_service_support::ExternalConnector> media_connector_;
-
   CastFeatureListCreator* cast_feature_list_creator_;
 };
 
diff --git a/chromecast/browser/cast_content_browser_client_receiver_bindings.cc b/chromecast/browser/cast_content_browser_client_receiver_bindings.cc
index 7983a96..276ef5b 100644
--- a/chromecast/browser/cast_content_browser_client_receiver_bindings.cc
+++ b/chromecast/browser/cast_content_browser_client_receiver_bindings.cc
@@ -173,7 +173,8 @@
       GetCmaBackendFactory(),
       base::BindRepeating(&CastContentBrowserClient::CreateCdmFactory,
                           base::Unretained(this)),
-      GetVideoModeSwitcher(), GetVideoResolutionPolicy(), media_connector());
+      GetVideoModeSwitcher(), GetVideoResolutionPolicy(),
+      browser_main_parts()->media_connector());
   mojo_media_client->SetVideoGeometrySetterService(
       video_geometry_setter_service_.get());
 
diff --git a/chromecast/browser/cast_web_service.cc b/chromecast/browser/cast_web_service.cc
index 1dc3ec3..45e93a4 100644
--- a/chromecast/browser/cast_web_service.cc
+++ b/chromecast/browser/cast_web_service.cc
@@ -42,27 +42,35 @@
 }  // namespace
 
 CastWebService::CastWebService(content::BrowserContext* browser_context,
-                               CastWebViewFactory* web_view_factory,
                                CastWindowManager* window_manager)
     : browser_context_(browser_context),
-      web_view_factory_(web_view_factory),
       window_manager_(window_manager),
+      default_web_view_factory_(browser_context),
+      override_web_view_factory_(nullptr),
       overlay_renderer_cache_(
           std::make_unique<LRURendererCache>(browser_context_, 1)),
       task_runner_(base::SequencedTaskRunnerHandle::Get()),
       weak_factory_(this) {
   DCHECK(browser_context_);
-  DCHECK(web_view_factory_);
   DCHECK(task_runner_);
   weak_ptr_ = weak_factory_.GetWeakPtr();
 }
 
 CastWebService::~CastWebService() = default;
 
+void CastWebService::OverrideWebViewFactory(
+    CastWebViewFactory* web_view_factory) {
+  override_web_view_factory_ = web_view_factory;
+}
+
 CastWebView::Scoped CastWebService::CreateWebViewInternal(
     mojom::CastWebViewParamsPtr params) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  auto web_view = web_view_factory_->CreateWebView(std::move(params), this);
+  CastWebViewFactory* web_view_factory = override_web_view_factory_;
+  if (!web_view_factory) {
+    web_view_factory = &default_web_view_factory_;
+  }
+  auto web_view = web_view_factory->CreateWebView(std::move(params), this);
   CastWebView::Scoped scoped(web_view.release(), [this](CastWebView* web_view) {
     OwnerDestroyed(web_view);
   });
@@ -75,7 +83,11 @@
     mojo::PendingReceiver<mojom::CastWebContents> web_contents,
     mojo::PendingReceiver<mojom::CastContentWindow> window) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  auto web_view = web_view_factory_->CreateWebView(std::move(params), this);
+  CastWebViewFactory* web_view_factory = override_web_view_factory_;
+  if (!web_view_factory) {
+    web_view_factory = &default_web_view_factory_;
+  }
+  auto web_view = web_view_factory->CreateWebView(std::move(params), this);
   web_view->cast_web_contents()->SetDisconnectCallback(base::BindOnce(
       &CastWebService::OwnerDestroyed, base::Unretained(this), web_view.get()));
   web_view->BindReceivers(std::move(web_contents), std::move(window));
diff --git a/chromecast/browser/cast_web_service.h b/chromecast/browser/cast_web_service.h
index c30cca90..6f674fd 100644
--- a/chromecast/browser/cast_web_service.h
+++ b/chromecast/browser/cast_web_service.h
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "chromecast/browser/cast_web_view.h"
+#include "chromecast/browser/cast_web_view_factory.h"
 #include "chromecast/browser/mojom/cast_web_service.mojom.h"
 #include "chromecast/common/identification_settings_manager.h"
 #include "chromecast/common/mojom/identification_settings.mojom.h"
@@ -32,7 +33,6 @@
 
 namespace chromecast {
 
-class CastWebViewFactory;
 class CastWindowManager;
 class LRURendererCache;
 
@@ -45,12 +45,15 @@
                        public mojom::BrowserIdentificationSettingsManager {
  public:
   CastWebService(content::BrowserContext* browser_context,
-                 CastWebViewFactory* web_view_factory,
                  CastWindowManager* window_manager);
   CastWebService(const CastWebService&) = delete;
   CastWebService& operator=(const CastWebService&) = delete;
   ~CastWebService() override;
 
+  // Allow a client to use its own CastWebViewFactory implementation instead of
+  // |default_web_view_factory_| below.
+  void OverrideWebViewFactory(CastWebViewFactory* web_view_factory);
+
   // These are temporary methods to allow in-process embedders to directly own
   // the CastWebView. This will be removed once the lifetime of CastWebview is
   // scoped by the CastWebContents mojo::Remote.
@@ -110,8 +113,11 @@
       const std::string& session_id);
 
   content::BrowserContext* const browser_context_;
-  CastWebViewFactory* const web_view_factory_;
+  // This is used on Aura platforms.
   CastWindowManager* const window_manager_;
+  CastWebViewFactory default_web_view_factory_;
+
+  CastWebViewFactory* override_web_view_factory_ = nullptr;
 
   // These CastWebViews are owned by CastWebService. This happens in two
   // scenarios:
diff --git a/chromecast/browser/service/cast_service_simple.cc b/chromecast/browser/service/cast_service_simple.cc
index 004cda0c7..d10d5e0 100644
--- a/chromecast/browser/service/cast_service_simple.cc
+++ b/chromecast/browser/service/cast_service_simple.cc
@@ -9,10 +9,8 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/time/time.h"
-#include "chromecast/browser/cast_browser_process.h"
 #include "chromecast/browser/cast_content_window.h"
 #include "chromecast/browser/cast_web_service.h"
-#include "chromecast/browser/cast_web_view_factory.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "net/base/filename_util.h"
@@ -39,14 +37,9 @@
 
 }  // namespace
 
-CastServiceSimple::CastServiceSimple(content::BrowserContext* browser_context,
-                                     CastWindowManager* window_manager)
-    : web_view_factory_(std::make_unique<CastWebViewFactory>(browser_context)),
-      web_service_(std::make_unique<CastWebService>(browser_context,
-                                                    web_view_factory_.get(),
-                                                    window_manager)) {
-  shell::CastBrowserProcess::GetInstance()->SetWebViewFactory(
-      web_view_factory_.get());
+CastServiceSimple::CastServiceSimple(CastWebService* web_service)
+    : web_service_(web_service) {
+  DCHECK(web_service_);
 }
 
 CastServiceSimple::~CastServiceSimple() {
diff --git a/chromecast/browser/service/cast_service_simple.h b/chromecast/browser/service/cast_service_simple.h
index fd575eb..eac59d4 100644
--- a/chromecast/browser/service/cast_service_simple.h
+++ b/chromecast/browser/service/cast_service_simple.h
@@ -5,30 +5,21 @@
 #ifndef CHROMECAST_BROWSER_SERVICE_CAST_SERVICE_SIMPLE_H_
 #define CHROMECAST_BROWSER_SERVICE_CAST_SERVICE_SIMPLE_H_
 
-#include <memory>
-
 #include "base/memory/weak_ptr.h"
 #include "chromecast/browser/cast_content_window.h"
 #include "chromecast/browser/cast_web_view.h"
 #include "chromecast/service/cast_service.h"
 #include "url/gurl.h"
 
-namespace content {
-class BrowserContext;
-}  // namespace content
-
 namespace chromecast {
 
 class CastWebService;
-class CastWebViewFactory;
-class CastWindowManager;
 
 namespace shell {
 
 class CastServiceSimple : public CastService {
  public:
-  CastServiceSimple(content::BrowserContext* browser_context,
-                    CastWindowManager* window_manager);
+  explicit CastServiceSimple(CastWebService* web_service);
 
   CastServiceSimple(const CastServiceSimple&) = delete;
   CastServiceSimple& operator=(const CastServiceSimple&) = delete;
@@ -43,8 +34,7 @@
   void StopInternal() override;
 
  private:
-  const std::unique_ptr<CastWebViewFactory> web_view_factory_;
-  const std::unique_ptr<CastWebService> web_service_;
+  CastWebService* const web_service_;
   CastWebView::Scoped cast_web_view_;
   GURL startup_url_;
 
diff --git a/chromecast/browser/test/cast_browser_test.cc b/chromecast/browser/test/cast_browser_test.cc
index e3c907c..4f27ad0 100644
--- a/chromecast/browser/test/cast_browser_test.cc
+++ b/chromecast/browser/test/cast_browser_test.cc
@@ -13,7 +13,6 @@
 #include "chromecast/browser/cast_browser_process.h"
 #include "chromecast/browser/cast_content_window.h"
 #include "chromecast/browser/cast_web_service.h"
-#include "chromecast/browser/cast_web_view_factory.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
@@ -45,11 +44,9 @@
   base::RunLoop().RunUntilIdle();
 
   metrics::CastMetricsHelper::GetInstance()->SetDummySessionIdForTesting();
-  web_view_factory_ = std::make_unique<CastWebViewFactory>(
-      CastBrowserProcess::GetInstance()->browser_context());
   web_service_ = std::make_unique<CastWebService>(
       CastBrowserProcess::GetInstance()->browser_context(),
-      web_view_factory_.get(), nullptr /* window_manager */);
+      nullptr /* window_manager */);
 }
 
 void CastBrowserTest::PostRunTestOnMainThread() {
diff --git a/chromecast/browser/test/cast_browser_test.h b/chromecast/browser/test/cast_browser_test.h
index 9de981c9..f0f84673 100644
--- a/chromecast/browser/test/cast_browser_test.h
+++ b/chromecast/browser/test/cast_browser_test.h
@@ -18,7 +18,6 @@
 namespace chromecast {
 
 class CastWebService;
-class CastWebViewFactory;
 
 namespace shell {
 
@@ -48,7 +47,6 @@
   content::WebContents* NavigateToURL(const GURL& url);
 
  private:
-  std::unique_ptr<CastWebViewFactory> web_view_factory_;
   std::unique_ptr<CastWebService> web_service_;
   CastWebView::Scoped cast_web_view_;
 
diff --git a/chromecast/cast_core/cast_runtime_content_browser_client.cc b/chromecast/cast_core/cast_runtime_content_browser_client.cc
index d8423caa..8e6f6b0 100644
--- a/chromecast/cast_core/cast_runtime_content_browser_client.cc
+++ b/chromecast/cast_core/cast_runtime_content_browser_client.cc
@@ -26,7 +26,8 @@
     CastSystemMemoryPressureEvaluatorAdjuster* memory_pressure_adjuster,
     PrefService* pref_service,
     media::VideoPlaneController* video_plane_controller,
-    CastWindowManager* window_manager) {
+    CastWindowManager* window_manager,
+    CastWebService* web_service) {
   auto network_context_getter = base::BindRepeating(
       [](CastRuntimeContentBrowserClient* client)
           -> network::mojom::NetworkContext* {
@@ -34,9 +35,8 @@
       },
       this);
   return CastRuntimeService::Create(
-      GetMediaTaskRunner(), browser_context, window_manager,
-      media_pipeline_backend_manager(), std::move(network_context_getter),
-      pref_service, video_plane_controller);
+      GetMediaTaskRunner(), web_service, media_pipeline_backend_manager(),
+      std::move(network_context_getter), pref_service, video_plane_controller);
 }
 
 void CastRuntimeContentBrowserClient::OverrideWebkitPrefs(
diff --git a/chromecast/cast_core/cast_runtime_content_browser_client.h b/chromecast/cast_core/cast_runtime_content_browser_client.h
index 1b3678e..56fa7af 100644
--- a/chromecast/cast_core/cast_runtime_content_browser_client.h
+++ b/chromecast/cast_core/cast_runtime_content_browser_client.h
@@ -26,7 +26,8 @@
       CastSystemMemoryPressureEvaluatorAdjuster* memory_pressure_adjuster,
       PrefService* pref_service,
       media::VideoPlaneController* video_plane_controller,
-      CastWindowManager* window_manager) final;
+      CastWindowManager* window_manager,
+      CastWebService* web_service) final;
   void OverrideWebkitPrefs(content::WebContents* web_contents,
                            blink::web_pref::WebPreferences* prefs) override;
   std::unique_ptr<::media::CdmFactory> CreateCdmFactory(
diff --git a/chromecast/cast_core/cast_runtime_service.h b/chromecast/cast_core/cast_runtime_service.h
index f61c7af..2269f58 100644
--- a/chromecast/cast_core/cast_runtime_service.h
+++ b/chromecast/cast_core/cast_runtime_service.h
@@ -17,10 +17,6 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace content {
-class BrowserContext;
-}  // namespace content
-
 namespace network {
 namespace mojom {
 class NetworkContext;
@@ -29,9 +25,8 @@
 
 namespace chromecast {
 
-class CastWindowManager;
-class WebCryptoServer;
 class CastWebService;
+class WebCryptoServer;
 
 namespace media {
 class MediaPipelineBackendManager;
@@ -54,8 +49,7 @@
 
   static std::unique_ptr<CastRuntimeService> Create(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      content::BrowserContext* browser_context,
-      CastWindowManager* window_manager,
+      CastWebService* web_service,
       media::MediaPipelineBackendManager* media_pipeline_backend_manager,
       NetworkContextGetter network_context_getter,
       PrefService* pref_service,
diff --git a/chromecast/cast_core/cast_runtime_service_impl.cc b/chromecast/cast_core/cast_runtime_service_impl.cc
index 80577ae..9cb3aff1e 100644
--- a/chromecast/cast_core/cast_runtime_service_impl.cc
+++ b/chromecast/cast_core/cast_runtime_service_impl.cc
@@ -26,13 +26,10 @@
 }
 
 CastRuntimeServiceImpl::CastRuntimeServiceImpl(
-    content::BrowserContext* browser_context,
-    CastWindowManager* window_manager,
+    CastWebService* web_service,
     NetworkContextGetter network_context_getter)
-    : app_dispatcher_(browser_context,
-                      window_manager,
-                      this,
-                      std::move(network_context_getter)) {}
+    : web_service_(web_service),
+      app_dispatcher_(web_service, this, std::move(network_context_getter)) {}
 
 CastRuntimeServiceImpl::~CastRuntimeServiceImpl() = default;
 
@@ -64,7 +61,7 @@
 }
 
 CastWebService* CastRuntimeServiceImpl::GetCastWebService() {
-  return app_dispatcher_.GetCastWebService();
+  return web_service_;
 }
 
 }  // namespace chromecast
diff --git a/chromecast/cast_core/cast_runtime_service_impl.h b/chromecast/cast_core/cast_runtime_service_impl.h
index 1cdb7610..90084f95 100644
--- a/chromecast/cast_core/cast_runtime_service_impl.h
+++ b/chromecast/cast_core/cast_runtime_service_impl.h
@@ -11,13 +11,9 @@
 #include "chromecast/cast_core/cast_runtime_service.h"
 #include "chromecast/cast_core/runtime_application_dispatcher.h"
 
-namespace content {
-class BrowserContext;
-}  // namespace content
-
 namespace chromecast {
 
-class CastWindowManager;
+class CastWebService;
 
 class CastEventBuilder;
 
@@ -28,8 +24,7 @@
     : public CastRuntimeService,
       public CastRuntimeMetricsRecorder::EventBuilderFactory {
  public:
-  CastRuntimeServiceImpl(content::BrowserContext* browser_context,
-                         CastWindowManager* window_manager,
+  CastRuntimeServiceImpl(CastWebService* web_service,
                          NetworkContextGetter network_context_getter);
   ~CastRuntimeServiceImpl() override;
 
@@ -44,6 +39,7 @@
   std::unique_ptr<CastEventBuilder> CreateEventBuilder() override;
 
  private:
+  CastWebService* const web_service_;
   RuntimeApplicationDispatcher app_dispatcher_;
 };
 
diff --git a/chromecast/cast_core/cast_runtime_service_impl_factory.cc b/chromecast/cast_core/cast_runtime_service_impl_factory.cc
index e8e57f2..efb682a 100644
--- a/chromecast/cast_core/cast_runtime_service_impl_factory.cc
+++ b/chromecast/cast_core/cast_runtime_service_impl_factory.cc
@@ -10,14 +10,13 @@
 
 std::unique_ptr<CastRuntimeService> CastRuntimeService::Create(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    content::BrowserContext* browser_context,
-    CastWindowManager* window_manager,
+    CastWebService* web_service,
     media::MediaPipelineBackendManager* media_pipeline_backend_manager,
     CastRuntimeService::NetworkContextGetter network_context_getter,
     PrefService* pref_service,
     media::VideoPlaneController* video_plane_controller) {
   return std::make_unique<CastRuntimeServiceImpl>(
-      browser_context, window_manager, std::move(network_context_getter));
+      web_service, std::move(network_context_getter));
 }
 
 }  // namespace chromecast
diff --git a/chromecast/cast_core/cast_runtime_service_simple.cc b/chromecast/cast_core/cast_runtime_service_simple.cc
index 9a153be..d64de3f 100644
--- a/chromecast/cast_core/cast_runtime_service_simple.cc
+++ b/chromecast/cast_core/cast_runtime_service_simple.cc
@@ -12,8 +12,7 @@
 // static
 std::unique_ptr<CastRuntimeService> CastRuntimeService::Create(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    content::BrowserContext* browser_context,
-    CastWindowManager* window_manager,
+    CastWebService* web_service,
     media::MediaPipelineBackendManager* media_pipeline_backend_manager,
     CastRuntimeService::NetworkContextGetter network_context_getter,
     PrefService* pref_service,
diff --git a/chromecast/cast_core/runtime_application_dispatcher.cc b/chromecast/cast_core/runtime_application_dispatcher.cc
index 00972b4..6703ab8a 100644
--- a/chromecast/cast_core/runtime_application_dispatcher.cc
+++ b/chromecast/cast_core/runtime_application_dispatcher.cc
@@ -7,10 +7,8 @@
 #include "base/notreached.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chromecast/browser/cast_browser_process.h"
 #include "chromecast/browser/cast_content_window.h"
 #include "chromecast/browser/cast_web_service.h"
-#include "chromecast/browser/cast_web_view_factory.h"
 #include "chromecast/cast_core/streaming_runtime_application.h"
 #include "chromecast/cast_core/web_runtime_application.h"
 #include "third_party/cast_core/public/src/proto/common/application_config.pb.h"
@@ -50,20 +48,13 @@
 }
 
 RuntimeApplicationDispatcher::RuntimeApplicationDispatcher(
-    content::BrowserContext* browser_context,
-    CastWindowManager* window_manager,
+    CastWebService* web_service,
     CastRuntimeMetricsRecorder::EventBuilderFactory* event_builder_factory,
     cast_streaming::NetworkContextGetter network_context_getter)
     : GrpcServer(base::SequencedTaskRunnerHandle::Get()),
-      web_view_factory_(std::make_unique<CastWebViewFactory>(browser_context)),
-      web_service_(std::make_unique<CastWebService>(browser_context,
-                                                    web_view_factory_.get(),
-                                                    window_manager)),
+      web_service_(web_service),
       network_context_getter_(std::move(network_context_getter)),
-      metrics_recorder_(event_builder_factory) {
-  shell::CastBrowserProcess::GetInstance()->SetWebViewFactory(
-      web_view_factory_.get());
-}
+      metrics_recorder_(event_builder_factory) {}
 
 RuntimeApplicationDispatcher::~RuntimeApplicationDispatcher() {
   Stop();
@@ -127,10 +118,9 @@
   if (openscreen::cast::IsCastStreamingReceiverAppId(app_id)) {
     // Deliberately copy |network_context_getter_|.
     app_ = std::make_unique<StreamingRuntimeApplication>(
-        web_service_.get(), task_runner_, network_context_getter_);
+        web_service_, task_runner_, network_context_getter_);
   } else {
-    app_ = std::make_unique<WebRuntimeApplication>(web_service_.get(),
-                                                   task_runner_);
+    app_ = std::make_unique<WebRuntimeApplication>(web_service_, task_runner_);
   }
   if (!app_->Load(request)) {
     app_.reset();
diff --git a/chromecast/cast_core/runtime_application_dispatcher.h b/chromecast/cast_core/runtime_application_dispatcher.h
index c81ec7b..ce14311d 100644
--- a/chromecast/cast_core/runtime_application_dispatcher.h
+++ b/chromecast/cast_core/runtime_application_dispatcher.h
@@ -19,15 +19,9 @@
 #include "third_party/cast_core/public/src/proto/metrics/metrics_recorder.grpc.pb.h"
 #include "third_party/grpc/src/include/grpcpp/server.h"
 
-namespace content {
-class BrowserContext;
-}  // namespace content
-
 namespace chromecast {
 
 class CastWebService;
-class CastWebViewFactory;
-class CastWindowManager;
 class RuntimeApplication;
 
 class RuntimeApplicationDispatcher final : public GrpcServer,
@@ -35,8 +29,7 @@
                                            public MetricsRecorderGrpc {
  public:
   RuntimeApplicationDispatcher(
-      content::BrowserContext* browser_context,
-      CastWindowManager* window_manager,
+      CastWebService* web_service,
       CastRuntimeMetricsRecorder::EventBuilderFactory* event_builder_factory,
       cast_streaming::NetworkContextGetter network_context_getter);
   ~RuntimeApplicationDispatcher() override;
@@ -68,7 +61,6 @@
       GrpcMethod* callback) override;
 
   const std::string& GetCastMediaServiceGrpcEndpoint() const;
-  CastWebService* GetCastWebService() const { return web_service_.get(); }
 
  private:
   // This class handles asynchronously calling MetricsRecorderService->Record
@@ -102,8 +94,7 @@
   // MetricsRecorderGrpc implementation:
   void Record(const cast::metrics::RecordRequest& request) override;
 
-  const std::unique_ptr<CastWebViewFactory> web_view_factory_;
-  const std::unique_ptr<CastWebService> web_service_;
+  CastWebService* const web_service_;
 
   cast_streaming::NetworkContextGetter network_context_getter_;
 
diff --git a/chromecast/common/cast_content_client.cc b/chromecast/common/cast_content_client.cc
index 45abda9..b119e04 100644
--- a/chromecast/common/cast_content_client.cc
+++ b/chromecast/common/cast_content_client.cc
@@ -70,7 +70,7 @@
   return std::make_unique<content::CdmInfo>(
       kWidevineKeySystem, content::CdmInfo::Robustness::kSoftwareSecure,
       std::move(capability), /*supports_sub_key_systems=*/false,
-      kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_library_path,
+      kWidevineCdmDisplayName, kWidevineCdmType, version, cdm_library_path,
       kWidevineCdmFileSystemId);
 }
 
diff --git a/chromecast/common/mojom/constants.mojom b/chromecast/common/mojom/constants.mojom
index 57eb395..fcdc0f6c 100644
--- a/chromecast/common/mojom/constants.mojom
+++ b/chromecast/common/mojom/constants.mojom
@@ -6,4 +6,7 @@
 
 const string kChromecastServiceName = "chromecast";
 
-const string kContentBrowserServiceName = "content_browser";
\ No newline at end of file
+const string kContentBrowserServiceName = "content_browser";
+
+// External service name for the standalone Cast Browser.
+const string kCastBrowserServiceName = "cast_browser";
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 0847e9a..b3549ac 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -2014,6 +2014,9 @@
       <message name="IDS_BLUETOOTH_DEVICE_LIST_PREVIOUSLY_CONNECTED" desc="Title for list displaying paired Bluetooth devices that have previously been connected.">
         Previously connected
       </message>
+      <message name="IDS_BLUETOOTH_DEVICE_LIST_NO_CONNECTED_DEVICES" desc="Text displayed indicating there are currently no paired Bluetooth devices.">
+        No device connected
+      </message>
 
       <!-- Shimless RMA -->
       <!-- Component names. Used by select components and calibration pages-->
@@ -2419,6 +2422,38 @@
       <message name="IDS_SHIMLESS_RMA_CONFIRM_DEVICE_INFO_SKU_WARNING" translateable="false" desc="The text warning explaining when the device's SKU should be changed.">
         The SKU should only be changed if the new component(s) are different from the ones they replaced. For example, a touchscreen replacing a non-touchscreen, or memory being upgraded from 8GB to 16GB.
       </message>
+      <!-- Firmware reimaging page -->
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_TITLE_REIMAGE_REQUIRED" translateable="false" desc="The title for the page when reimaging is required.">
+        Select an option for firmware reimaging
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_TITLE_REIMAGE_NOT_REQUIRED" translateable="false" desc="The title for the page when reimaging is not required.">
+        This device doesn't require firmware reimaging.
+        Would you like to reimage the firmware anyway?
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_INTERNET_ACCESS" translateable="false" desc="The label that says that internet access is required.">
+        Requires internet access
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_THUMBDRIVE_1" translateable="false" desc="Part 1 of the label that says that a thumbdrive is required.">
+        Requires a Thumbdrive configured for
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_THUMBDRIVE_2" translateable="false" desc="Part 2 of the label that says that a thumbdrive is required.">
+        Chromebook Recovery
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_SKIP" translateable="false" desc="The label that offers to skip reimaging.">
+        No, skip it for now.
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_DOWNLOAD_REIMAGE_REQUIRED" translateable="false" desc="The label that offers to download if reimaging is required.">
+        Download the firmware image
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_DOWNLOAD_REIMAGE_NOT_REQUIRED" translateable="false" desc="The label that offers to download if reimaging is not required.">
+        Yes, download the firmware image
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_RECOVERY_REIMAGE_REQUIRED" translateable="false" desc="The label that offers to use the recovery utility if reimaging is required.">
+        Use the Chromebook Recovery Utility
+      </message>
+      <message name="IDS_SHIMLESS_RMA_REIMAGING_FIRMWARE_RECOVERY_REIMAGE_NOT_REQUIRED" translateable="false" desc="The label that offers to use the recovery utility if reimaging is not required.">
+        Yes, use the Chromebook Recovery Utility
+      </message>
 
       <!-- Firmware Update -->
       <message name="IDS_FIRMWARE_TITLE_TEXT" desc="The title of the Firmware update app.">
diff --git a/chromeos/chromeos_strings_grd/IDS_BLUETOOTH_DEVICE_LIST_NO_CONNECTED_DEVICES.png.sha1 b/chromeos/chromeos_strings_grd/IDS_BLUETOOTH_DEVICE_LIST_NO_CONNECTED_DEVICES.png.sha1
new file mode 100644
index 0000000..d88862e9
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_BLUETOOTH_DEVICE_LIST_NO_CONNECTED_DEVICES.png.sha1
@@ -0,0 +1 @@
+26e29be3c462612ed0238be9712db27c7fc1d2ea
\ No newline at end of file
diff --git a/chromeos/components/quick_answers/BUILD.gn b/chromeos/components/quick_answers/BUILD.gn
index 57a9176..56af87a 100644
--- a/chromeos/components/quick_answers/BUILD.gn
+++ b/chromeos/components/quick_answers/BUILD.gn
@@ -40,10 +40,10 @@
     "utils/unit_converter.h",
   ]
   deps = [
-    "//ash/constants",
     "//base",
     "//chromeos/components/quick_answers/public/cpp:cpp",
     "//chromeos/components/quick_answers/public/cpp:prefs",
+    "//chromeos/constants",
     "//chromeos/services/assistant/public/shared",
     "//chromeos/services/machine_learning/public/cpp",
     "//chromeos/services/machine_learning/public/mojom",
@@ -81,12 +81,10 @@
 
   deps = [
     ":quick_answers",
-    "//ash/public/cpp",
     "//base",
     "//base/test:test_support",
     "//chromeos/components/quick_answers/public/cpp:cpp",
     "//chromeos/components/quick_answers/public/cpp:prefs",
-    "//chromeos/services/assistant:test_support",
     "//chromeos/services/assistant/public/shared",
     "//chromeos/services/machine_learning/public/cpp:stub",
     "//chromeos/services/machine_learning/public/mojom",
diff --git a/chromeos/components/quick_answers/quick_answers_client.cc b/chromeos/components/quick_answers/quick_answers_client.cc
index 62ca7af7..73ccdd9 100644
--- a/chromeos/components/quick_answers/quick_answers_client.cc
+++ b/chromeos/components/quick_answers/quick_answers_client.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "ash/constants/ash_features.h"
 #include "base/containers/contains.h"
 #include "chromeos/components/quick_answers/public/cpp/quick_answers_state.h"
 #include "chromeos/components/quick_answers/quick_answers_model.h"
diff --git a/chromeos/components/quick_answers/test/quick_answers_test_base.cc b/chromeos/components/quick_answers/test/quick_answers_test_base.cc
index 7bca234..d768cfa 100644
--- a/chromeos/components/quick_answers/test/quick_answers_test_base.cc
+++ b/chromeos/components/quick_answers/test/quick_answers_test_base.cc
@@ -4,8 +4,6 @@
 
 #include "chromeos/components/quick_answers/test/quick_answers_test_base.h"
 
-#include "ash/public/cpp/assistant/assistant_state.h"
-
 namespace ash {
 
 QuickAnswersTestBase::QuickAnswersTestBase() = default;
@@ -15,19 +13,12 @@
 void QuickAnswersTestBase::SetUp() {
   testing::Test::SetUp();
 
-  if (!AssistantState::Get()) {
-    assistant_state_ =
-        std::make_unique<chromeos::assistant::FullyInitializedAssistantState>();
-  }
-
   if (!QuickAnswersState::Get())
     quick_answers_state_ = std::make_unique<QuickAnswersState>();
 }
 
 void QuickAnswersTestBase::TearDown() {
   quick_answers_state_.reset();
-  assistant_state_.reset();
-
   testing::Test::TearDown();
 }
 
diff --git a/chromeos/components/quick_answers/test/quick_answers_test_base.h b/chromeos/components/quick_answers/test/quick_answers_test_base.h
index 2e49cf4..eb2a3984 100644
--- a/chromeos/components/quick_answers/test/quick_answers_test_base.h
+++ b/chromeos/components/quick_answers/test/quick_answers_test_base.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "chromeos/components/quick_answers/public/cpp/quick_answers_state.h"
-#include "chromeos/services/assistant/test_support/fully_initialized_assistant_state.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -28,8 +27,6 @@
   void TearDown() override;
 
  private:
-  std::unique_ptr<chromeos::assistant::FullyInitializedAssistantState>
-      assistant_state_;
   std::unique_ptr<QuickAnswersState> quick_answers_state_;
 };
 
diff --git a/chromeos/components/quick_answers/understanding/intent_generator.cc b/chromeos/components/quick_answers/understanding/intent_generator.cc
index 08403af..5451fca 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator.cc
+++ b/chromeos/components/quick_answers/understanding/intent_generator.cc
@@ -6,7 +6,6 @@
 
 #include <map>
 
-#include "ash/constants/ash_features.h"
 #include "base/i18n/case_conversion.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_split.h"
@@ -14,6 +13,7 @@
 #include "chromeos/components/quick_answers/public/cpp/quick_answers_state.h"
 #include "chromeos/components/quick_answers/quick_answers_model.h"
 #include "chromeos/components/quick_answers/utils/quick_answers_utils.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -223,7 +223,7 @@
   DCHECK(complete_callback_);
 
   if (!ash::QuickAnswersState::Get()->translation_enabled() ||
-      features::IsQuickAnswersV2TranslationDisabled()) {
+      chromeos::features::IsQuickAnswersV2TranslationDisabled()) {
     std::move(complete_callback_)
         .Run(IntentInfo(request.selected_text, IntentType::kUnknown));
     return;
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index accbb03..aa7f2bb 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -23,9 +23,25 @@
 const base::Feature kBluetoothPhoneFilter{"BluetoothPhoneFilter",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Disables translation services of the Quick Answers V2.
+const base::Feature kDisableQuickAnswersV2Translation{
+    "DisableQuickAnswersV2Translation", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls whether to enable quick answers V2 settings sub-toggles.
+const base::Feature kQuickAnswersV2SettingsSubToggle{
+    "QuickAnswersV2SettingsSubToggle", base::FEATURE_DISABLED_BY_DEFAULT};
+
 bool IsBluetoothAdvertisementMonitoringEnabled() {
   return base::FeatureList::IsEnabled(kBluetoothAdvertisementMonitoring);
 }
 
+bool IsQuickAnswersV2TranslationDisabled() {
+  return base::FeatureList::IsEnabled(kDisableQuickAnswersV2Translation);
+}
+
+bool IsQuickAnswersV2SettingsSubToggleEnabled() {
+  return base::FeatureList::IsEnabled(kQuickAnswersV2SettingsSubToggle);
+}
+
 }  // namespace features
 }  // namespace chromeos
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 82b9106..6bd8e89 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -18,14 +18,26 @@
 
 namespace features {
 
-COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
-extern const base::Feature kBluetoothAdvertisementMonitoring;
+// All features in alphabetical order. The features should be documented
+// alongside the definition of their values in the .cc file. If a feature is
+// being rolled out via Finch, add a comment in the .cc file.
 
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kBluetoothAdvertisementMonitoring;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kBluetoothPhoneFilter;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kDisableQuickAnswersV2Translation;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kQuickAnswersV2SettingsSubToggle;
+
+// Keep alphabetized.
 
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 bool IsBluetoothAdvertisementMonitoringEnabled();
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsQuickAnswersV2TranslationDisabled();
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+bool IsQuickAnswersV2SettingsSubToggleEnabled();
 
 }  // namespace features
 }  // namespace chromeos
diff --git a/chromeos/crosapi/cpp/gurl_os_handler_unittest.cc b/chromeos/crosapi/cpp/gurl_os_handler_unittest.cc
index 65f0c6c..3f637bd 100644
--- a/chromeos/crosapi/cpp/gurl_os_handler_unittest.cc
+++ b/chromeos/crosapi/cpp/gurl_os_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
+#include "url/url_util.h"
 
 namespace crosapi {
 
@@ -111,6 +112,26 @@
   EXPECT_EQ(AshOsUrlHost(GURL("://")), "");
 }
 
+TEST(GurlOsHandlerUtilsTest, GetSystemUrlFromChromeUrl) {
+  url::ScopedSchemeRegistryForTests scoped_registry;
+  url::AddStandardScheme("chrome", url::SCHEME_WITH_HOST);
+  EXPECT_EQ(GetSystemUrlFromChromeUrl(GURL("chrome://flags/")),
+            GURL("os://flags"));
+  EXPECT_EQ(GetSystemUrlFromChromeUrl(GURL("chrome://flags/abc")),
+            GURL("os://flags"));
+  EXPECT_EQ(GetSystemUrlFromChromeUrl(GURL("chrome://flags?foo")),
+            GURL("os://flags"));
+  EXPECT_EQ(GetSystemUrlFromChromeUrl(GURL("chrome://foo")), GURL("os://foo"));
+}
+
+TEST(GurlOsHandlerUtilsTest, GetChromeUrlFromSystemUrl) {
+  EXPECT_EQ(GetChromeUrlFromSystemUrl(GURL("os://flags/abc")),
+            GURL("chrome://flags"));
+  EXPECT_EQ(GetChromeUrlFromSystemUrl(GURL("os://flags?foo")),
+            GURL("chrome://flags"));
+  EXPECT_EQ(GetChromeUrlFromSystemUrl(GURL("os://foo")), GURL("chrome://foo"));
+}
+
 }  // namespace gurl_os_handler_utils
 
 }  // namespace crosapi
diff --git a/chromeos/crosapi/cpp/gurl_os_handler_utils.cc b/chromeos/crosapi/cpp/gurl_os_handler_utils.cc
index 85edf4f..ad350e7 100644
--- a/chromeos/crosapi/cpp/gurl_os_handler_utils.cc
+++ b/chromeos/crosapi/cpp/gurl_os_handler_utils.cc
@@ -13,6 +13,8 @@
 
 const char kOsScheme[] = "os";
 const char kOsUrlPrefix[] = "os://";
+const char kChromeUIScheme[] = "chrome";
+const char kChromeUrlPrefix[] = "chrome://";
 
 // The start of the host portion of a GURL which starts with the os scheme.
 const size_t kHostStart = sizeof(kOsUrlPrefix) - 1;
@@ -106,6 +108,18 @@
   return base::ToLowerASCII(url_part.substr(0, cut_off));
 }
 
+// Convert a passed GURL from os:// to chrome://.
+GURL GetSystemUrlFromChromeUrl(const GURL& url) {
+  DCHECK(url.SchemeIs(kChromeUIScheme));
+  return GURL(kOsUrlPrefix + url.host());
+}
+
+// Convert a passed GURL from chrome:// to os://.
+GURL GetChromeUrlFromSystemUrl(const GURL& url) {
+  DCHECK(IsAshOsUrl(url));
+  return GURL(kChromeUrlPrefix + AshOsUrlHost(url));
+}
+
 }  // namespace gurl_os_handler_utils
 
 }  // namespace crosapi
diff --git a/chromeos/crosapi/cpp/gurl_os_handler_utils.h b/chromeos/crosapi/cpp/gurl_os_handler_utils.h
index e01f21a44..b1cc26e9 100644
--- a/chromeos/crosapi/cpp/gurl_os_handler_utils.h
+++ b/chromeos/crosapi/cpp/gurl_os_handler_utils.h
@@ -51,6 +51,12 @@
 // Get the host from the given os:// URL.
 COMPONENT_EXPORT(CROSAPI) std::string AshOsUrlHost(const GURL& url);
 
+// Convert a passed GURL from os:// scheme to chrome:// scheme.
+COMPONENT_EXPORT(CROSAPI) GURL GetSystemUrlFromChromeUrl(const GURL& url);
+
+// Convert a passed GURL from chrome:// scheme to os:// scheme.
+COMPONENT_EXPORT(CROSAPI) GURL GetChromeUrlFromSystemUrl(const GURL& url);
+
 }  // namespace gurl_os_handler_utils
 
 }  // namespace crosapi
diff --git a/chromeos/crosapi/mojom/test_controller.mojom b/chromeos/crosapi/mojom/test_controller.mojom
index 6485bd7..9548b9a 100644
--- a/chromeos/crosapi/mojom/test_controller.mojom
+++ b/chromeos/crosapi/mojom/test_controller.mojom
@@ -30,8 +30,8 @@
 // This interface is implemented by Ash-Chrome.
 // This interface provides tests a mechanism to mutate or query ash.
 // In the future, this interface may merge with an automation or a11y interface.
-// Next version: 7
-// Next method id: 13
+// Next version: 9
+// Next method id: 16
 [Stable, Uuid="1f93f9d7-e466-466c-a675-c21b48cf30d3"]
 interface TestController {
   // Clicks the middle of the window. Assumes that the window exists and is
@@ -114,4 +114,13 @@
   SendTouchEvent@7(string window_id, TouchEventType type, uint8 pointer_id,
                    gfx.mojom.PointF location_in_window) => ();
 
+  // Get the number of open Ash browser windows.
+  [MinVersion=8]
+  GetOpenAshBrowserWindows@14() => (uint32 number);
+
+  // Close all browser windows.
+  // Note: Usually there should be no Ash window open unless the test opened
+  // one.
+  [MinVersion=8]
+  CloseAllBrowserWindows@15() => (bool success);
 };
diff --git a/chromeos/dbus/fwupd/DEPS b/chromeos/dbus/fwupd/DEPS
index 5aa4ceb6..a1c1c6f 100644
--- a/chromeos/dbus/fwupd/DEPS
+++ b/chromeos/dbus/fwupd/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+ash/constants",
+  "+components/dbus",
 ]
\ No newline at end of file
diff --git a/chromeos/dbus/fwupd/fake_fwupd_client.cc b/chromeos/dbus/fwupd/fake_fwupd_client.cc
index b8aacaa..2d76355 100644
--- a/chromeos/dbus/fwupd/fake_fwupd_client.cc
+++ b/chromeos/dbus/fwupd/fake_fwupd_client.cc
@@ -40,4 +40,16 @@
     observer.OnUpdateListResponse(device_id, &updates);
 }
 
+void FakeFwupdClient::InstallUpdate(const std::string& device_id,
+                                    base::ScopedFD file_descriptor,
+                                    FirmwareInstallOptions options) {
+  // This matches the behavior of the real class. I.e. if you send an unknown
+  // id, nothing happens.
+  if (device_id != kFakeDeviceIdForTesting)
+    return;
+
+  for (auto& observer : observers_)
+    observer.OnInstallResponse(install_success_);
+}
+
 }  // namespace chromeos
\ No newline at end of file
diff --git a/chromeos/dbus/fwupd/fake_fwupd_client.h b/chromeos/dbus/fwupd/fake_fwupd_client.h
index ebb4cc2..a26a718 100644
--- a/chromeos/dbus/fwupd/fake_fwupd_client.h
+++ b/chromeos/dbus/fwupd/fake_fwupd_client.h
@@ -6,6 +6,7 @@
 #define CHROMEOS_DBUS_FWUPD_FAKE_FWUPD_CLIENT_H_
 
 #include "base/component_export.h"
+#include "base/files/scoped_file.h"
 #include "chromeos/dbus/fwupd/fwupd_client.h"
 
 namespace chromeos {
@@ -18,9 +19,16 @@
   FakeFwupdClient& operator=(const FakeFwupdClient&) = delete;
   ~FakeFwupdClient() override;
 
+  // FwupdClient:
   void Init(dbus::Bus* bus) override;
   void RequestUpdates(const std::string& device_id) override;
   void RequestDevices() override;
+  void InstallUpdate(const std::string& device_id,
+                     base::ScopedFD file_descriptor,
+                     FirmwareInstallOptions options) override;
+
+ private:
+  bool install_success_ = false;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/fwupd/fwupd_client.cc b/chromeos/dbus/fwupd/fwupd_client.cc
index 7deefce..1d12bac0 100644
--- a/chromeos/dbus/fwupd/fwupd_client.cc
+++ b/chromeos/dbus/fwupd/fwupd_client.cc
@@ -25,6 +25,7 @@
 const char kFwupdDeviceAddedSignalName[] = "DeviceAdded";
 const char kFwupdGetUpgradesMethodName[] = "GetUpgrades";
 const char kFwupdGetDevicesMethodName[] = "GetDevices";
+const char kFwupdInstallMethodName[] = "Install";
 
 }  // namespace
 
@@ -74,6 +75,34 @@
                        weak_ptr_factory_.GetWeakPtr()));
   }
 
+  void InstallUpdate(const std::string& device_id,
+                     base::ScopedFD file_descriptor,
+                     FirmwareInstallOptions options) override {
+    dbus::MethodCall method_call(kFwupdServiceInterface,
+                                 kFwupdInstallMethodName);
+    dbus::MessageWriter writer(&method_call);
+
+    writer.AppendString(device_id);
+    writer.AppendFileDescriptor(file_descriptor.get());
+
+    // Write the options in form of "a{sv}".
+    dbus::MessageWriter array_writer(nullptr);
+    writer.OpenArray("{sv}", &array_writer);
+    for (const auto& option : options) {
+      dbus::MessageWriter dict_entry_writer(nullptr);
+      array_writer.OpenDictEntry(&dict_entry_writer);
+      dict_entry_writer.AppendString(option.first);
+      dict_entry_writer.AppendVariantOfBool(option.second);
+      array_writer.CloseContainer(&dict_entry_writer);
+    }
+    writer.CloseContainer(&array_writer);
+
+    proxy_->CallMethodWithErrorResponse(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&FwupdClientImpl::InstallUpdateCallback,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
  private:
   // Pops a string-to-variant-string dictionary from the reader.
   std::unique_ptr<base::DictionaryValue> PopStringToStringDictionary(
@@ -209,6 +238,24 @@
       observer.OnDeviceListResponse(&devices);
   }
 
+  void InstallUpdateCallback(dbus::Response* response,
+                             dbus::ErrorResponse* error_response) {
+    if (!response) {
+      LOG(ERROR) << "No Dbus response received from fwupd.";
+      return;
+    }
+
+    bool success;
+    dbus::MessageReader reader(response);
+    if (!reader.PopBool(&success)) {
+      LOG(ERROR) << "Failed to parse bool from DBus Signal";
+      return;
+    }
+
+    for (auto& observer : observers_)
+      observer.OnInstallResponse(success);
+  }
+
   void OnSignalConnected(const std::string& interface_name,
                          const std::string& signal_name,
                          bool is_connected) {
diff --git a/chromeos/dbus/fwupd/fwupd_client.h b/chromeos/dbus/fwupd/fwupd_client.h
index e043128b..3e85642 100644
--- a/chromeos/dbus/fwupd/fwupd_client.h
+++ b/chromeos/dbus/fwupd/fwupd_client.h
@@ -5,16 +5,20 @@
 #ifndef CHROMEOS_DBUS_FWUPD_FWUPD_CLIENT_H_
 #define CHROMEOS_DBUS_FWUPD_FWUPD_CLIENT_H_
 
+#include <map>
 #include <memory>
 #include <string>
 
 #include "base/component_export.h"
+#include "base/files/scoped_file.h"
 #include "base/observer_list.h"
 #include "chromeos/dbus/dbus_client.h"
 #include "chromeos/dbus/fwupd/fwupd_device.h"
 #include "chromeos/dbus/fwupd/fwupd_update.h"
 
 namespace chromeos {
+using FirmwareInstallOptions = std::map<std::string, bool>;
+
 // FwupdClient is used for handling signals from the fwupd daemon.
 class COMPONENT_EXPORT(CHROMEOS_DBUS_FWUPD) FwupdClient : public DBusClient {
  public:
@@ -24,6 +28,7 @@
     virtual void OnDeviceListResponse(FwupdDeviceList* devices) = 0;
     virtual void OnUpdateListResponse(const std::string& device_id,
                                       FwupdUpdateList* updates) = 0;
+    virtual void OnInstallResponse(bool success) = 0;
   };
 
   void AddObserver(Observer* observer);
@@ -50,6 +55,10 @@
   // Query fwupd for devices that are currently connected.
   virtual void RequestDevices() = 0;
 
+  virtual void InstallUpdate(const std::string& device_id,
+                             base::ScopedFD file_descriptor,
+                             FirmwareInstallOptions options) = 0;
+
  protected:
   friend class FwupdClientTest;
 
diff --git a/chromeos/dbus/fwupd/fwupd_client_unittest.cc b/chromeos/dbus/fwupd/fwupd_client_unittest.cc
index 362d898..a7159251 100644
--- a/chromeos/dbus/fwupd/fwupd_client_unittest.cc
+++ b/chromeos/dbus/fwupd/fwupd_client_unittest.cc
@@ -5,6 +5,7 @@
 #include "chromeos/dbus/fwupd/fwupd_client.h"
 
 #include "ash/constants/ash_features.h"
+#include "base/files/scoped_file.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
@@ -51,6 +52,7 @@
               (const std::string& device_id,
                chromeos::FwupdUpdateList* updates),
               (override));
+  MOCK_METHOD(void, OnInstallResponse, (bool success), (override));
 };
 
 }  // namespace
@@ -119,6 +121,10 @@
              (*updates)[0].priority);
   }
 
+  void CheckInstallState(bool success) { CHECK_EQ(install_success_, success); }
+
+  void SetInstallState(bool success) { install_success_ = success; }
+
   void AddDbusMethodCallResultSimulation(
       std::unique_ptr<dbus::Response> response,
       std::unique_ptr<dbus::ErrorResponse> error_response) {
@@ -170,6 +176,8 @@
   using MethodCallResult = std::pair<std::unique_ptr<dbus::Response>,
                                      std::unique_ptr<dbus::ErrorResponse>>;
   std::deque<MethodCallResult> dbus_method_call_simulated_results_;
+
+  bool install_success_ = false;
 };
 
 // TODO (swifton): Rewrite this test with an observer when it's available.
@@ -272,4 +280,34 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(FwupdClientTest, Install) {
+  // The observer will check that the update description is parsed and passed
+  // correctly.
+  MockObserver observer;
+  EXPECT_CALL(observer, OnInstallResponse(_))
+      .Times(1)
+      .WillRepeatedly(Invoke(this, &FwupdClientTest::CheckInstallState));
+  fwupd_client_->AddObserver(&observer);
+
+  EXPECT_CALL(*proxy_, DoCallMethodWithErrorResponse(_, _, _))
+      .WillRepeatedly(Invoke(this, &FwupdClientTest::OnMethodCalled));
+
+  auto response = dbus::Response::CreateEmpty();
+
+  dbus::MessageWriter response_writer(response.get());
+
+  // The response is an boolean for whether the install request was successful
+  // or not.
+  const bool install_success = true;
+  SetInstallState(install_success);
+  response_writer.AppendBool(install_success);
+
+  AddDbusMethodCallResultSimulation(std::move(response), nullptr);
+
+  fwupd_client_->InstallUpdate(kFakeDeviceIdForTesting, base::ScopedFD(0),
+                               std::map<std::string, bool>());
+
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/hps/fake_hps_dbus_client.cc b/chromeos/dbus/hps/fake_hps_dbus_client.cc
index 68dfdb5..f54f0fe 100644
--- a/chromeos/dbus/hps/fake_hps_dbus_client.cc
+++ b/chromeos/dbus/hps/fake_hps_dbus_client.cc
@@ -53,7 +53,7 @@
 void FakeHpsDBusClient::WaitForServiceToBeAvailable(
     dbus::ObjectProxy::WaitForServiceToBeAvailableCallback cb) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(cb), hps_service_is_avaible_));
+      FROM_HERE, base::BindOnce(std::move(cb), hps_service_is_available_));
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/hps/fake_hps_dbus_client.h b/chromeos/dbus/hps/fake_hps_dbus_client.h
index 911b32e..ec1a7b5 100644
--- a/chromeos/dbus/hps/fake_hps_dbus_client.h
+++ b/chromeos/dbus/hps/fake_hps_dbus_client.h
@@ -43,14 +43,14 @@
   int hps_notify_count() const { return hps_notify_count_; }
 
   // Methods for co-ordinating WaitForServiceToBeAvailable calls in tests.
-  void set_hps_service_is_avaible_(bool is_available) {
-    hps_service_is_avaible_ = is_available;
+  void set_hps_service_is_available(bool is_available) {
+    hps_service_is_available_ = is_available;
   }
 
  private:
   absl::optional<bool> hps_notify_result_;
   int hps_notify_count_ = 0;
-  bool hps_service_is_avaible_ = false;
+  bool hps_service_is_available_ = false;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/services/bluetooth_config/device_conversion_util.cc b/chromeos/services/bluetooth_config/device_conversion_util.cc
index 2cd9fe9..491cab70 100644
--- a/chromeos/services/bluetooth_config/device_conversion_util.cc
+++ b/chromeos/services/bluetooth_config/device_conversion_util.cc
@@ -75,16 +75,53 @@
   return mojom::AudioOutputCapability::kNotCapableOfAudioOutput;
 }
 
-mojom::DeviceBatteryInfoPtr ComputeBatteryInfo(
-    const device::BluetoothDevice* device) {
+mojom::BatteryPropertiesPtr ComputeBatteryInfoForBatteryType(
+    const device::BluetoothDevice* device,
+    device::BluetoothDevice::BatteryType battery_type) {
   const absl::optional<device::BluetoothDevice::BatteryInfo> battery_info =
-      device->GetBatteryInfo(device::BluetoothDevice::BatteryType::kDefault);
+      device->GetBatteryInfo(battery_type);
 
   if (!battery_info || !battery_info->percentage.has_value())
     return nullptr;
 
-  return mojom::DeviceBatteryInfo::New(
-      mojom::BatteryProperties::New(battery_info->percentage.value()));
+  return mojom::BatteryProperties::New(battery_info->percentage.value());
+}
+
+mojom::DeviceBatteryInfoPtr ComputeBatteryInfo(
+    const device::BluetoothDevice* device) {
+  mojom::BatteryPropertiesPtr default_battery =
+      ComputeBatteryInfoForBatteryType(
+          device, device::BluetoothDevice::BatteryType::kDefault);
+  mojom::BatteryPropertiesPtr left_bud_battery =
+      ComputeBatteryInfoForBatteryType(
+          device, device::BluetoothDevice::BatteryType::kLeftBudTrueWireless);
+  mojom::BatteryPropertiesPtr right_bud_battery =
+      ComputeBatteryInfoForBatteryType(
+          device, device::BluetoothDevice::BatteryType::kRightBudTrueWireless);
+  mojom::BatteryPropertiesPtr case_battery = ComputeBatteryInfoForBatteryType(
+      device, device::BluetoothDevice::BatteryType::kCaseTrueWireless);
+
+  if (!default_battery && !left_bud_battery && !right_bud_battery &&
+      !case_battery) {
+    return nullptr;
+  }
+
+  mojom::DeviceBatteryInfoPtr device_battery_info =
+      mojom::DeviceBatteryInfo::New();
+
+  if (default_battery)
+    device_battery_info->default_properties = std::move(default_battery);
+
+  if (left_bud_battery)
+    device_battery_info->left_bud_info = std::move(left_bud_battery);
+
+  if (right_bud_battery)
+    device_battery_info->right_bud_info = std::move(right_bud_battery);
+
+  if (case_battery)
+    device_battery_info->case_info = std::move(case_battery);
+
+  return device_battery_info;
 }
 
 mojom::DeviceConnectionState ComputeConnectionState(
diff --git a/chromeos/services/bluetooth_config/device_conversion_util_unittest.cc b/chromeos/services/bluetooth_config/device_conversion_util_unittest.cc
index 29b89ad..25f5cfb 100644
--- a/chromeos/services/bluetooth_config/device_conversion_util_unittest.cc
+++ b/chromeos/services/bluetooth_config/device_conversion_util_unittest.cc
@@ -69,5 +69,70 @@
   EXPECT_TRUE(properties->is_blocked_by_policy);
 }
 
+TEST_F(DeviceConversionUtilTest, TestConversion_DefaultBattery) {
+  device::BluetoothDevice* device = InitDevice(
+      /*bluetooth_class=*/0u, /*name=*/"name", /*address=*/"address",
+      /*paired=*/true, /*connected=*/true, /*is_blocked_by_policy=*/false);
+
+  device::BluetoothDevice::BatteryInfo battery_info(
+      /*battery_type=*/device::BluetoothDevice::BatteryType::kDefault,
+      /*percentage=*/65,
+      /*charge_state=*/
+      device::BluetoothDevice::BatteryInfo::ChargeState::kCharging);
+  device->SetBatteryInfo(battery_info);
+
+  mojom::BluetoothDevicePropertiesPtr properties =
+      GenerateBluetoothDeviceMojoProperties(device);
+  ASSERT_TRUE(properties);
+
+  EXPECT_TRUE(properties->battery_info->default_properties);
+  EXPECT_EQ(properties->battery_info->default_properties->battery_percentage,
+            65);
+  EXPECT_FALSE(properties->battery_info->left_bud_info);
+  EXPECT_FALSE(properties->battery_info->right_bud_info);
+  EXPECT_FALSE(properties->battery_info->case_info);
+}
+
+TEST_F(DeviceConversionUtilTest, TestConversion_MultipleBatteries) {
+  device::BluetoothDevice* device = InitDevice(
+      /*bluetooth_class=*/0u, /*name=*/"name", /*address=*/"address",
+      /*paired=*/true, /*connected=*/true, /*is_blocked_by_policy=*/false);
+
+  device::BluetoothDevice::BatteryInfo left_battery_info(
+      /*battery_type=*/device::BluetoothDevice::BatteryType::
+          kLeftBudTrueWireless,
+      /*percentage=*/65,
+      /*charge_state=*/
+      device::BluetoothDevice::BatteryInfo::ChargeState::kCharging);
+  device->SetBatteryInfo(left_battery_info);
+
+  device::BluetoothDevice::BatteryInfo right_battery_info(
+      /*battery_type=*/device::BluetoothDevice::BatteryType::
+          kRightBudTrueWireless,
+      /*percentage=*/45,
+      /*charge_state=*/
+      device::BluetoothDevice::BatteryInfo::ChargeState::kCharging);
+  device->SetBatteryInfo(right_battery_info);
+
+  device::BluetoothDevice::BatteryInfo case_battery_info(
+      /*battery_type=*/device::BluetoothDevice::BatteryType::kCaseTrueWireless,
+      /*percentage=*/50,
+      /*charge_state=*/
+      device::BluetoothDevice::BatteryInfo::ChargeState::kCharging);
+  device->SetBatteryInfo(case_battery_info);
+
+  mojom::BluetoothDevicePropertiesPtr properties =
+      GenerateBluetoothDeviceMojoProperties(device);
+  ASSERT_TRUE(properties);
+
+  EXPECT_FALSE(properties->battery_info->default_properties);
+  EXPECT_TRUE(properties->battery_info->left_bud_info);
+  EXPECT_EQ(properties->battery_info->left_bud_info->battery_percentage, 65);
+  EXPECT_TRUE(properties->battery_info->right_bud_info);
+  EXPECT_EQ(properties->battery_info->right_bud_info->battery_percentage, 45);
+  EXPECT_TRUE(properties->battery_info->case_info);
+  EXPECT_EQ(properties->battery_info->case_info->battery_percentage, 50);
+}
+
 }  // namespace bluetooth_config
 }  // namespace chromeos
diff --git a/chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom b/chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom
index 3f610039..303bbe61 100644
--- a/chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom
+++ b/chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom
@@ -72,12 +72,15 @@
   uint8 battery_percentage;
 };
 
-// Battery info belonging to a device. Initially contains an optional
-// "default" set of properties, but will eventually contain information
-// about multiple batteries per device (e.g., Pixel Buds include battery
-// info about the left earbud, right earbud, and case).
+// Battery info belonging to a device. Contains an optional "default" set of
+// properties, and may contain information about multiple batteries per device
+// (e.g., Pixel Buds include battery info about the left earbud, right earbud,
+// and case).
 struct DeviceBatteryInfo {
   BatteryProperties? default_properties;
+  BatteryProperties? left_bud_info;
+  BatteryProperties? right_bud_info;
+  BatteryProperties? case_info;
 };
 
 // Properties belonging to a Bluetooth device.
diff --git a/components/BUILD.gn b/components/BUILD.gn
index d8e02d0..48b02bb 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -474,9 +474,9 @@
     deps += [
       # TODO(b/206686476): Move this target to //ash/components:unit_tests
       "//ash/components/arc:unit_tests",
+      "//ash/components/arc/session:unit_tests",
       "//components/arc:unit_tests",
       "//components/arc/mojom:unit_tests",
-      "//components/arc/session:unit_tests",
       "//components/desks_storage:unit_tests",
       "//components/guest_os:unit_tests",
       "//components/metrics/structured:unit_tests",
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index d9116231..f778444 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -36,6 +36,7 @@
   # TODO(b/129295708): Clean up unused deps. Update users of this target.
   deps = [
     "//ash:ash",
+    "//ash/components/arc/enterprise",
     "//ash/components/arc/input_overlay/resources:resources_grit",
     "//ash/components/audio",
     "//ash/constants",
@@ -61,7 +62,6 @@
     "//chromeos/ui/base",
     "//chromeos/ui/frame",
     "//components/account_id",
-    "//components/arc/enterprise",
     "//components/arc/vector_icons",
     "//components/exo",
     "//components/google/core/common",
diff --git a/components/arc/intent_helper/activity_icon_loader.cc b/components/arc/intent_helper/activity_icon_loader.cc
index 29a9e13..50931e2 100644
--- a/components/arc/intent_helper/activity_icon_loader.cc
+++ b/components/arc/intent_helper/activity_icon_loader.cc
@@ -10,14 +10,14 @@
 #include <utility>
 
 #include "ash/components/arc/arc_util.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "components/arc/intent_helper/adaptive_icon_delegate.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "ui/base/layout.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/image/image_skia_operations.h"
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc
index d1b7a85..81ebd6a 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -9,6 +9,8 @@
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "ash/components/arc/audio/arc_audio_bridge.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "ash/public/cpp/new_window_delegate.h"
 #include "ash/public/cpp/wallpaper/wallpaper_controller.h"
 #include "base/json/json_writer.h"
@@ -21,8 +23,6 @@
 #include "components/arc/intent_helper/control_camera_app_delegate.h"
 #include "components/arc/intent_helper/intent_constants.h"
 #include "components/arc/intent_helper/open_url_delegate.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/url_formatter/url_fixer.h"
 #include "net/base/url_util.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
index 69c4a15b..31f25a6ac 100644
--- a/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
+++ b/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/components/arc/session/arc_bridge_service.h"
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -16,7 +17,6 @@
 #include "components/arc/intent_helper/open_url_delegate.h"
 #include "components/arc/mojom/intent_helper.mojom-forward.h"
 #include "components/arc/mojom/intent_helper.mojom.h"
-#include "components/arc/session/arc_bridge_service.h"
 #include "mojo/public/cpp/bindings/clone_traits.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/arc/intent_helper/link_handler_model.cc b/components/arc/intent_helper/link_handler_model.cc
index f2c39d7..971badd 100644
--- a/components/arc/intent_helper/link_handler_model.cc
+++ b/components/arc/intent_helper/link_handler_model.cc
@@ -8,13 +8,13 @@
 
 #include "ash/components/arc/metrics/arc_metrics_constants.h"
 #include "ash/components/arc/metrics/arc_metrics_service.h"
+#include "ash/components/arc/session/arc_bridge_service.h"
+#include "ash/components/arc/session/arc_service_manager.h"
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/arc/session/arc_service_manager.h"
 #include "components/google/core/common/google_util.h"
 #include "url/url_util.h"
 
diff --git a/components/arc/mojom/BUILD.gn b/components/arc/mojom/BUILD.gn
index 969ea61..cccef19 100644
--- a/components/arc/mojom/BUILD.gn
+++ b/components/arc/mojom/BUILD.gn
@@ -353,7 +353,7 @@
         traits_headers = [ "video_accelerator_mojom_traits.h" ]
         traits_sources = [ "video_accelerator_mojom_traits.cc" ]
         traits_public_deps = [
-          "//components/arc/video_accelerator:common",
+          "//ash/components/arc/video_accelerator:common",
           "//media",
           "//ui/gfx/geometry",
         ]
diff --git a/components/arc/mojom/anr.mojom b/components/arc/mojom/anr.mojom
index b9364df..348f1da 100644
--- a/components/arc/mojom/anr.mojom
+++ b/components/arc/mojom/anr.mojom
@@ -10,8 +10,8 @@
   UNKNOWN = 0,
   // ANR while handling input events.
   INPUT = 1,
-  // ANR in services.
-  SERVICE = 2,
+  // ANR in foreground services.
+  FOREGROUND_SERVICE = 2,
   // ANR in broadcasts.
   BROADCAST = 3,
   // ANR in content provider.
@@ -19,7 +19,9 @@
   // App custom ANR.
   APP_REQUESTED = 5,
   // ANR in processes.
-  PROCESS = 6
+  PROCESS = 6,
+  // ANR in background services.
+  BACKGROUND_SERVICE = 7
 };
 
 [Extensible]
diff --git a/components/arc/mojom/video_accelerator_mojom_traits.h b/components/arc/mojom/video_accelerator_mojom_traits.h
index 594d53f..3328611 100644
--- a/components/arc/mojom/video_accelerator_mojom_traits.h
+++ b/components/arc/mojom/video_accelerator_mojom_traits.h
@@ -7,8 +7,8 @@
 
 #include <memory>
 
+#include "ash/components/arc/video_accelerator/video_frame_plane.h"
 #include "components/arc/mojom/video_common.mojom-shared.h"
-#include "components/arc/video_accelerator/video_frame_plane.h"
 #include "media/base/color_plane_layout.h"
 #include "media/base/video_codecs.h"
 #include "media/base/video_frame_layout.h"
diff --git a/components/arc/session/arc_container_client_adapter.h b/components/arc/session/arc_container_client_adapter.h
deleted file mode 100644
index 95f96e7..0000000
--- a/components/arc/session/arc_container_client_adapter.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 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_ARC_SESSION_ARC_CONTAINER_CLIENT_ADAPTER_H_
-#define COMPONENTS_ARC_SESSION_ARC_CONTAINER_CLIENT_ADAPTER_H_
-
-#include <memory>
-
-#include "components/arc/session/arc_client_adapter.h"
-
-namespace arc {
-
-// Returns an adapter for talking to session_manager via D-Bus.
-std::unique_ptr<ArcClientAdapter> CreateArcContainerClientAdapter();
-
-}  // namespace arc
-
-#endif  // COMPONENTS_ARC_SESSION_ARC_CONTAINER_CLIENT_ADAPTER_H_
diff --git a/components/autofill/core/browser/payments/autofill_offer_manager.cc b/components/autofill/core/browser/payments/autofill_offer_manager.cc
index 42ca3d8..ae68d83 100644
--- a/components/autofill/core/browser/payments/autofill_offer_manager.cc
+++ b/components/autofill/core/browser/payments/autofill_offer_manager.cc
@@ -7,6 +7,7 @@
 #include <map>
 
 #include "base/bind.h"
+#include "base/containers/contains.h"
 #include "base/ranges/algorithm.h"
 #include "base/ranges/ranges.h"
 #include "base/strings/utf_string_conversions.h"
@@ -75,17 +76,12 @@
 }
 
 bool AutofillOfferManager::IsUrlEligible(const GURL& last_committed_url) {
-  // Checking set::empty and using set::count to prevent possible crashes (see
-  // crbug.com/1195949).
   if (coupon_service_delegate_ &&
       coupon_service_delegate_->IsUrlEligible(last_committed_url)) {
     return true;
   }
-  // For most cases this vector will be empty, so add the empty check to avoid
-  // unnecessary calls.
-  return !eligible_merchant_domains_.empty() &&
-         eligible_merchant_domains_.count(
-             last_committed_url.DeprecatedGetOriginAsURL());
+  return base::Contains(eligible_merchant_domains_,
+                        last_committed_url.DeprecatedGetOriginAsURL());
 }
 
 AutofillOfferData* AutofillOfferManager::GetOfferForUrl(
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
index a629fdd..f277e52 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -720,10 +720,6 @@
                 && !WebsitePreferenceBridge.isCategoryEnabled(
                         browserContextHandle, ContentSettingsType.AUTOMATIC_DOWNLOADS)) {
             allowSpecifyingExceptions = true;
-        } else if (mCategory.showSites(SiteSettingsCategory.Type.AUTO_DARK_WEB_CONTENT)
-                && WebsitePreferenceBridge.isCategoryEnabled(
-                        browserContextHandle, ContentSettingsType.AUTO_DARK_WEB_CONTENT)) {
-            allowSpecifyingExceptions = true;
         }
         if (allowSpecifyingExceptions) {
             getPreferenceScreen().addPreference(new AddExceptionPreference(getStyledContext(),
diff --git a/components/component_updater/android/component_loader_policy.cc b/components/component_updater/android/component_loader_policy.cc
index a7cef21..cdffa4e 100644
--- a/components/component_updater/android/component_loader_policy.cc
+++ b/components/component_updater/android/component_loader_policy.cc
@@ -7,7 +7,7 @@
 #include <jni.h>
 #include <stdio.h>
 
-#include <cstddef>
+#include <stddef.h>
 #include <map>
 #include <memory>
 #include <string>
@@ -58,7 +58,8 @@
 
 std::unique_ptr<base::DictionaryValue> ReadManifestFromFd(int fd) {
   std::string content;
-  base::ScopedFILE file_stream(fdopen(fd, "r"));
+  base::ScopedFILE file_stream(
+      base::FileToFILE(base::File(std::move(fd)), "r"));
   return base::ReadStreamToString(file_stream.get(), &content)
              ? ReadManifest(content)
              : nullptr;
diff --git a/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc b/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc
index 351fec9e..4d8c6f2 100644
--- a/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc
+++ b/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc
@@ -5,7 +5,6 @@
 #include "components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.h"
 
 #include <stdint.h>
-#include <stdio.h>
 
 #include <memory>
 #include <string>
diff --git a/components/content_creation/notes/core/server/note_data.cc b/components/content_creation/notes/core/server/note_data.cc
index 202bfb5..625e567 100644
--- a/components/content_creation/notes/core/server/note_data.cc
+++ b/components/content_creation/notes/core/server/note_data.cc
@@ -4,7 +4,7 @@
 
 #include "components/content_creation/notes/core/server/note_data.h"
 
-#include "components/shared_highlighting/core/common/text_fragments_utils.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #include "url/gurl.h"
 
 namespace content_creation {
diff --git a/components/cronet/PRESUBMIT.py b/components/cronet/PRESUBMIT.py
index 1c940c4..2727c04 100644
--- a/components/cronet/PRESUBMIT.py
+++ b/components/cronet/PRESUBMIT.py
@@ -7,12 +7,14 @@
 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
 for more details about the presubmit API built into depot_tools.
 """
-
 import os
 
+USE_PYTHON3 = True
+
 def _PyLintChecks(input_api, output_api):
   pylint_checks = input_api.canned_checks.GetPylint(input_api, output_api,
-          extra_paths_list=_GetPathsToPrepend(input_api), pylintrc='pylintrc')
+          extra_paths_list=_GetPathsToPrepend(input_api), pylintrc='pylintrc',
+          version='2.6')
   return input_api.RunTests(pylint_checks)
 
 
@@ -69,13 +71,17 @@
         'API classes must be in org.chromium.net package, and implementation\n'
         'classes must not be in org.chromium.net package.',
         problems)]
-  else:
-    return []
+  return []
 
 
 def _RunToolsUnittests(input_api, output_api):
   return input_api.canned_checks.RunUnitTestsInDirectory(
-      input_api, output_api, '.', [ r'^tools_unittest\.py$'])
+      input_api, output_api,
+      '.',
+      [ r'^tools_unittest\.py$'],
+      run_on_python2 = False,
+      run_on_python3 = True,
+      skip_shebang_check = True)
 
 
 def _ChangeAffectsCronetTools(change):
diff --git a/components/cronet/android/test/javaperftests/run.py b/components/cronet/android/test/javaperftests/run.py
index d973fd1f..4db5d38 100755
--- a/components/cronet/android/test/javaperftests/run.py
+++ b/components/cronet/android/test/javaperftests/run.py
@@ -41,13 +41,13 @@
 """
 
 import json
-import optparse
+import argparse
 import os
 import shutil
 import sys
 import tempfile
 import time
-import urllib
+import urllib.parse
 
 REPOSITORY_ROOT = os.path.abspath(os.path.join(
     os.path.dirname(__file__), '..', '..', '..', '..', '..'))
@@ -67,7 +67,7 @@
 from pylib import constants
 from telemetry import android
 from telemetry import benchmark
-from telemetry import story
+from telemetry import story as story_module
 from telemetry.web_perf import timeline_based_measurement
 # pylint: enable=wrong-import-position
 
@@ -87,7 +87,7 @@
     self._device = device
     config = perf_test_utils.GetConfig(device)
     device.RemovePath(config['DONE_FILE'], force=True)
-    self.url ='http://dummy/?'+urllib.urlencode(config)
+    self.url ='http://dummy/?'+urllib.parse.urlencode(config)
     start_intent = intent.Intent(
         package=perf_test_utils.APP_PACKAGE,
         activity=perf_test_utils.APP_ACTIVITY,
@@ -98,23 +98,23 @@
         data=self.url,
         extras=None,
         category=None)
-    super(CronetPerfTestAndroidStory, self).__init__(
+    super().__init__(
         start_intent, name='CronetPerfTest',
         # No reason to wait for app; Run() will wait for results.  By default
         # StartActivity will timeout waiting for CronetPerfTest, so override
         # |is_app_ready_predicate| to not wait.
         is_app_ready_predicate=lambda app: True)
 
-  def Run(self, shared_user_story_state):
+  def Run(self, shared_state):
     while not self._device.FileExists(
         perf_test_utils.GetConfig(self._device)['DONE_FILE']):
       time.sleep(1.0)
 
 
-class CronetPerfTestStorySet(story.StorySet):
+class CronetPerfTestStorySet(story_module.StorySet):
 
   def __init__(self, device):
-    super(CronetPerfTestStorySet, self).__init__()
+    super().__init__()
     # Create and add Cronet perf test AndroidStory.
     self.AddStory(CronetPerfTestAndroidStory(device))
 
@@ -126,13 +126,15 @@
   # Cronet perf test app.
 
   def __init__(self, device, options):
-    super(CronetPerfTestMeasurement, self).__init__(options)
+    super().__init__(options)
     self._device = device
 
+  # pylint: disable=redefined-outer-name
   def WillRunStory(self, platform, story=None):
     # Skip parent implementation which doesn't apply to Cronet perf test app as
     # it is not a browser with a timeline interface.
     pass
+  # pylint: enable=redefined-outer-name
 
   def Measure(self, platform, results):
     # Reads results from |RESULTS_FILE| on target and adds to |results|.
@@ -150,10 +152,10 @@
 class CronetPerfTestBenchmark(benchmark.Benchmark):
   # Benchmark implementation spawning off Cronet perf test measurement and
   # StorySet.
-  SUPPORTED_PLATFORMS = [story.expectations.ALL_ANDROID]
+  SUPPORTED_PLATFORMS = [story_module.expectations.ALL_ANDROID]
 
   def __init__(self, max_failures=None):
-    super(CronetPerfTestBenchmark, self).__init__(max_failures)
+    super().__init__(max_failures)
     self._device = GetDevice()
 
   def CreatePageTest(self, options):
@@ -164,13 +166,13 @@
 
 
 def main():
-  parser = optparse.OptionParser()
-  parser.add_option('--output-format', default='html',
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--output-format', default='html',
                    help='The output format of the results file.')
-  parser.add_option('--output-dir', default=None,
+  parser.add_argument('--output-dir', default=None,
                    help='The directory for the output file. Default value is '
                         'the base directory of this script.')
-  options, _ = parser.parse_args()
+  args, _ = parser.parse_known_args()
   constants.SetBuildType(perf_test_utils.BUILD_TYPE)
   # Install APK
   device = GetDevice()
@@ -206,9 +208,9 @@
   sys.argv.insert(1, 'run')
   sys.argv.insert(2, 'run.CronetPerfTestBenchmark')
   sys.argv.insert(3, '--browser=android-system-chrome')
-  sys.argv.insert(4, '--output-format=' + options.output_format)
-  if options.output_dir:
-    sys.argv.insert(5, '--output-dir=' + options.output_dir)
+  sys.argv.insert(4, '--output-format=' + args.output_format)
+  if args.output_dir:
+    sys.argv.insert(5, '--output-dir=' + args.output_dir)
   benchmark_runner.main(runner_config)
   # Shutdown.
   quic_server.ShutdownQuicServer()
diff --git a/components/cronet/tools/android_rndis_forwarder.py b/components/cronet/tools/android_rndis_forwarder.py
index 4eff5da..84d0535 100644
--- a/components/cronet/tools/android_rndis_forwarder.py
+++ b/components/cronet/tools/android_rndis_forwarder.py
@@ -11,13 +11,13 @@
 import subprocess
 import sys
 
+ # pylint: disable=wrong-import-position,inconsistent-return-statements
 REPOSITORY_ROOT = os.path.abspath(os.path.join(
     os.path.dirname(__file__), '..', '..', '..'))
 sys.path.append(os.path.join(REPOSITORY_ROOT, 'tools', 'perf'))
-from core import path_util  # pylint: disable=wrong-import-position
+from core import path_util
 sys.path.append(path_util.GetTelemetryDir())
 
-# pylint: disable=wrong-import-position
 from telemetry.core import platform
 from telemetry.internal.platform import android_device
 from telemetry.internal.util import binary_manager
@@ -29,7 +29,7 @@
 # pylint: enable=wrong-import-position
 
 
-class AndroidRndisForwarder(object):
+class AndroidRndisForwarder():
   """Forwards traffic using RNDIS. Assumes the device has root access."""
 
   def __init__(self, device, rndis_configurator):
@@ -129,7 +129,7 @@
         ['netcfg', self._device_iface, 'down'], check_return=True)
 
 
-class AndroidRndisConfigurator(object):
+class AndroidRndisConfigurator():
   """Configures a linux host to connect to an android device via RNDIS.
 
   Note that we intentionally leave RNDIS running on the device. This is
diff --git a/components/cronet/tools/api_static_checks_unittest.py b/components/cronet/tools/api_static_checks_unittest.py
index 7f415dcf..8f88804 100755
--- a/components/cronet/tools/api_static_checks_unittest.py
+++ b/components/cronet/tools/api_static_checks_unittest.py
@@ -7,8 +7,8 @@
 
 
 import contextlib
-from cStringIO import StringIO
-import md5
+import hashlib
+from io import StringIO
 import os
 import shutil
 import sys
@@ -102,7 +102,7 @@
 
   def run_check_api_calls(self, api_java, impl_java):
     test = self
-    class MockOpts(object):
+    class MockOpts():
       def __init__(self):
         self.api_jar = test.make_jar(api_java, 'Api')
         self.impl_jar = [test.make_jar(impl_java, 'Impl')]
@@ -147,9 +147,9 @@
     api_stamp = api.split('\n')[-2]
     stamp_length = len('Stamp: 78418460c193047980ae9eabb79293f2\n')
     api = api[:-stamp_length]
-    api_hash = md5.new()
-    api_hash.update(api)
-    self.assertEquals(api_stamp, 'Stamp: %s' % api_hash.hexdigest())
+    api_hash = hashlib.md5()
+    api_hash.update(api.encode())
+    self.assertEqual(api_stamp, 'Stamp: %s' % api_hash.hexdigest())
 
     return [return_code == 0, output, api, api_version]
 
diff --git a/components/cronet/tools/cr_cronet.py b/components/cronet/tools/cr_cronet.py
index 42bff8f5f..99485859 100755
--- a/components/cronet/tools/cr_cronet.py
+++ b/components/cronet/tools/cr_cronet.py
@@ -19,13 +19,13 @@
 
 
 def run(command, **kwargs):
-  print command, kwargs
+  print(command, kwargs)
   return subprocess.call(command, **kwargs)
 
 
 def run_shell(command, extra_options=''):
   command = command + ' ' + extra_options
-  print command
+  print(command)
   return os.system(command)
 
 
@@ -121,7 +121,7 @@
 
 
 def get_ios_gn_args(is_release, bundle_id_prefix, target_cpu):
-  print is_release, bundle_id_prefix, target_cpu
+  print(is_release, bundle_id_prefix, target_cpu)
   return get_mobile_gn_args('ios', is_release) + \
       ('is_cronet_build=true  '
       'enable_remoting=false '
@@ -132,6 +132,15 @@
       'target_cpu="%s" ') % (bundle_id_prefix, target_cpu)
 
 
+def get_android_gn_args(is_release):
+  return (get_mobile_gn_args('android', is_release) +
+          # Keep in sync with //tools/mb/mb_config.pyl cronet_android config.
+          'default_min_sdk_version = 16 ' +
+          'use_errorprone_java_compiler=true ' +
+          'enable_reporting=true ' +
+          'use_hashed_jni_names=true ')
+
+
 def get_mac_gn_args(is_release):
   return get_default_gn_args('mac', is_release) + \
       'disable_histogram_support=true ' + \
@@ -170,8 +179,8 @@
                       help='configure bundle id prefix')
 
   options, extra_options = parser.parse_known_args()
-  print options
-  print extra_options
+  print(options)
+  print(extra_options)
 
   if is_ios:
     test_target = 'cronet_test'
@@ -191,9 +200,7 @@
   else:
     test_target = 'cronet_test_instrumentation_apk'
     unit_target = 'cronet_unittests_android'
-    gn_args = get_mobile_gn_args('android', options.release) + \
-              'use_errorprone_java_compiler=true enable_reporting=true ' + \
-              'use_hashed_jni_names=true '
+    gn_args = get_android_gn_args(options.release)
     gn_extra = []
     out_dir_suffix = ''
     if options.x86:
diff --git a/components/cronet/tools/generate_accept_languages.py b/components/cronet/tools/generate_accept_languages.py
index 2db0a44..beb4170 100644
--- a/components/cronet/tools/generate_accept_languages.py
+++ b/components/cronet/tools/generate_accept_languages.py
@@ -13,7 +13,6 @@
 #   * assumes that there is only one relevant element with the
 #     IDS_ACCEPT_LANGUAGES attribute
 
-from __future__ import print_function
 
 import os
 import re
@@ -22,11 +21,13 @@
 
 STRINGS_DIR = sys.argv[2] + 'components/strings/'
 
+# pylint: disable=inconsistent-return-statements
 def extract_accept_langs(filename):
   tree = ElementTree.parse(STRINGS_DIR + filename).getroot()
   for child in tree:
     if child.get('id') == 'IDS_ACCEPT_LANGUAGES':
       return tree.get('lang'), child.text
+# pylint: enable=inconsistent-return-statements
 
 def gen_accept_langs_table():
   accept_langs_list = [extract_accept_langs(filename)
diff --git a/components/cronet/tools/generate_idl_bindings.py b/components/cronet/tools/generate_idl_bindings.py
index 4df9c7dd..fcaeec45 100755
--- a/components/cronet/tools/generate_idl_bindings.py
+++ b/components/cronet/tools/generate_idl_bindings.py
@@ -4,7 +4,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import optparse
+import argparse
 import os
 import shutil
 import sys
@@ -12,7 +12,7 @@
 
 def run(command, extra_options=''):
   command = command + ' ' + extra_options
-  print command
+  print(command)
   ret = os.system(command)
   if ret != 0:
     raise OSError(ret)
@@ -36,12 +36,12 @@
 
 
 def main():
-  parser = optparse.OptionParser()
-  parser.add_option('--output-path',
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--output-path',
         help='Output path for generated bindings')
 
-  options, input_files = parser.parse_args()
-  GenerateIdlBindings(options.output_path, input_files)
+  args, input_files = parser.parse_known_args()
+  GenerateIdlBindings(args.output_path, input_files)
 
 
 if __name__ == '__main__':
diff --git a/components/cronet/tools/generate_javadoc.py b/components/cronet/tools/generate_javadoc.py
index cc878ca..0a6843f 100755
--- a/components/cronet/tools/generate_javadoc.py
+++ b/components/cronet/tools/generate_javadoc.py
@@ -4,7 +4,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import optparse
+import argparse
 import os
 import shutil
 import sys
@@ -45,11 +45,11 @@
                           CronetPostprocessor(md), '_end')
 
 
-def GenerateJavadoc(options, src_dir, output_dir):
-  working_dir = os.path.join(options.input_dir, 'android', 'api')
-  overview_file = os.path.abspath(options.overview_file)
+def GenerateJavadoc(args, src_dir, output_dir):
+  working_dir = os.path.join(args.input_dir, 'android', 'api')
+  overview_file = os.path.abspath(args.overview_file)
 
-  android_sdk_jar = options.android_sdk_jar
+  android_sdk_jar = args.android_sdk_jar
   if not android_sdk_jar:
     android_sdk_jar = os.path.join(
         SDK_DIR, 'platforms', 'android-27', 'android.jar')
@@ -70,7 +70,7 @@
     '-federationapi', 'Android', os.path.join(DOCLAVA_DIR, 'current.txt'),
     '-classpath',
     '%s:%s' % (os.path.abspath(android_sdk_jar),
-               os.path.abspath(options.support_annotations_jar)),
+               os.path.abspath(args.support_annotations_jar)),
   ]
   for subdir, _, files in os.walk(src_dir):
     for filename in files:
@@ -96,44 +96,44 @@
 
 
 def main():
-  parser = optparse.OptionParser()
+  parser = argparse.ArgumentParser()
   build_utils.AddDepfileOption(parser)
-  parser.add_option('--output-dir', help='Directory to put javadoc')
-  parser.add_option('--input-dir', help='Root of cronet source')
-  parser.add_option('--input-src-jar', help='Cronet api source jar')
-  parser.add_option('--overview-file', help='Path of the overview page')
-  parser.add_option('--readme-file', help='Path of the README.md')
-  parser.add_option('--zip-file', help='Path to ZIP archive of javadocs.')
-  parser.add_option('--android-sdk-jar', help='Path to android.jar')
-  parser.add_option('--support-annotations-jar',
+  parser.add_argument('--output-dir', help='Directory to put javadoc')
+  parser.add_argument('--input-dir', help='Root of cronet source')
+  parser.add_argument('--input-src-jar', help='Cronet api source jar')
+  parser.add_argument('--overview-file', help='Path of the overview page')
+  parser.add_argument('--readme-file', help='Path of the README.md')
+  parser.add_argument('--zip-file', help='Path to ZIP archive of javadocs.')
+  parser.add_argument('--android-sdk-jar', help='Path to android.jar')
+  parser.add_argument('--support-annotations-jar',
                     help='Path to support-annotations-$VERSION.jar')
 
-  options, _ = parser.parse_args()
+  args, _ = parser.parse_known_args()
   # A temporary directory to put the output of cronet api source jar files.
-  unzipped_jar_path = tempfile.mkdtemp(dir=options.output_dir)
-  if os.path.exists(options.input_src_jar):
-    jar_cmd = ['jar', 'xf', os.path.abspath(options.input_src_jar)]
+  unzipped_jar_path = tempfile.mkdtemp(dir=args.output_dir)
+  if os.path.exists(args.input_src_jar):
+    jar_cmd = ['jar', 'xf', os.path.abspath(args.input_src_jar)]
     build_utils.CheckOutput(jar_cmd, cwd=unzipped_jar_path)
   else:
-    raise Exception('Jar file does not exist: %s' % options.input_src_jar)
+    raise Exception('Jar file does not exist: %s' % args.input_src_jar)
 
-  net_docs.ProcessDocs([options.readme_file], options.input_dir,
-                       options.output_dir, extensions=[CronetExtension()])
+  net_docs.ProcessDocs([args.readme_file], args.input_dir,
+                       args.output_dir, extensions=[CronetExtension()])
 
-  output_dir = os.path.abspath(os.path.join(options.output_dir, 'javadoc'))
-  GenerateJavadoc(options, os.path.abspath(unzipped_jar_path), output_dir)
+  output_dir = os.path.abspath(os.path.join(args.output_dir, 'javadoc'))
+  GenerateJavadoc(args, os.path.abspath(unzipped_jar_path), output_dir)
 
-  if options.zip_file:
-    assert options.zip_file.endswith('.zip')
-    shutil.make_archive(options.zip_file[:-4], 'zip', output_dir)
-  if options.depfile:
-    assert options.zip_file
+  if args.zip_file:
+    assert args.zip_file.endswith('.zip')
+    shutil.make_archive(args.zip_file[:-4], 'zip', output_dir)
+  if args.depfile:
+    assert args.zip_file
     deps = []
-    for root, _, filenames in os.walk(options.input_dir):
+    for root, _, filenames in os.walk(args.input_dir):
       # Ignore .pyc files here, it might be re-generated during build.
       deps.extend(os.path.join(root, f) for f in filenames
                   if not f.endswith('.pyc'))
-    build_utils.WriteDepfile(options.depfile, options.zip_file, deps)
+    build_utils.WriteDepfile(args.depfile, args.zip_file, deps)
   # Clean up temporary output directory.
   build_utils.DeleteDirectory(unzipped_jar_path)
 
diff --git a/components/cronet/tools/generate_proguard_file.py b/components/cronet/tools/generate_proguard_file.py
index 8ff42cf..dcb8ad8 100755
--- a/components/cronet/tools/generate_proguard_file.py
+++ b/components/cronet/tools/generate_proguard_file.py
@@ -10,7 +10,7 @@
 # The final output file is formed by concatenating all of the
 # input proguard files.
 
-import optparse
+import argparse
 import sys
 
 
@@ -20,14 +20,14 @@
 
 
 def main():
-  parser = optparse.OptionParser()
-  parser.add_option('--output-file',
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--output-file',
           help='Output file for the generated proguard file')
 
-  options, input_files = parser.parse_args()
+  args, input_files = parser.parse_known_args()
 
   # Concatenate all the proguard files.
-  with open(options.output_file, 'wb') as target:
+  with open(args.output_file, 'wb') as target:
     for input_file in input_files:
       target.write(ReadFile(input_file))
 
diff --git a/components/cronet/tools/generators/cronet_bindings_generator.py b/components/cronet/tools/generators/cronet_bindings_generator.py
index 02cff017..167cc7cb 100755
--- a/components/cronet/tools/generators/cronet_bindings_generator.py
+++ b/components/cronet/tools/generators/cronet_bindings_generator.py
@@ -15,6 +15,7 @@
 import struct
 import sys
 
+# pylint: disable=inconsistent-return-statements
 # Disable lint check for finding modules:
 # pylint: disable=F0401
 
@@ -63,7 +64,7 @@
       generator_name = os.path.join(script_dir,
                                     _BUILTIN_GENERATORS[language])
     else:
-      print "Unknown generator name %s" % generator_name
+      print ("Unknown generator name %s" % generator_name)
       sys.exit(1)
     generator_module = imp.load_source(os.path.basename(generator_name)[:-3],
                                        generator_name)
@@ -79,7 +80,7 @@
                     zip(imported_filename_stack[1:], imported_filename_stack)]))
 
 
-class RelativePath(object):
+class RelativePath():
   """Represents a path relative to the source tree."""
   def __init__(self, path, source_root):
     self.path = path
@@ -139,7 +140,7 @@
     return f.read()
 
 
-class MojomProcessor(object):
+class MojomProcessor():
   """Parses mojom files and creates ASTs for them.
 
   Attributes:
@@ -161,7 +162,7 @@
       with open(filename) as f:
         typemaps = json.loads("".join([l for l in f.readlines()
                                        if no_comments(l)]))
-        for language, typemap in typemaps.iteritems():
+        for language, typemap in typemaps.items():
           language_map = self._typemap.get(language, {})
           language_map.update(typemap)
           self._typemap[language] = language_map
@@ -205,7 +206,7 @@
 
     if self._should_generate(rel_filename.path):
       AddComputedData(module)
-      for language, generator_module in generator_modules.iteritems():
+      for language, generator_module in generator_modules.items():
         generator = generator_module.Generator(
             module, args.output_dir, typemap=self._typemap.get(language, {}),
             variant=args.variant, bytecode_path=args.bytecode_path,
@@ -232,23 +233,23 @@
       return
 
     if rel_filename.path in imported_filename_stack:
-      print "%s: Error: Circular dependency" % rel_filename.path + \
-          MakeImportStackMessage(imported_filename_stack + [rel_filename.path])
+      print("%s: Error: Circular dependency" % rel_filename.path + \
+          MakeImportStackMessage(imported_filename_stack + [rel_filename.path]))
       sys.exit(1)
 
     try:
       with open(rel_filename.path) as f:
         source = f.read()
     except IOError as e:
-      print "%s: Error: %s" % (rel_filename.path, e.strerror) + \
-          MakeImportStackMessage(imported_filename_stack + [rel_filename.path])
+      print("%s: Error: %s" % (rel_filename.path, e.strerror) + \
+          MakeImportStackMessage(imported_filename_stack + [rel_filename.path]))
       sys.exit(1)
 
     try:
       tree = Parse(source, rel_filename.path)
     except Error as e:
       full_stack = imported_filename_stack + [rel_filename.path]
-      print str(e) + MakeImportStackMessage(full_stack)
+      print(str(e) + MakeImportStackMessage(full_stack))
       sys.exit(1)
 
     dirname = os.path.split(rel_filename.path)[0]
@@ -285,13 +286,13 @@
     with open(args.depfile, 'w') as f:
       f.write('%s: %s' % (
           args.depfile_target,
-          ' '.join(processor._parsed_files.keys())))
+          ' '.join(list(processor._parsed_files.keys()))))
 
   return 0
 
 
 def _Precompile(args, _):
-  generator_modules = LoadGenerators(",".join(_BUILTIN_GENERATORS.keys()))
+  generator_modules = LoadGenerators(",".join(list(_BUILTIN_GENERATORS.keys())))
 
   template_expander.PrecompileTemplates(generator_modules, args.output_dir)
   return 0
diff --git a/components/cronet/tools/generators/cronet_c_generator.py b/components/cronet/tools/generators/cronet_c_generator.py
index 43bbf7b..8e1bcc23 100644
--- a/components/cronet/tools/generators/cronet_c_generator.py
+++ b/components/cronet/tools/generators/cronet_c_generator.py
@@ -6,10 +6,14 @@
 
 import os
 
+# This is called from cronet_bindings_generator.py which does some magic to add
+# libraries to the lookup path which pylint does not
+# pylint: disable=import-error
 import mojom.generate.generator as generator
 import mojom.generate.module as mojom
 import mojom.generate.pack as pack
 from mojom.generate.template_expander import UseJinja
+# pylint: enable=import-error
 
 
 _kind_to_cpp_type = {
@@ -36,7 +40,7 @@
 
 ATTRIBUTE_ABSTRACT = "Abstract"
 
-class _NameFormatter(object):
+class _NameFormatter():
   """A formatter for the names of kinds or values."""
 
   def __init__(self, token, variant):
@@ -114,9 +118,12 @@
   def _ShouldIncludeNamespace(self, omit_namespace_for_module):
     return self._token.module
 
+
+  # pylint: disable=inconsistent-return-statements
   def _GetNamespace(self):
     if self._token.module:
       return NamespaceToArray(self._token.module.namespace)
+  # pylint: enable=inconsistent-return-statements
 
 
 def NamespaceToArray(namespace):
@@ -179,7 +186,7 @@
   return kind.attributes.get(ATTRIBUTE_ABSTRACT, False) \
       if kind.attributes else False
 
-class StructConstructor(object):
+class StructConstructor():
   """Represents a constructor for a generated struct.
 
   Fields:
@@ -202,8 +209,6 @@
 
 
 class Generator(generator.Generator):
-  def __init__(self, *args, **kwargs):
-    super(Generator, self).__init__(*args, **kwargs)
 
   def _GetExtraTraitsHeaders(self):
     extra_headers = set()
@@ -503,30 +508,29 @@
       checked.add(kind.spec)
       if mojom.IsNullableKind(kind):
         return False
-      elif mojom.IsStructKind(kind):
+      if mojom.IsStructKind(kind):
         if kind.native_only:
           return False
         if (self._IsTypemappedKind(kind) and
             not self.typemap[self._GetFullMojomNameForKind(kind)]["hashable"]):
           return False
         return all(Check(field.kind) for field in kind.fields)
-      elif mojom.IsEnumKind(kind):
+      if mojom.IsEnumKind(kind):
         return not self._IsTypemappedKind(kind) or self.typemap[
             self._GetFullMojomNameForKind(kind)]["hashable"]
-      elif mojom.IsUnionKind(kind):
+      if mojom.IsUnionKind(kind):
         return all(Check(field.kind) for field in kind.fields)
-      elif mojom.IsAnyHandleKind(kind):
+      if mojom.IsAnyHandleKind(kind):
         return False
-      elif mojom.IsAnyInterfaceKind(kind):
+      if mojom.IsAnyInterfaceKind(kind):
         return False
       # TODO(crbug.com/735301): Arrays and maps could be made hashable. We just
       # don't have a use case yet.
-      elif mojom.IsArrayKind(kind):
+      if mojom.IsArrayKind(kind):
         return False
-      elif mojom.IsMapKind(kind):
+      if mojom.IsMapKind(kind):
         return False
-      else:
-        return True
+      return True
     return Check(kind)
 
   def _GetNativeTypeName(self, typemapped_kind):
@@ -805,10 +809,8 @@
         return "%d, %s, %s" % (expected_num_elements,
                                "true" if element_is_nullable else "false",
                                element_validate_params)
-      else:
-        return "%s, %s" % (key_validate_params, element_validate_params)
-    else:
-      return "%d, %s" % (expected_num_elements, enum_validate_func)
+      return "%s, %s" % (key_validate_params, element_validate_params)
+    return "%d, %s" % (expected_num_elements, enum_validate_func)
 
   def _GetNewContainerValidateParams(self, kind):
     if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and
diff --git a/components/cronet/tools/hide_symbols.py b/components/cronet/tools/hide_symbols.py
index 374982c1..ad05619 100755
--- a/components/cronet/tools/hide_symbols.py
+++ b/components/cronet/tools/hide_symbols.py
@@ -15,7 +15,7 @@
 from __future__ import print_function
 
 import glob
-import optparse
+import argparse
 import os
 import subprocess
 import sys
@@ -34,32 +34,32 @@
 
 
 def main():
-  parser = optparse.OptionParser()
-  parser.add_option(
+  parser = argparse.ArgumentParser()
+  parser.add_argument(
       '--input_libs',
       help='Comma-separated paths to input .a files which contain symbols '
            'which must be always linked.')
-  parser.add_option(
+  parser.add_argument(
       '--deps_lib',
       help='The path to a complete static library (.a file) which contains all '
            'dependencies of --input_libs. .o files in this library are also '
            'added to the output library, but only if they are referred from '
            '--input_libs.')
-  parser.add_option(
+  parser.add_argument(
       '--output_obj',
       help='Outputs the generated .o file here. This is an intermediate file.')
-  parser.add_option(
+  parser.add_argument(
       '--output_lib',
       help='Outputs the generated .a file here.')
-  parser.add_option(
+  parser.add_argument(
       '--current_cpu',
       help='The current processor architecture in the format of the target_cpu '
            'attribute in GN.')
-  parser.add_option(
+  parser.add_argument(
       '--use_custom_libcxx', default=False, action='store_true',
       help='Confirm there is a custom libc++ linked in.')
-  (options, args) = parser.parse_args()
-  assert not args
+  args, unknownargs = parser.parse_known_args()
+  assert not unknownargs
 
   developer_dir = subprocess.check_output(
       ['xcode-select', '--print-path'], universal_newlines=True).strip()
@@ -73,49 +73,49 @@
   # while "hiding" symbols not marked as visible.
   command = [
     'xcrun', 'ld',
-    '-arch', GN_CPU_TO_LD_ARCH[options.current_cpu],
+    '-arch', GN_CPU_TO_LD_ARCH[args.current_cpu],
     '-r',
   ]
-  for input_lib in options.input_libs.split(','):
+  for input_lib in args.input_libs.split(','):
     # By default, ld only pulls .o files out of a static library if needed to
     # resolve some symbol reference. We apply -force_load option to input_lib
     # (but not to deps_lib) to force pulling all .o files.
     command += ['-force_load', input_lib]
   command += xctoolchain_libs
   command += [
-    options.deps_lib,
-    '-o', options.output_obj
+    args.deps_lib,
+    '-o', args.output_obj
   ]
   try:
     subprocess.check_call(command)
   except subprocess.CalledProcessError:
     # Work around LD failure for x86 Debug buiilds when it fails with error:
     # ld: scattered reloc r_address too large for architecture i386
-    if options.current_cpu == "x86":
+    if args.current_cpu == "x86":
       # Combmine input lib with dependencies into output lib.
       command = [
         'xcrun', 'libtool', '-static', '-no_warning_for_no_symbols',
-        '-o', options.output_lib,
-        options.input_libs, options.deps_lib,
+        '-o', args.output_lib,
+        args.input_libs, args.deps_lib,
       ]
       subprocess.check_call(command)
       # Strip debug info from output lib so its size doesn't exceed 512mb.
       command = [
-        'xcrun', 'strip', '-S', options.output_lib,
+        'xcrun', 'strip', '-S', args.output_lib,
       ]
       subprocess.check_call(command)
       return
-    else:
-      exit(1)
 
-  if os.path.exists(options.output_lib):
-    os.remove(options.output_lib)
+    sys.exit(1)
+
+  if os.path.exists(args.output_lib):
+    os.remove(args.output_lib)
 
   # Creates a .a file which contains a single .o file.
   command = [
     'xcrun', 'ar', '-r',
-    options.output_lib,
-    options.output_obj,
+    args.output_lib,
+    args.output_obj,
   ]
 
   # When compiling for 64bit targets, the symbols in call_with_eh_frame.o are
@@ -125,13 +125,13 @@
   # other parts of cronet. Instead, simply add a second .o file with the
   # personality routine. Note that this issue was not caught by Chrome tests,
   # it was only detected when apps tried to link the resulting .a file.
-  if options.current_cpu == 'x64' or options.current_cpu == 'arm64':
+  if args.current_cpu in ('x64', 'arm64'):
     command += [ 'obj/base/base/call_with_eh_frame.o' ]
 
   subprocess.check_call(command)
 
-  if options.use_custom_libcxx:
-    ret = os.system('xcrun nm -u "' + options.output_obj +
+  if args.use_custom_libcxx:
+    ret = os.system('xcrun nm -u "' + args.output_obj +
                     '" | grep ___cxa_pure_virtual')
     if ret == 0:
       print("ERROR: Found undefined libc++ symbols, "
diff --git a/components/cronet/tools/link_dependencies.py b/components/cronet/tools/link_dependencies.py
index 94e612e9..af59a2d 100755
--- a/components/cronet/tools/link_dependencies.py
+++ b/components/cronet/tools/link_dependencies.py
@@ -135,7 +135,7 @@
   _, err = p.communicate()
   for line in err.splitlines():
     if not libtool_re.match(line):
-      print >>sys.stderr, line
+      print(line, file=sys.stderr)
   if p.returncode != 0:
     message = "subprocess libtool returned {0}".format(p.returncode)
     raise SubprocessError(message)
diff --git a/components/cronet/tools/package_ios.py b/components/cronet/tools/package_ios.py
deleted file mode 100755
index 00a08e6..0000000
--- a/components/cronet/tools/package_ios.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 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_ios.py - Build and Package Release and Debug frameworks for iOS.
-"""
-
-import argparse
-import os
-import shutil
-import sys
-
-from cronet.tools import cr_cronet
-
-
-def package_ios_framework_using_gn(out_dir):
-  print 'Building Cronet Dynamic Framework...'
-
-  # Package all builds in the output directory.
-  os.makedirs(out_dir)
-  build_dir = ''
-  for (is_release, build_config, gn_extra_args) in \
-        [(False, 'Debug', ''),
-         (True, 'Release', 'enable_stripping=true ')]:
-    for (target_device, target_cpu, additional_cpu) in \
-        [('os', 'arm', 'arm64'),
-         ('simulator', 'x86', 'x64')]:
-      target_dir = '%s-iphone%s' % (build_config, target_device)
-      build_dir = os.path.join("out", "build_ios", target_dir)
-      gn_args = cr_cronet.get_ios_gn_args(is_release, target_cpu) + \
-                'additional_target_cpus = ["%s"] ' % additional_cpu
-
-      print 'Generating ninja ' + target_dir
-      gn_result = cr_cronet.gn(build_dir, gn_args + gn_extra_args)
-      if gn_result != 0:
-        return gn_result
-
-      print 'Building ' + target_dir
-      build_result = cr_cronet.build(build_dir, 'cronet_package')
-      if build_result != 0:
-        return build_result
-
-      # Copy framework.
-      shutil.copytree(os.path.join(build_dir, 'Cronet.framework'),
-          os.path.join(out_dir, 'Dynamic', target_dir, 'Cronet.framework'))
-      # Copy symbols.
-      shutil.copytree(os.path.join(build_dir, 'Cronet.dSYM'),
-          os.path.join(out_dir, 'Dynamic', target_dir, 'Cronet.framework.dSYM'))
-      # Copy static framework.
-      shutil.copytree(os.path.join(build_dir, 'Static', 'Cronet.framework'),
-          os.path.join(out_dir, 'Static', target_dir, 'Cronet.framework'))
-
-  # Copy common files from last built package.
-  package_dir = os.path.join(build_dir, 'cronet')
-  shutil.copy2(os.path.join(package_dir, 'AUTHORS'), out_dir)
-  shutil.copy2(os.path.join(package_dir, 'LICENSE'), out_dir)
-  shutil.copy2(os.path.join(package_dir, 'VERSION'), out_dir)
-  # Copy the headers.
-  shutil.copytree(os.path.join(build_dir,
-                               'Cronet.framework', 'Headers'),
-                  os.path.join(out_dir, 'Headers'))
-  print 'Cronet framework is packaged into %s' % out_dir
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('out_dir', help='path to output directory')
-  options, _ = parser.parse_known_args()
-
-  out_dir = options.out_dir
-
-  # Make sure that the output directory does not exist
-  if os.path.exists(out_dir):
-    print >>sys.stderr, 'The output directory already exists: ' + out_dir
-    return 1
-
-  return package_ios_framework_using_gn(out_dir)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/components/cronet/tools/package_mac.py b/components/cronet/tools/package_mac.py
index a5fcf40..df08350 100755
--- a/components/cronet/tools/package_mac.py
+++ b/components/cronet/tools/package_mac.py
@@ -16,26 +16,28 @@
 from cronet.tools import cr_cronet
 
 
+# pylint: disable=inconsistent-return-statements
 def package_mac(out_dir, gn_args, build_config):
   target_dir = out_dir + '/' + build_config
   build_dir = "out/build_mac/" + build_config
-  print 'Generating Ninja ' + gn_args
+  print('Generating Ninja ' + gn_args)
   gn_result = cr_cronet.run('gn gen %s --args=\'%s\'' % (build_dir, gn_args))
   if gn_result != 0:
     return gn_result
 
-  print 'Building ' + build_dir
+  print('Building ' + build_dir)
   build_result = cr_cronet.run('ninja -C %s cronet_package -j200' % build_dir)
   if build_result != 0:
     return build_result
 
-  print 'Copying to ' + target_dir
+  print('Copying to ' + target_dir)
   if (not os.path.exists(out_dir)):
     shutil.copytree(build_dir + "/cronet", out_dir,
                     ignore=shutil.ignore_patterns('libcronet*'))
   os.mkdir(target_dir)
   for libcronet in glob.glob(build_dir + "/cronet/libcronet*"):
     shutil.copy(libcronet, target_dir)
+# pylint: enable=inconsistent-return-statements
 
 
 def main():
@@ -47,7 +49,7 @@
 
   # Make sure that the output directory does not exist
   if os.path.exists(out_dir):
-    print >>sys.stderr, 'The output directory already exists: ' + out_dir
+    print('The output directory already exists: ' + out_dir, file=sys.stderr)
     return 1
 
   return package_mac(out_dir, cr_cronet.get_mac_gn_args(True), "opt") or \
diff --git a/components/cronet/tools/perf_test_utils.py b/components/cronet/tools/perf_test_utils.py
index b1b5d9b..23b4a71 100755
--- a/components/cronet/tools/perf_test_utils.py
+++ b/components/cronet/tools/perf_test_utils.py
@@ -62,11 +62,11 @@
 # Add benchmark config to global state for easy access.
 globals().update(DEFAULT_BENCHMARK_CONFIG)
 # Pylint doesn't really interpret the file, so it won't find the definitions
-# added from DEFAULT_BENCHMARK_CONFIG, so suppress the undefined variable
-# warning.
-#pylint: disable=undefined-variable
+# added from DEFAULT_BENCHMARK_CONFIG, so suppress the undefined variable and
+# bad string format type warnings.
+#pylint: disable=undefined-variable,bad-string-format-type
 
-class NativeDevice(object):
+class NativeDevice():
   def GetExternalStoragePath(self):
     return '/tmp'
 
@@ -108,7 +108,7 @@
   return 'http://%s:%d/%s' % (GetServersHost(device), HTTP_PORT, resource)
 
 
-class QuicServer(object):
+class QuicServer():
 
   def __init__(self, quic_server_doc_root):
     self._process = None
@@ -122,7 +122,7 @@
            '--port=%d' % QUIC_PORT]
     logging.info("Starting Quic Server: %s", cmd)
     self._process = subprocess.Popen(cmd)
-    assert self._process != None
+    assert self._process is not None
     # Wait for quic_server to start serving.
     waited_s = 0
     while subprocess.call(['lsof', '-i', 'udp:%d' % QUIC_PORT, '-p',
diff --git a/components/feed/core/proto/v2/ui.proto b/components/feed/core/proto/v2/ui.proto
index 3796b596..a391b8c 100644
--- a/components/feed/core/proto/v2/ui.proto
+++ b/components/feed/core/proto/v2/ui.proto
@@ -50,6 +50,11 @@
 
   // A client ID used for reliability logging.
   string client_instance_id = 3;
+
+  // Whether attention / interaction logging is enabled.
+  bool logging_enabled = 4;
+  // Whether view actions may be recorded.
+  bool view_actions_enabled = 5;
 }
 
 // A horizontal slice of UI to be presented in the vertical-scrolling feed.
diff --git a/components/feed/core/v2/api_test/feed_api_stream_unittest.cc b/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
index b3bf75a..73eccf51 100644
--- a/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
+++ b/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
@@ -197,7 +197,8 @@
   const feedui::StreamUpdate& initial_state = surface.initial_state.value();
   const feedui::StreamUpdate& update = surface.update.value();
 
-  ASSERT_EQ("2 slices -> 2 slices", surface.DescribeUpdates());
+  ASSERT_EQ("[View logging only user@foo] 2 slices -> 2 slices",
+            surface.DescribeUpdates());
   // First slice is just an ID that matches the old 1st slice ID.
   EXPECT_EQ(initial_state.updated_slices(0).slice().slice_id(),
             update.updated_slices(0).slice_id());
@@ -232,7 +233,8 @@
 
   // The last update should have only one new piece of content.
   // This verifies the current content set is tracked properly.
-  ASSERT_EQ("2 slices -> 3 slices -> 4 slices", surface.DescribeUpdates());
+  ASSERT_EQ("[View logging only user@foo] 2 slices -> 3 slices -> 4 slices",
+            surface.DescribeUpdates());
 
   ASSERT_EQ(4, surface.update->updated_slices().size());
   EXPECT_FALSE(surface.update->updated_slices(0).has_slice());
@@ -785,7 +787,10 @@
                   .empty());
 
   // Validate the downstream consumption of the response.
-  EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+  // TODO(crbug.com/1268575): We should disable view logging for the signed-out
+  // feed even if the user is signed-in.
+  EXPECT_EQ("loading -> [View logging only user@foo] 2 slices",
+            surface.DescribeUpdates());
   EXPECT_EQ(kSessionId, stream_->GetMetadata().session_id().token());
   EXPECT_FALSE(stream_->GetModel(surface.GetStreamType())->signed_in());
 
@@ -1467,7 +1472,7 @@
   EXPECT_EQ(false, cr.GetResult());
   EXPECT_EQ(
       "loading -> [user@foo] 2 slices -> 2 slices +spinner -> 2 slices -> "
-      "loading -> [NO Logging] 2 slices",
+      "loading -> [NO logging user@foo] 2 slices",
       surface.DescribeUpdates());
 }
 
diff --git a/components/feed/core/v2/api_test/feed_api_test.cc b/components/feed/core/v2/api_test/feed_api_test.cc
index 9b04d16..900704c 100644
--- a/components/feed/core/v2/api_test/feed_api_test.cc
+++ b/components/feed/core/v2/api_test/feed_api_test.cc
@@ -227,14 +227,20 @@
   std::string parameter_change_description;
   if (!update->updated_slices().empty()) {
     std::string logging_parameters_description;
-    if (!update->logging_parameters().email().empty()) {
+    if (update->logging_parameters().logging_enabled()) {
+      // View actions will always be enabled if logging is enabled.
+      CHECK(update->logging_parameters().view_actions_enabled());
       logging_parameters_description = update->logging_parameters().email();
+    } else if (!update->logging_parameters().email().empty()) {
+      if (update->logging_parameters().view_actions_enabled()) {
+        logging_parameters_description =
+            "View logging only " + update->logging_parameters().email();
+      } else {
+        logging_parameters_description =
+            "NO logging " + update->logging_parameters().email();
+      }
     }
-    if (!update->logging_parameters().session_id().empty()) {
-      CHECK(logging_parameters_description.empty());
-      logging_parameters_description =
-          update->logging_parameters().session_id();
-    }
+
     if (last_logging_parameters_description_ !=
         logging_parameters_description) {
       last_logging_parameters_description_ = logging_parameters_description;
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc
index 60eecf1..3803e3c0 100644
--- a/components/feed/core/v2/feed_stream.cc
+++ b/components/feed/core/v2/feed_stream.cc
@@ -333,12 +333,12 @@
     const StreamType& stream_type) {
   LoggingParameters logging_params;
   logging_params.client_instance_id = GetClientInstanceId();
-  if (IsActivityLoggingEnabled(stream_type)) {
-    logging_params.email = delegate_->GetSyncSignedInEmail();
-    if (logging_params.email.empty()) {
-      logging_params.session_id = GetSessionId();
-    }
-  }
+  logging_params.logging_enabled = IsActivityLoggingEnabled(stream_type);
+  logging_params.view_actions_enabled = CanLogViews();
+  // We provide account name even if logging is disabled, so that account name
+  // can be verified for action uploads.
+  logging_params.email = delegate_->GetSyncSignedInEmail();
+
   return logging_params;
 }
 
@@ -657,6 +657,14 @@
   }
 }
 
+void FeedStream::ProcessThereAndBackAgain(
+    base::StringPiece data,
+    const feedui::LoggingParameters& logging_parameters) {
+  // TODO(crbug.com/1268575): Thread logging parameters to UploadActionTask when
+  // it's always available.
+  ProcessThereAndBackAgain(data);
+}
+
 void FeedStream::ProcessViewAction(base::StringPiece data) {
   if (!CanLogViews()) {
     return;
@@ -669,6 +677,14 @@
                               base::Unretained(this)));
 }
 
+void FeedStream::ProcessViewAction(
+    base::StringPiece data,
+    const feedui::LoggingParameters& logging_parameters) {
+  // TODO(crbug.com/1268575): Thread logging parameters to UploadActionTask when
+  // it's always available.
+  ProcessViewAction(data);
+}
+
 void FeedStream::UploadActionsComplete(UploadActionsTask::Result result) {
   PopulateDebugStreamData(result, *profile_prefs_);
 }
diff --git a/components/feed/core/v2/feed_stream.h b/components/feed/core/v2/feed_stream.h
index 23e48f36..88d9309e 100644
--- a/components/feed/core/v2/feed_stream.h
+++ b/components/feed/core/v2/feed_stream.h
@@ -133,7 +133,13 @@
   bool RejectEphemeralChange(const StreamType& stream_type,
                              EphemeralChangeId id) override;
   void ProcessThereAndBackAgain(base::StringPiece data) override;
+  void ProcessThereAndBackAgain(
+      base::StringPiece data,
+      const feedui::LoggingParameters& logging_parameters) override;
   void ProcessViewAction(base::StringPiece data) override;
+  void ProcessViewAction(
+      base::StringPiece data,
+      const feedui::LoggingParameters& logging_parameters) override;
   bool WasUrlRecentlyNavigatedFromFeed(const GURL& url) override;
   DebugStreamData GetDebugStreamData() override;
   void ForceRefreshForDebugging(const StreamType& stream_type) override;
diff --git a/components/feed/core/v2/public/feed_api.h b/components/feed/core/v2/public/feed_api.h
index 1a3fd38..a334aab4 100644
--- a/components/feed/core/v2/public/feed_api.h
+++ b/components/feed/core/v2/public/feed_api.h
@@ -22,6 +22,7 @@
 
 namespace feedui {
 class StreamUpdate;
+class LoggingParameters;
 }  // namespace feedui
 namespace feedstore {
 class DataOperation;
@@ -139,9 +140,16 @@
   // Sends 'ThereAndBackAgainData' back to the server. |data| is a serialized
   // |feedwire::ThereAndBackAgainData| message.
   virtual void ProcessThereAndBackAgain(base::StringPiece data) = 0;
+  virtual void ProcessThereAndBackAgain(
+      base::StringPiece data,
+      const feedui::LoggingParameters& logging_parameters) = 0;
   // Saves a view action for eventual upload. |data| is a serialized
-  //|feedwire::FeedAction| message.
+  //|feedwire::FeedAction| message. `logging_parameters` are the logging
+  // parameters associated with this item, see `feedui::StreamUpdate`.
   virtual void ProcessViewAction(base::StringPiece data) = 0;
+  virtual void ProcessViewAction(
+      base::StringPiece data,
+      const feedui::LoggingParameters& logging_parameters) = 0;
 
   // Returns whether `url` is a suggested Feed URLs, recently
   // navigated to by the user.
diff --git a/components/feed/core/v2/public/test/stub_feed_api.h b/components/feed/core/v2/public/test/stub_feed_api.h
index bbf21a3..16abc85 100644
--- a/components/feed/core/v2/public/test/stub_feed_api.h
+++ b/components/feed/core/v2/public/test/stub_feed_api.h
@@ -64,7 +64,13 @@
   bool RejectEphemeralChange(const StreamType& stream_type,
                              EphemeralChangeId id) override;
   void ProcessThereAndBackAgain(base::StringPiece data) override {}
+  void ProcessThereAndBackAgain(
+      base::StringPiece data,
+      const feedui::LoggingParameters& logging_parameters) override {}
   void ProcessViewAction(base::StringPiece data) override {}
+  void ProcessViewAction(
+      base::StringPiece data,
+      const feedui::LoggingParameters& logging_parameters) override {}
   bool WasUrlRecentlyNavigatedFromFeed(const GURL& url) override;
   void ReportSliceViewed(SurfaceId surface_id,
                          const StreamType& stream_type,
diff --git a/components/feed/core/v2/surface_updater.cc b/components/feed/core/v2/surface_updater.cc
index b63d4511..1a60ffcc 100644
--- a/components/feed/core/v2/surface_updater.cc
+++ b/components/feed/core/v2/surface_updater.cc
@@ -139,16 +139,8 @@
         model->GetLastAddedTime().ToDeltaSinceWindowsEpoch().InMilliseconds());
   }
 
-  auto& proto_logging_params =
-      *update.stream_update.mutable_logging_parameters();
-  if (!logging_parameters.email.empty()) {
-    proto_logging_params.set_email(logging_parameters.email);
-  }
-  if (!logging_parameters.session_id.empty()) {
-    proto_logging_params.set_session_id(logging_parameters.session_id);
-  }
-  proto_logging_params.set_client_instance_id(
-      logging_parameters.client_instance_id);
+  ToProto(logging_parameters,
+          *update.stream_update.mutable_logging_parameters());
 
   return update;
 }
diff --git a/components/feed/core/v2/types.cc b/components/feed/core/v2/types.cc
index 5673c43..3785d2ca 100644
--- a/components/feed/core/v2/types.cc
+++ b/components/feed/core/v2/types.cc
@@ -13,6 +13,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
+#include "components/feed/core/proto/v2/ui.pb.h"
 #include "components/feed/core/v2/public/types.h"
 
 // Note: This file contains implementation for both types.h and public/types.h.
@@ -224,8 +225,27 @@
 LaunchResult& LaunchResult::operator=(const LaunchResult& other) = default;
 
 bool LoggingParameters::operator==(const LoggingParameters& rhs) const {
-  return std::tie(email, session_id, client_instance_id) ==
-         std::tie(rhs.email, rhs.session_id, rhs.client_instance_id);
+  return std::tie(email, client_instance_id, logging_enabled,
+                  view_actions_enabled) ==
+         std::tie(rhs.email, rhs.client_instance_id, logging_enabled,
+                  view_actions_enabled);
+}
+
+LoggingParameters FromProto(const feedui::LoggingParameters& proto) {
+  LoggingParameters result;
+  result.email = proto.email();
+  result.client_instance_id = proto.client_instance_id();
+  result.logging_enabled = proto.logging_enabled();
+  result.view_actions_enabled = proto.view_actions_enabled();
+  return result;
+}
+
+void ToProto(const LoggingParameters& logging_parameters,
+             feedui::LoggingParameters& proto) {
+  proto.set_email(logging_parameters.email);
+  proto.set_client_instance_id(logging_parameters.client_instance_id);
+  proto.set_logging_enabled(logging_parameters.logging_enabled);
+  proto.set_view_actions_enabled(logging_parameters.view_actions_enabled);
 }
 
 }  // namespace feed
diff --git a/components/feed/core/v2/types.h b/components/feed/core/v2/types.h
index b69d5e3..2abcba4d 100644
--- a/components/feed/core/v2/types.h
+++ b/components/feed/core/v2/types.h
@@ -19,6 +19,9 @@
 #include "components/feed/core/v2/public/common_enums.h"
 #include "components/feed/core/v2/public/types.h"
 
+namespace feedui {
+class LoggingParameters;
+}
 namespace feed {
 
 // Make sure public types are included here too.
@@ -147,17 +150,22 @@
 };
 
 struct LoggingParameters {
-  // User ID. Either `email` or `session_id`. If both are empty, activity
-  // logging is not  enabled.
+  // User ID, if the user is signed-in.
   std::string email;
-  std::string session_id;
-
   // A unique ID for this client. Used for reliability logging.
   std::string client_instance_id;
+  // Whether attention / interaction logging is enabled.
+  bool logging_enabled = false;
+  // Whether view actions may be recorded.
+  bool view_actions_enabled = false;
 
   bool operator==(const LoggingParameters& rhs) const;
 };
 
+LoggingParameters FromProto(const feedui::LoggingParameters& proto);
+void ToProto(const LoggingParameters& logging_parameters,
+             feedui::LoggingParameters& proto);
+
 }  // namespace feed
 
 #endif  // COMPONENTS_FEED_CORE_V2_TYPES_H_
diff --git a/components/feed/core/v2/types_unittest.cc b/components/feed/core/v2/types_unittest.cc
index 08907c26..9c8ef7e 100644
--- a/components/feed/core/v2/types_unittest.cc
+++ b/components/feed/core/v2/types_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/feed/core/v2/types.h"
 #include "base/json/json_writer.h"
 #include "base/strings/string_util.h"
+#include "components/feed/core/proto/v2/ui.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace feed {
@@ -61,4 +62,34 @@
   EXPECT_TRUE(ContentIdSet().IsEmpty());
 }
 
+TEST(Types, LoggingParametersSet_ToFromProto) {
+  LoggingParameters params;
+  params.email = "foo@bar.com";
+  params.client_instance_id = "instanceid";
+  params.logging_enabled = true;
+  params.view_actions_enabled = true;
+
+  feedui::LoggingParameters proto;
+  ToProto(params, proto);
+
+  EXPECT_EQ("foo@bar.com", proto.email());
+  EXPECT_EQ("instanceid", proto.client_instance_id());
+  EXPECT_EQ(true, proto.logging_enabled());
+  EXPECT_EQ(true, proto.view_actions_enabled());
+  EXPECT_EQ(params, FromProto(proto));
+}
+
+TEST(Types, LoggingParametersEmpty_ToFromProto) {
+  LoggingParameters params;
+
+  feedui::LoggingParameters proto;
+  ToProto(params, proto);
+
+  EXPECT_EQ("", proto.email());
+  EXPECT_EQ("", proto.client_instance_id());
+  EXPECT_EQ(false, proto.logging_enabled());
+  EXPECT_EQ(false, proto.view_actions_enabled());
+  EXPECT_EQ(params, FromProto(proto));
+}
+
 }  // namespace feed
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
index f362cab..45d5afa 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
@@ -823,6 +823,10 @@
 
   // Whether this visit contained a user-input search or query.
   bool is_search_visit = false;
+
+  // The site engagement score of the URL associated with this visit. This
+  // should not be used by the UI.
+  float engagement_score = 0.0;
 };
 
 // A cluster of `ClusterVisit`s with associated metadata (i.e. `keywords` and
diff --git a/components/history_clusters/core/BUILD.gn b/components/history_clusters/core/BUILD.gn
index 2629c0c..fbd45ff 100644
--- a/components/history_clusters/core/BUILD.gn
+++ b/components/history_clusters/core/BUILD.gn
@@ -43,6 +43,8 @@
       "content_annotations_cluster_processor.h",
       "content_visibility_cluster_finalizer.cc",
       "content_visibility_cluster_finalizer.h",
+      "noisy_cluster_finalizer.cc",
+      "noisy_cluster_finalizer.h",
       "on_device_clustering_backend.cc",
       "on_device_clustering_backend.h",
       "on_device_clustering_features.cc",
@@ -69,6 +71,7 @@
     "//components/pref_registry",
     "//components/query_parser",
     "//components/search_engines",
+    "//components/site_engagement/core",
     "//components/url_formatter",
     "//net",
     "//services/network/public/cpp",
@@ -90,6 +93,7 @@
       "clusterer_unittest.cc",
       "content_annotations_cluster_processor_unittest.cc",
       "content_visibility_cluster_finalizer_unittest.cc",
+      "noisy_cluster_finalizer_unittest.cc",
       "on_device_clustering_backend_unittest.cc",
       "on_device_clustering_util_unittest.cc",
       "ranking_cluster_finalizer_unittest.cc",
diff --git a/components/history_clusters/core/DEPS b/components/history_clusters/core/DEPS
index 010b5cdd..f15ad59 100644
--- a/components/history_clusters/core/DEPS
+++ b/components/history_clusters/core/DEPS
@@ -5,6 +5,7 @@
   "+components/pref_registry",
   "+components/query_parser",
   "+components/search_engines",
+  "+components/site_engagement/core",
   "+components/url_formatter",
   "+net",
   "+services/network/public/cpp",
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc
index 73af7ec7..c4cbaff 100644
--- a/components/history_clusters/core/history_clusters_service.cc
+++ b/components/history_clusters/core/history_clusters_service.cc
@@ -38,6 +38,7 @@
 #include "components/history_clusters/core/remote_clustering_backend.h"
 #include "components/optimization_guide/core/entity_metadata_provider.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/site_engagement/core/site_engagement_score_provider.h"
 #include "components/url_formatter/url_formatter.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/time_format.h"
@@ -285,7 +286,8 @@
     history::HistoryService* history_service,
     TemplateURLService* template_url_service,
     optimization_guide::EntityMetadataProvider* entity_metadata_provider,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    site_engagement::SiteEngagementScoreProvider* engagement_score_provider)
     : history_service_(history_service),
       visit_deletion_observer_(this),
       post_processing_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
@@ -297,7 +299,8 @@
 #if BUILDFLAG(BUILD_WITH_ON_DEVICE_CLUSTERING_BACKEND)
   if (kUseOnDeviceClusteringBackend.Get()) {
     backend_ = std::make_unique<OnDeviceClusteringBackend>(
-        template_url_service, entity_metadata_provider);
+        template_url_service, entity_metadata_provider,
+        engagement_score_provider);
   }
 #endif
 
diff --git a/components/history_clusters/core/history_clusters_service.h b/components/history_clusters/core/history_clusters_service.h
index 24c1da1..f186d5ae 100644
--- a/components/history_clusters/core/history_clusters_service.h
+++ b/components/history_clusters/core/history_clusters_service.h
@@ -35,6 +35,10 @@
 class EntityMetadataProvider;
 }  // namespace optimization_guide
 
+namespace site_engagement {
+class SiteEngagementScoreProvider;
+}  // namespace site_engagement
+
 namespace history_clusters {
 
 class HistoryClustersService;
@@ -83,7 +87,8 @@
       history::HistoryService* history_service,
       TemplateURLService* template_url_service,
       optimization_guide::EntityMetadataProvider* entity_metadata_provider,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      site_engagement::SiteEngagementScoreProvider* engagement_score_provider);
   HistoryClustersService(const HistoryClustersService&) = delete;
   HistoryClustersService& operator=(const HistoryClustersService&) = delete;
   ~HistoryClustersService() override;
diff --git a/components/history_clusters/core/history_clusters_service_unittest.cc b/components/history_clusters/core/history_clusters_service_unittest.cc
index 1ba1ffca..0d700937 100644
--- a/components/history_clusters/core/history_clusters_service_unittest.cc
+++ b/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -103,6 +103,7 @@
     history_clusters_service_ = std::make_unique<HistoryClustersService>(
         history_service_.get(), /*template_url_service=*/nullptr,
         /*entity_metadata_provider=*/nullptr,
+        /*engagement_score_provider=*/nullptr,
         /*url_loader_factory=*/nullptr);
 
     history_clusters_service_test_api_ =
diff --git a/components/history_clusters/core/noisy_cluster_finalizer.cc b/components/history_clusters/core/noisy_cluster_finalizer.cc
new file mode 100644
index 0000000..ff5b8ef
--- /dev/null
+++ b/components/history_clusters/core/noisy_cluster_finalizer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/history_clusters/core/noisy_cluster_finalizer.h"
+
+#include "components/history_clusters/core/on_device_clustering_features.h"
+#include "components/history_clusters/core/on_device_clustering_util.h"
+
+namespace history_clusters {
+
+NoisyClusterFinalizer::NoisyClusterFinalizer() = default;
+NoisyClusterFinalizer::~NoisyClusterFinalizer() = default;
+
+void NoisyClusterFinalizer::FinalizeCluster(history::Cluster& cluster) {
+  size_t interesting_visit_cnt = 0;
+  for (const auto& visit : cluster.visits) {
+    if (visit.engagement_score <
+        features::NoisyClusterVisitEngagementThreshold()) {
+      interesting_visit_cnt += 1;
+    }
+    if (interesting_visit_cnt >=
+        features::NumberInterestingVisitsFilterThreshold()) {
+      return;
+    }
+  }
+
+  // If we check all the visits in the cluster and all have high engagement
+  // scores, then its probably not interesting so we can hide it.
+  cluster.should_show_on_prominent_ui_surfaces = false;
+}
+
+}  // namespace history_clusters
diff --git a/components/history_clusters/core/noisy_cluster_finalizer.h b/components/history_clusters/core/noisy_cluster_finalizer.h
new file mode 100644
index 0000000..bb45e17
--- /dev/null
+++ b/components/history_clusters/core/noisy_cluster_finalizer.h
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_NOISY_CLUSTER_FINALIZER_H_
+#define COMPONENTS_HISTORY_CLUSTERS_CORE_NOISY_CLUSTER_FINALIZER_H_
+
+#include "components/history_clusters/core/cluster_finalizer.h"
+
+namespace history_clusters {
+
+// A cluster finalizer that finalizes single visit clusters by not showing them.
+class NoisyClusterFinalizer : public ClusterFinalizer {
+ public:
+  NoisyClusterFinalizer();
+  ~NoisyClusterFinalizer() override;
+
+  // ClusterFinalizer:
+  void FinalizeCluster(history::Cluster& cluster) override;
+};
+
+}  // namespace history_clusters
+
+#endif  // COMPONENTS_HISTORY_CLUSTERS_CORE_NOISY_CLUSTER_FINALIZER_H_
diff --git a/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc b/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc
new file mode 100644
index 0000000..c0a387c2e
--- /dev/null
+++ b/components/history_clusters/core/noisy_cluster_finalizer_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/history_clusters/core/noisy_cluster_finalizer.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/history_clusters/core/clustering_test_utils.h"
+#include "components/history_clusters/core/on_device_clustering_features.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace history_clusters {
+namespace {
+
+using ::testing::ElementsAre;
+
+class NoisyClusterFinalizerTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    cluster_finalizer_ = std::make_unique<NoisyClusterFinalizer>();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        features::kOnDeviceClustering,
+        {{"num_interesting_visits_filter_threshold", "2"}});
+  }
+
+  void TearDown() override { cluster_finalizer_.reset(); }
+
+  void FinalizeCluster(history::Cluster& cluster) {
+    cluster_finalizer_->FinalizeCluster(cluster);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  std::unique_ptr<NoisyClusterFinalizer> cluster_finalizer_;
+  base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(NoisyClusterFinalizerTest, FilterHighEngagementClusters) {
+  history::ClusterVisit visit = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(1, GURL("https://bar.com/")));
+  visit.engagement_score = 25.0;
+
+  history::ClusterVisit visit2 = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
+  visit2.duplicate_visit_ids.push_back(1);
+  visit2.engagement_score = 25.0;
+
+  history::Cluster cluster;
+  cluster.visits = {visit, visit2};
+  FinalizeCluster(cluster);
+  EXPECT_FALSE(cluster.should_show_on_prominent_ui_surfaces);
+}
+
+TEST_F(NoisyClusterFinalizerTest, HideClusterWithOnlyOneInterestingVisit) {
+  history::ClusterVisit visit = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(1, GURL("https://bar.com/")));
+  visit.engagement_score = 5.0;
+
+  history::ClusterVisit visit2 = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
+  visit2.duplicate_visit_ids.push_back(1);
+  visit2.engagement_score = 25.0;
+
+  history::Cluster cluster;
+  cluster.visits = {visit, visit2};
+  FinalizeCluster(cluster);
+  EXPECT_FALSE(cluster.should_show_on_prominent_ui_surfaces);
+}
+
+TEST_F(NoisyClusterFinalizerTest, KeepClusterWitihAtLeastTwoInterestingVisits) {
+  history::ClusterVisit visit = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(1, GURL("https://bar.com/")));
+  visit.engagement_score = 5.0;
+
+  history::ClusterVisit visit2 = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(2, GURL("https://bar.com/")));
+  visit2.duplicate_visit_ids.push_back(1);
+  visit2.engagement_score = 25.0;
+
+  history::ClusterVisit visit3 = testing::CreateClusterVisit(
+      testing::CreateDefaultAnnotatedVisit(3, GURL("https://foo.com/")));
+  visit3.engagement_score = 5.0;
+
+  history::Cluster cluster;
+  cluster.visits = {visit, visit2, visit3};
+  FinalizeCluster(cluster);
+  EXPECT_TRUE(cluster.should_show_on_prominent_ui_surfaces);
+}
+
+}  // namespace
+}  // namespace history_clusters
diff --git a/components/history_clusters/core/on_device_clustering_backend.cc b/components/history_clusters/core/on_device_clustering_backend.cc
index 0da9a9c2..be9d21d23 100644
--- a/components/history_clusters/core/on_device_clustering_backend.cc
+++ b/components/history_clusters/core/on_device_clustering_backend.cc
@@ -18,6 +18,7 @@
 #include "components/history/core/browser/history_types.h"
 #include "components/history_clusters/core/content_annotations_cluster_processor.h"
 #include "components/history_clusters/core/content_visibility_cluster_finalizer.h"
+#include "components/history_clusters/core/noisy_cluster_finalizer.h"
 #include "components/history_clusters/core/on_device_clustering_features.h"
 #include "components/history_clusters/core/ranking_cluster_finalizer.h"
 #include "components/history_clusters/core/similar_visit_deduper_cluster_finalizer.h"
@@ -26,6 +27,7 @@
 #include "components/optimization_guide/core/batch_entity_metadata_task.h"
 #include "components/optimization_guide/core/entity_metadata_provider.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/site_engagement/core/site_engagement_score_provider.h"
 
 namespace history_clusters {
 
@@ -68,9 +70,11 @@
 
 OnDeviceClusteringBackend::OnDeviceClusteringBackend(
     TemplateURLService* template_url_service,
-    optimization_guide::EntityMetadataProvider* entity_metadata_provider)
+    optimization_guide::EntityMetadataProvider* entity_metadata_provider,
+    site_engagement::SiteEngagementScoreProvider* engagement_score_provider)
     : template_url_service_(template_url_service),
       entity_metadata_provider_(entity_metadata_provider),
+      engagement_score_provider_(engagement_score_provider),
       background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
           {base::MayBlock(), base::TaskPriority::USER_VISIBLE})) {}
 
@@ -158,6 +162,11 @@
     cluster_visit.normalized_url =
         maybe_normalized_url.value_or(visit.url_row.url());
 
+    if (engagement_score_provider_) {
+      cluster_visit.engagement_score =
+          engagement_score_provider_->GetScore(visit.url_row.url());
+    }
+
     // Rewrite the entities for the visit, but only if it is possible that we
     // had additional metadata for it.
     if (entity_metadata_provider_) {
@@ -258,6 +267,10 @@
     cluster_finalizers.push_back(
         std::make_unique<SingleVisitClusterFinalizer>());
   }
+  // Add feature to turn on/off site engagement score filter.
+  if (engagement_score_provider_ && features::ShouldFilterNoisyClusters()) {
+    cluster_finalizers.push_back(std::make_unique<NoisyClusterFinalizer>());
+  }
 
   // Group visits into clusters.
   std::vector<history::Cluster> clusters =
diff --git a/components/history_clusters/core/on_device_clustering_backend.h b/components/history_clusters/core/on_device_clustering_backend.h
index dbb866a..1775b8f 100644
--- a/components/history_clusters/core/on_device_clustering_backend.h
+++ b/components/history_clusters/core/on_device_clustering_backend.h
@@ -25,6 +25,10 @@
 class EntityMetadataProvider;
 }  // namespace optimization_guide
 
+namespace site_engagement {
+class SiteEngagementScoreProvider;
+}  // namespace site_engagement
+
 namespace history_clusters {
 
 // A clustering backend that clusters visits on device.
@@ -32,7 +36,8 @@
  public:
   OnDeviceClusteringBackend(
       TemplateURLService* template_url_service,
-      optimization_guide::EntityMetadataProvider* entity_metadata_provider);
+      optimization_guide::EntityMetadataProvider* entity_metadata_provider,
+      site_engagement::SiteEngagementScoreProvider* engagement_score_provider);
   ~OnDeviceClusteringBackend() override;
 
   // ClusteringBackend:
@@ -61,6 +66,9 @@
   // The object to fetch entity metadata from. Not owned. Must outlive |this|.
   optimization_guide::EntityMetadataProvider* entity_metadata_provider_;
 
+  // The object to get engagement scores from. Not owned. Must outlive |this|.
+  site_engagement::SiteEngagementScoreProvider* engagement_score_provider_;
+
   // The set of batch entity metadata tasks currently in flight.
   base::flat_set<std::unique_ptr<optimization_guide::BatchEntityMetadataTask>,
                  base::UniquePtrComparator>
diff --git a/components/history_clusters/core/on_device_clustering_backend_unittest.cc b/components/history_clusters/core/on_device_clustering_backend_unittest.cc
index 8170e323..5458c75 100644
--- a/components/history_clusters/core/on_device_clustering_backend_unittest.cc
+++ b/components/history_clusters/core/on_device_clustering_backend_unittest.cc
@@ -77,7 +77,8 @@
 
   void SetUp() override {
     clustering_backend_ = std::make_unique<OnDeviceClusteringBackend>(
-        /*template_url_service=*/nullptr, /*entity_metadata_provider=*/nullptr);
+        /*template_url_service=*/nullptr, /*entity_metadata_provider=*/nullptr,
+        /*engagement_score_provider=*/nullptr);
   }
 
   void TearDown() override { clustering_backend_.reset(); }
@@ -484,7 +485,8 @@
         task_environment_.GetMainThreadTaskRunner());
 
     clustering_backend_ = std::make_unique<OnDeviceClusteringBackend>(
-        template_url_service_.get(), entity_metadata_provider_.get());
+        template_url_service_.get(), entity_metadata_provider_.get(),
+        /*engagement_score_provider=*/nullptr);
   }
 
  private:
diff --git a/components/history_clusters/core/on_device_clustering_features.cc b/components/history_clusters/core/on_device_clustering_features.cc
index 615d515b..06eca91 100644
--- a/components/history_clusters/core/on_device_clustering_features.cc
+++ b/components/history_clusters/core/on_device_clustering_features.cc
@@ -73,6 +73,23 @@
                                            "dedupe_similar_visits", true);
 }
 
+bool ShouldFilterNoisyClusters() {
+  return GetFieldTrialParamByFeatureAsBool(kOnDeviceClustering,
+                                           "filter_noisy_clusters", true);
+}
+
+float NoisyClusterVisitEngagementThreshold() {
+  float threshold = GetFieldTrialParamByFeatureAsDouble(
+      kOnDeviceClustering, "noisy_cluster_visit_engagement_threshold", 15.0);
+  return threshold;
+}
+
+size_t NumberInterestingVisitsFilterThreshold() {
+  int threshold = GetFieldTrialParamByFeatureAsInt(
+      kOnDeviceClustering, "num_interesting_visits_filter_threshold", 1);
+  return threshold;
+}
+
 float VisitDurationRankingWeight() {
   float weight = GetFieldTrialParamByFeatureAsDouble(
       kOnDeviceClustering, "visit_duration_ranking_weight", 1.0);
diff --git a/components/history_clusters/core/on_device_clustering_features.h b/components/history_clusters/core/on_device_clustering_features.h
index 6d075bb..7b26403 100644
--- a/components/history_clusters/core/on_device_clustering_features.h
+++ b/components/history_clusters/core/on_device_clustering_features.h
@@ -52,6 +52,19 @@
 // same way.
 bool ShouldDedupeSimilarVisits();
 
+// Whether to filter clusters that are noisy from the UI. This will
+// heuristically remove clusters that are unlikely to be "interesting".
+bool ShouldFilterNoisyClusters();
+
+// Returns the threshold used to determine if a cluster, and its visits, has
+// too high site engagement to be likely useful.
+float NoisyClusterVisitEngagementThreshold();
+
+// Returns the number of visits considered interesting, or not noisy, required
+// to prevent the cluster from being filtered out (i.e., marked as not visible
+// on the zero state UI).
+size_t NumberInterestingVisitsFilterThreshold();
+
 // Returns the weight to use for the visit duration when ranking visits within a
 // cluster. Will always be greater than or equal to 0.
 float VisitDurationRankingWeight();
diff --git a/components/language/android/BUILD.gn b/components/language/android/BUILD.gn
index e2c50612..d3a6191b 100644
--- a/components/language/android/BUILD.gn
+++ b/components/language/android/BUILD.gn
@@ -24,27 +24,47 @@
   ]
 }
 
-android_library("language_bridge_java") {
+android_library("java") {
   sources = [
     "java/src/org/chromium/components/language/AndroidLanguageMetricsBridge.java",
     "java/src/org/chromium/components/language/GeoLanguageProviderBridge.java",
-    "java/src/org/chromium/components/language/LanguageProfileDelegate.java",
-    "java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java",
   ]
 
   deps = [
     "//base:base_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
+
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
-android_library("language_bridge_javatests") {
+android_library("ulp_delegate_java") {
+  sources = [
+    "java/src/org/chromium/components/language/LanguageProfileDelegate.java",
+    "java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java",
+  ]
+
+  deps = [ "//base:base_java" ]
+
+  # Allow downstream targets to provide their own implementations.
+  jar_excluded_patterns = [ "*/LanguageProfileDelegateImpl.class" ]
+}
+
+android_library("ulp_delegate_public_java") {
+  sources = [ "java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java" ]
+
+  deps = [
+    ":ulp_delegate_java",
+    "//base:base_java",
+  ]
+}
+
+android_library("javatests") {
   testonly = true
 
   sources = [ "java/src/org/chromium/components/language/AndroidLanguageMetricsBridgeTest.java" ]
   deps = [
-    ":language_bridge_java",
+    ":java",
     "//base:base_java",
     "//base:base_java_test_support",
     "//chrome/browser/flags:java",
diff --git a/components/language/android/java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java b/components/language/android/java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java
index 5cda336a..e716370 100644
--- a/components/language/android/java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java
+++ b/components/language/android/java/src/org/chromium/components/language/LanguageProfileDelegateImpl.java
@@ -8,7 +8,7 @@
 import java.util.List;
 
 /**
- * Interface to get ULP data from GSM Core.
+ * Default implementation of language profile delegate.
  */
 public class LanguageProfileDelegateImpl implements LanguageProfileDelegate {
     /**
diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc
index 0c97d8c..924d679 100644
--- a/components/omnibox/browser/autocomplete_input.cc
+++ b/components/omnibox/browser/autocomplete_input.cc
@@ -264,8 +264,6 @@
     // become inaccessible (e.g. the flags page which allows to disable Lacros).
     // The os:// scheme is able to forward a keyed set of pages to Ash, hence
     // making them accessible again.
-    // TODO(crbug/1269355): Treat all os:// input as valid destination and add
-    // 404 handler if Ash does not handle the request.
     return metrics::OmniboxInputType::URL;
   }
 #endif
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc
index c62a620..05c497c 100644
--- a/components/page_info/page_info.cc
+++ b/components/page_info/page_info.cc
@@ -690,13 +690,8 @@
   // Identity section.
   certificate_ = visible_security_state.certificate;
 
-  // TODO(crbug.com/1044747): This conditional special-cases
-  // CERT_STATUS_LEGACY_TLS to avoid marking the certificate as "Invalid" in
-  // Page Info, but once we clean up the overloading of CertStatus for Legacy
-  // TLS we can remove this.
   if (certificate_ &&
-      (!net::IsCertStatusError(visible_security_state.cert_status &
-                               ~net::CERT_STATUS_LEGACY_TLS))) {
+      (!net::IsCertStatusError(visible_security_state.cert_status))) {
     // HTTPS with no or minor errors.
     if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -854,10 +849,6 @@
           subject_name));
     }
 
-    if (visible_security_state.cert_status & net::CERT_STATUS_LEGACY_TLS) {
-      site_connection_status_ = SITE_CONNECTION_STATUS_LEGACY_TLS;
-    }
-
     ReportAnyInsecureContent(visible_security_state, &site_connection_status_,
                              &site_connection_details_);
   }
diff --git a/components/page_info/page_info.h b/components/page_info/page_info.h
index b75ddbe..c0effa2b 100644
--- a/components/page_info/page_info.h
+++ b/components/page_info/page_info.h
@@ -57,7 +57,6 @@
     SITE_CONNECTION_STATUS_UNENCRYPTED,      // Connection is not encrypted.
     SITE_CONNECTION_STATUS_ENCRYPTED_ERROR,  // Connection error occurred.
     SITE_CONNECTION_STATUS_INTERNAL_PAGE,    // Internal site.
-    SITE_CONNECTION_STATUS_LEGACY_TLS,  // Connection used a legacy TLS version.
   };
 
   // Validation status of a website's identity.
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc
index 7aacf8f..088d88f 100644
--- a/components/page_info/page_info_ui.cc
+++ b/components/page_info/page_info_ui.cc
@@ -479,12 +479,6 @@
               IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT,
               IDS_PAGE_INFO_MIXED_CONTENT_DETAILS,
               SecurityDescriptionType::CONNECTION);
-        case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
-          return CreateSecurityDescription(
-              SecuritySummaryColor::RED,
-              IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT,
-              IDS_PAGE_INFO_LEGACY_TLS_DETAILS,
-              SecurityDescriptionType::CONNECTION);
         default:
           // Do not show details for secure connections.
           return CreateSecurityDescription(SecuritySummaryColor::GREEN,
@@ -524,11 +518,6 @@
                                            IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
                                            IDS_PAGE_INFO_MIXED_CONTENT_DETAILS,
                                            SecurityDescriptionType::CONNECTION);
-        case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
-          return CreateSecurityDescription(SecuritySummaryColor::RED,
-                                           IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
-                                           IDS_PAGE_INFO_LEGACY_TLS_DETAILS,
-                                           SecurityDescriptionType::CONNECTION);
         default:
 
           auto description = CreateSecurityDescription(
@@ -925,7 +914,6 @@
       return IDR_PAGEINFO_GOOD;
     case PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE:
     case PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION:
-    case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
     case PageInfo::SITE_CONNECTION_STATUS_UNENCRYPTED:
     case PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE:
     case PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR:
@@ -961,7 +949,6 @@
       return IDR_PAGEINFO_GOOD_COLOR;
     case PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE:
     case PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION:
-    case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
     case PageInfo::SITE_CONNECTION_STATUS_UNENCRYPTED:
       return IDR_PAGEINFO_WARNING_COLOR;
     case PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE:
diff --git a/components/policy/test_support/bootstrap_deps b/components/policy/test_support/bootstrap_deps
index c9dacaa..09d9245 100644
--- a/components/policy/test_support/bootstrap_deps
+++ b/components/policy/test_support/bootstrap_deps
@@ -7,8 +7,6 @@
         "https://src.chromium.org/chrome/trunk/src/components/policy/test_support",
     "src/net/tools/testserver":
         "https://src.chromium.org/chrome/trunk/src/net/tools/testserver",
-    "src/third_party/tlslite/tlslite":
-        "https://src.chromium.org/chrome/trunk/src/third_party/tlslite/tlslite",
     "src/third_party/protobuf/python/google":
         "https://src.chromium.org/chrome/trunk/src/third_party/protobuf/python/google",
     "src/tools/telemetry":
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc
index 6cea186..f74c4c6 100644
--- a/components/safe_browsing/core/common/features.cc
+++ b/components/safe_browsing/core/common/features.cc
@@ -114,7 +114,7 @@
 
 const base::Feature kRealTimeUrlLookupReferrerChainForEnterprise{
     "SafeBrowsingRealTimeUrlLookupReferrerChainForEnterprise",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kSafeBrowsingPageLoadToken{
     "SafeBrowsingPageLoadToken", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/security_interstitials/content/BUILD.gn b/components/security_interstitials/content/BUILD.gn
index 7dd2cb58..2f66e25f 100644
--- a/components/security_interstitials/content/BUILD.gn
+++ b/components/security_interstitials/content/BUILD.gn
@@ -33,8 +33,6 @@
     "insecure_form_tab_storage.h",
     "known_interception_disclosure_ui.cc",
     "known_interception_disclosure_ui.h",
-    "legacy_tls_blocking_page.cc",
-    "legacy_tls_blocking_page.h",
     "mitm_software_blocking_page.cc",
     "mitm_software_blocking_page.h",
     "origin_policy_interstitial_page.cc",
diff --git a/components/security_interstitials/content/legacy_tls_blocking_page.cc b/components/security_interstitials/content/legacy_tls_blocking_page.cc
deleted file mode 100644
index d866bbf..0000000
--- a/components/security_interstitials/content/legacy_tls_blocking_page.cc
+++ /dev/null
@@ -1,91 +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.
-
-#include "components/security_interstitials/content/legacy_tls_blocking_page.h"
-
-#include "components/security_interstitials/content/cert_report_helper.h"
-#include "components/security_interstitials/content/security_interstitial_controller_client.h"
-#include "components/security_interstitials/content/security_interstitial_page.h"
-#include "components/security_interstitials/content/ssl_cert_reporter.h"
-#include "components/security_interstitials/core/metrics_helper.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/ssl_status.h"
-#include "content/public/browser/web_contents.h"
-#include "net/base/net_errors.h"
-
-using content::NavigationController;
-using content::NavigationEntry;
-
-// static
-const security_interstitials::SecurityInterstitialPage::TypeID
-    LegacyTLSBlockingPage::kTypeForTesting =
-        &LegacyTLSBlockingPage::kTypeForTesting;
-
-// Note that we always create a navigation entry with SSL errors.
-// No error happening loading a sub-resource triggers an interstitial so far.
-// Creating an interstitial without showing (e.g. from chrome://interstitials)
-// it leaks memory, so don't create it here.
-LegacyTLSBlockingPage::LegacyTLSBlockingPage(
-    content::WebContents* web_contents,
-    int cert_error,
-    const GURL& request_url,
-    std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    bool can_show_enhanced_protection_message,
-    const net::SSLInfo& ssl_info,
-    std::unique_ptr<
-        security_interstitials::SecurityInterstitialControllerClient>
-        controller_client)
-    : SSLBlockingPageBase(web_contents,
-                          CertificateErrorReport::INTERSTITIAL_LEGACY_TLS,
-                          ssl_info,
-                          request_url,
-                          std::move(ssl_cert_reporter),
-                          true /* overridable */,
-                          base::Time::Now(),
-                          can_show_enhanced_protection_message,
-                          std::move(controller_client)),
-      ssl_info_(ssl_info),
-      legacy_tls_ui_(new security_interstitials::LegacyTLSUI(request_url,
-                                                             cert_error,
-                                                             ssl_info,
-                                                             controller())) {}
-
-LegacyTLSBlockingPage::~LegacyTLSBlockingPage() = default;
-
-security_interstitials::SecurityInterstitialPage::TypeID
-LegacyTLSBlockingPage::GetTypeForTesting() {
-  return LegacyTLSBlockingPage::kTypeForTesting;
-}
-
-void LegacyTLSBlockingPage::PopulateInterstitialStrings(
-    base::Value* load_time_data) {
-  legacy_tls_ui_->PopulateStringsForHTML(load_time_data);
-  cert_report_helper()->PopulateExtendedReportingOption(load_time_data);
-  cert_report_helper()->PopulateEnhancedProtectionMessage(load_time_data);
-}
-
-// This handles the commands sent from the interstitial JavaScript.
-void LegacyTLSBlockingPage::CommandReceived(const std::string& command) {
-  if (command == "\"pageLoadComplete\"") {
-    // content::WaitForRenderFrameReady sends this message when the page
-    // load completes. Ignore it.
-    return;
-  }
-
-  int cmd = 0;
-  bool retval = base::StringToInt(command, &cmd);
-  DCHECK(retval);
-
-  // Let the CertReportHelper handle commands first, This allows it to get set
-  // up to send reports, so that the report is populated properly if
-  // LegacyTLSUI's command handling triggers a report to be sent.
-  cert_report_helper()->HandleReportingCommands(
-      static_cast<security_interstitials::SecurityInterstitialCommand>(cmd),
-      controller()->GetPrefService());
-  legacy_tls_ui_->HandleCommand(
-      static_cast<security_interstitials::SecurityInterstitialCommand>(cmd));
-}
diff --git a/components/security_interstitials/content/legacy_tls_blocking_page.h b/components/security_interstitials/content/legacy_tls_blocking_page.h
deleted file mode 100644
index 365df655..0000000
--- a/components/security_interstitials/content/legacy_tls_blocking_page.h
+++ /dev/null
@@ -1,53 +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_SECURITY_INTERSTITIALS_CONTENT_LEGACY_TLS_BLOCKING_PAGE_H_
-#define COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_LEGACY_TLS_BLOCKING_PAGE_H_
-
-#include "components/security_interstitials/content/ssl_blocking_page_base.h"
-#include "components/security_interstitials/content/ssl_cert_reporter.h"
-#include "components/security_interstitials/core/legacy_tls_ui.h"
-#include "net/ssl/ssl_info.h"
-
-// This class is responsible for showing/hiding the interstitial page that is
-// shown then a connection uses an obsolete TLS version (i.e., TLS 1.0 or 1.1).
-// It deletes itself when the interstitial page is closed.
-class LegacyTLSBlockingPage : public SSLBlockingPageBase {
- public:
-  // Interstitial type, used in tests.
-  static const security_interstitials::SecurityInterstitialPage::TypeID
-      kTypeForTesting;
-
-  LegacyTLSBlockingPage(
-      content::WebContents* web_contents,
-      int cert_error,
-      const GURL& request_url,
-      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-      bool can_show_enhanced_protection_message,
-      const net::SSLInfo& ssl_info,
-      std::unique_ptr<
-          security_interstitials::SecurityInterstitialControllerClient>
-          controller_client);
-
-  LegacyTLSBlockingPage(const LegacyTLSBlockingPage&) = delete;
-  LegacyTLSBlockingPage& operator=(const LegacyTLSBlockingPage&) = delete;
-
-  ~LegacyTLSBlockingPage() override;
-
-  // SecurityInterstitialPage method:
-  security_interstitials::SecurityInterstitialPage::TypeID GetTypeForTesting()
-      override;
-
- protected:
-  // SecurityInterstitialPage implementation:
-  void CommandReceived(const std::string& command) override;
-  void PopulateInterstitialStrings(base::Value* load_time_data) override;
-
- private:
-  const net::SSLInfo ssl_info_;
-
-  const std::unique_ptr<security_interstitials::LegacyTLSUI> legacy_tls_ui_;
-};
-
-#endif  // COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_LEGACY_TLS_BLOCKING_PAGE_H_
diff --git a/components/security_interstitials/content/security_blocking_page_factory.h b/components/security_interstitials/content/security_blocking_page_factory.h
index 2c6cf60..8c8d42ff 100644
--- a/components/security_interstitials/content/security_blocking_page_factory.h
+++ b/components/security_interstitials/content/security_blocking_page_factory.h
@@ -13,7 +13,6 @@
 #include "components/security_interstitials/content/captive_portal_blocking_page.h"
 #include "components/security_interstitials/content/https_only_mode_blocking_page.h"
 #include "components/security_interstitials/content/insecure_form_blocking_page.h"
-#include "components/security_interstitials/content/legacy_tls_blocking_page.h"
 #include "components/security_interstitials/content/mitm_software_blocking_page.h"
 #include "components/security_interstitials/content/ssl_blocking_page.h"
 #include "components/security_interstitials/content/ssl_blocking_page_base.h"
@@ -62,14 +61,6 @@
       ssl_errors::ClockState clock_state,
       std::unique_ptr<SSLCertReporter> ssl_cert_reporter) = 0;
 
-  // Creates a legacy TLS blocking page.
-  virtual std::unique_ptr<LegacyTLSBlockingPage> CreateLegacyTLSBlockingPage(
-      content::WebContents* web_contents,
-      int cert_error,
-      const GURL& request_url,
-      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-      const net::SSLInfo& ssl_info) = 0;
-
   // Creates a man-in-the-middle software blocking page.
   virtual std::unique_ptr<MITMSoftwareBlockingPage>
   CreateMITMSoftwareBlockingPage(
diff --git a/components/security_interstitials/content/ssl_error_handler.cc b/components/security_interstitials/content/ssl_error_handler.cc
index a0f9ef2..7442884 100644
--- a/components/security_interstitials/content/ssl_error_handler.cc
+++ b/components/security_interstitials/content/ssl_error_handler.cc
@@ -26,7 +26,6 @@
 #include "components/security_interstitials/content/blocked_interception_blocking_page.h"
 #include "components/security_interstitials/content/captive_portal_blocking_page.h"
 #include "components/security_interstitials/content/captive_portal_helper.h"
-#include "components/security_interstitials/content/legacy_tls_blocking_page.h"
 #include "components/security_interstitials/content/mitm_software_blocking_page.h"
 #include "components/security_interstitials/content/security_blocking_page_factory.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
@@ -388,8 +387,6 @@
   void ShowBlockedInterceptionInterstitial() override;
   void ReportNetworkConnectivity(base::OnceClosure callback) override;
   bool HasBlockedInterception() const override;
-  void ShowLegacyTLSInterstitial() override;
-  bool HasLegacyTLS() const override;
 
  private:
   // Calls the |blocking_page_ready_callback_| if it's not null, else calls
@@ -509,13 +506,6 @@
           std::move(ssl_cert_reporter_), ssl_info_));
 }
 
-void SSLErrorHandlerDelegateImpl::ShowLegacyTLSInterstitial() {
-  // Show legacy TLS blocking page. The interstitial owns the blocking page.
-  OnBlockingPageReady(blocking_page_factory_->CreateLegacyTLSBlockingPage(
-      web_contents_, cert_error_, request_url_, std::move(ssl_cert_reporter_),
-      ssl_info_));
-}
-
 void SSLErrorHandlerDelegateImpl::ReportNetworkConnectivity(
     base::OnceClosure callback) {
 #if defined(OS_ANDROID)
@@ -533,11 +523,6 @@
          ssl_errors::ErrorInfo::CERT_KNOWN_INTERCEPTION_BLOCKED;
 }
 
-bool SSLErrorHandlerDelegateImpl::HasLegacyTLS() const {
-  return ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) ==
-         ssl_errors::ErrorInfo::LEGACY_TLS;
-}
-
 void SSLErrorHandlerDelegateImpl::OnBlockingPageReady(
     std::unique_ptr<security_interstitials::SecurityInterstitialPage>
         interstitial_page) {
@@ -684,12 +669,6 @@
     return ShowBlockedInterceptionInterstitial();
   }
 
-  // The legacy TLS interstitial is only shown if no other errors were found.
-  if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) ==
-      ssl_errors::ErrorInfo::LEGACY_TLS) {
-    return ShowLegacyTLSInterstitial();
-  }
-
   if (ssl_errors::ErrorInfo::NetErrorToErrorType(cert_error_) ==
       ssl_errors::ErrorInfo::CERT_DATE_INVALID) {
     HandleCertDateInvalidError();
@@ -888,15 +867,6 @@
   web_contents()->RemoveUserData(UserDataKey());
 }
 
-void SSLErrorHandler::ShowLegacyTLSInterstitial() {
-  // Show a blocking page. The interstitial owns the blocking page.
-  RecordUMA(SHOW_LEGACY_TLS_INTERSTITIAL);
-  delegate_->ShowLegacyTLSInterstitial();
-  // Once an interstitial is displayed, no need to keep the handler around.
-  // This is the equivalent of "delete this".
-  web_contents()->RemoveUserData(UserDataKey());
-}
-
 void SSLErrorHandler::CommonNameMismatchHandlerCallback(
     CommonNameMismatchHandler::SuggestedUrlCheckResult result,
     const GURL& suggested_url) {
diff --git a/components/security_interstitials/content/ssl_error_handler.h b/components/security_interstitials/content/ssl_error_handler.h
index b4e412b..36d6183 100644
--- a/components/security_interstitials/content/ssl_error_handler.h
+++ b/components/security_interstitials/content/ssl_error_handler.h
@@ -105,7 +105,7 @@
     SHOW_MITM_SOFTWARE_INTERSTITIAL = 11,
     OS_REPORTS_CAPTIVE_PORTAL = 12,
     SHOW_BLOCKED_INTERCEPTION_INTERSTITIAL = 13,
-    SHOW_LEGACY_TLS_INTERSTITIAL = 14,
+    SHOW_LEGACY_TLS_INTERSTITIAL = 14,  // Deprecated in M98.
     SSL_ERROR_HANDLER_EVENT_COUNT
   };
 
@@ -133,8 +133,6 @@
     virtual void ShowBlockedInterceptionInterstitial() = 0;
     virtual void ReportNetworkConnectivity(base::OnceClosure callback) = 0;
     virtual bool HasBlockedInterception() const = 0;
-    virtual void ShowLegacyTLSInterstitial() = 0;
-    virtual bool HasLegacyTLS() const = 0;
   };
 
   // Entry point for the class. Most parameters are the same as
@@ -222,7 +220,6 @@
                                 ssl_errors::ClockState clock_state);
   void ShowDynamicInterstitial(const DynamicInterstitialInfo interstitial);
   void ShowBlockedInterceptionInterstitial();
-  void ShowLegacyTLSInterstitial();
 
   // Gets the result of whether the suggested URL is valid. Displays
   // common name mismatch interstitial or ssl interstitial accordingly.
diff --git a/components/security_interstitials/content/ssl_error_handler_unittest.cc b/components/security_interstitials/content/ssl_error_handler_unittest.cc
index e47b324..9f1f913 100644
--- a/components/security_interstitials/content/ssl_error_handler_unittest.cc
+++ b/components/security_interstitials/content/ssl_error_handler_unittest.cc
@@ -163,8 +163,7 @@
         blocked_interception_interstitial_shown_(false),
         redirected_to_suggested_url_(false),
         is_overridable_error_(true),
-        has_blocked_interception_(false),
-        legacy_tls_interstitial_shown_(false) {}
+        has_blocked_interception_(false) {}
 
   TestSSLErrorHandlerDelegate(const TestSSLErrorHandlerDelegate&) = delete;
   TestSSLErrorHandlerDelegate& operator=(const TestSSLErrorHandlerDelegate&) =
@@ -194,15 +193,11 @@
   bool redirected_to_suggested_url() const {
     return redirected_to_suggested_url_;
   }
-  bool legacy_tls_interstitial_shown() const {
-    return legacy_tls_interstitial_shown_;
-  }
 
   void set_suggested_url_exists() { suggested_url_exists_ = true; }
   void set_non_overridable_error() { is_overridable_error_ = false; }
   void set_os_reports_captive_portal() { os_reports_captive_portal_ = true; }
   void set_has_blocked_interception() { has_blocked_interception_ = true; }
-  void set_has_legacy_tls() { has_legacy_tls_ = true; }
 
   void ClearSeenOperations() {
     captive_portal_checked_ = false;
@@ -215,8 +210,6 @@
     mitm_software_interstitial_shown_ = false;
     redirected_to_suggested_url_ = false;
     has_blocked_interception_ = false;
-    legacy_tls_interstitial_shown_ = false;
-    has_legacy_tls_ = false;
   }
 
  private:
@@ -256,10 +249,6 @@
     blocked_interception_interstitial_shown_ = true;
   }
 
-  void ShowLegacyTLSInterstitial() override {
-    legacy_tls_interstitial_shown_ = true;
-  }
-
   void CheckSuggestedUrl(
       const GURL& suggested_url,
       CommonNameMismatchHandler::CheckUrlCallback callback) override {
@@ -280,8 +269,6 @@
     return has_blocked_interception_;
   }
 
-  bool HasLegacyTLS() const override { return has_legacy_tls_; }
-
   bool captive_portal_checked_;
   bool os_reports_captive_portal_;
   bool suggested_url_exists_;
@@ -294,8 +281,6 @@
   bool redirected_to_suggested_url_;
   bool is_overridable_error_;
   bool has_blocked_interception_;
-  bool legacy_tls_interstitial_shown_;
-  bool has_legacy_tls_;
   CommonNameMismatchHandler::CheckUrlCallback suggested_url_callback_;
 };
 
@@ -1595,51 +1580,13 @@
       SSLErrorHandler::SHOW_BLOCKED_INTERCEPTION_INTERSTITIAL, 1);
 }
 
-// Tests that a legacy TLS interstitial is shown. This test mainly checks
-// histogram accuracy (see BlockedInterceptionInterstitial test above).
-TEST_F(SSLErrorHandlerTest, LegacyTLSInterstitial) {
-  net::SSLInfo ssl_info;
-  ssl_info.cert =
-      net::ImportCertFromFile(net::GetTestCertsDirectory(), kOkayCertName);
-  ssl_info.cert_status = net::CERT_STATUS_LEGACY_TLS;
-  ssl_info.public_key_hashes.push_back(net::HashValue(kCertPublicKeyHashValue));
-
-  std::unique_ptr<TestSSLErrorHandlerDelegate> delegate(
-      new TestSSLErrorHandlerDelegate(web_contents(), ssl_info));
-
-  TestSSLErrorHandlerDelegate* delegate_ptr = delegate.get();
-  TestSSLErrorHandler error_handler(
-      std::move(delegate), web_contents(),
-      net::MapCertStatusToNetError(ssl_info.cert_status), ssl_info,
-      /*network_time_tracker=*/nullptr, /*request_url=*/GURL(),
-      /*captive_portal_service=*/nullptr);
-
-  base::HistogramTester histograms;
-  delegate_ptr->set_has_legacy_tls();
-
-  EXPECT_FALSE(error_handler.IsTimerRunningForTesting());
-  error_handler.StartHandlingError();
-  EXPECT_FALSE(error_handler.IsTimerRunningForTesting());
-  EXPECT_FALSE(delegate_ptr->captive_portal_checked());
-  EXPECT_FALSE(delegate_ptr->ssl_interstitial_shown());
-  EXPECT_FALSE(delegate_ptr->captive_portal_interstitial_shown());
-  EXPECT_TRUE(delegate_ptr->legacy_tls_interstitial_shown());
-
-  histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2);
-  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
-                               SSLErrorHandler::HANDLE_ALL, 1);
-  histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
-                               SSLErrorHandler::SHOW_LEGACY_TLS_INTERSTITIAL,
-                               1);
-}
-
 // Tests that non-primary main frame navigations should not affect
 // SSLErrorHandler.
 TEST_F(SSLErrorHandlerTest, NonPrimaryMainframeShouldNotAffectSSLErrorHandler) {
   net::SSLInfo ssl_info;
   ssl_info.cert =
       net::ImportCertFromFile(net::GetTestCertsDirectory(), kOkayCertName);
-  ssl_info.cert_status = net::CERT_STATUS_LEGACY_TLS;
+  ssl_info.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
   ssl_info.public_key_hashes.push_back(net::HashValue(kCertPublicKeyHashValue));
 
   std::unique_ptr<TestSSLErrorHandlerDelegate> delegate(
diff --git a/components/security_interstitials/core/BUILD.gn b/components/security_interstitials/core/BUILD.gn
index 84e008c..346f5b5 100644
--- a/components/security_interstitials/core/BUILD.gn
+++ b/components/security_interstitials/core/BUILD.gn
@@ -14,8 +14,6 @@
     "common_string_util.h",
     "controller_client.cc",
     "controller_client.h",
-    "legacy_tls_ui.cc",
-    "legacy_tls_ui.h",
     "metrics_helper.cc",
     "metrics_helper.h",
     "mitm_software_ui.cc",
diff --git a/components/security_interstitials/core/browser/resources/interstitial_large.js b/components/security_interstitials/core/browser/resources/interstitial_large.js
index d1800049..7aab7c62 100644
--- a/components/security_interstitials/core/browser/resources/interstitial_large.js
+++ b/components/security_interstitials/core/browser/resources/interstitial_large.js
@@ -74,14 +74,13 @@
       interstitialType === 'SAFEBROWSING' && loadTimeData.getBoolean('billing');
   const originPolicy = interstitialType === 'ORIGIN_POLICY';
   const blockedInterception = interstitialType === 'BLOCKED_INTERCEPTION';
-  const legacyTls = interstitialType == 'LEGACY_TLS';
   const insecureForm = interstitialType == 'INSECURE_FORM';
   const httpsOnly = interstitialType == 'HTTPS_ONLY';
   const hidePrimaryButton = loadTimeData.getBoolean('hide_primary_button');
   const showRecurrentErrorParagraph = loadTimeData.getBoolean(
     'show_recurrent_error_paragraph');
 
-  if (ssl || originPolicy || blockedInterception || legacyTls) {
+  if (ssl || originPolicy || blockedInterception) {
     $('body').classList.add(badClock ? 'bad-clock' : 'ssl');
     if (loadTimeData.valueExists('errorCode')) {
       $('error-code').textContent = loadTimeData.getString('errorCode');
@@ -106,10 +105,6 @@
 
   $('icon').classList.add('icon');
 
-  if (legacyTls) {
-    $('icon').classList.add('legacy-tls');
-  }
-
   if (hidePrimaryButton) {
     $('primary-button').classList.add(HIDDEN_CLASS);
   } else {
@@ -120,7 +115,6 @@
           break;
 
         case 'SSL':
-        case 'LEGACY_TLS':
           if (badClock) {
             sendCommand(SecurityInterstitialCommandId.CMD_OPEN_DATE_SETTINGS);
           } else if (overridable) {
diff --git a/components/security_interstitials/core/browser/resources/interstitial_ssl.css b/components/security_interstitials/core/browser/resources/interstitial_ssl.css
index 268c578..98184fb 100644
--- a/components/security_interstitials/core/browser/resources/interstitial_ssl.css
+++ b/components/security_interstitials/core/browser/resources/interstitial_ssl.css
@@ -8,18 +8,6 @@
       url(images/2x/triangle_red.png) 2x);
 }
 
-.ssl .legacy-tls.icon {
-  background-image: -webkit-image-set(
-      url(images/1x/info.png) 1x,
-      url(images/2x/info.png) 2x);
-}
-
-@media (prefers-color-scheme: dark) {
-  .ssl .legacy-tls.icon {
-    filter: invert(1);
-  }
-}
-
 .ssl-opt-in .checkbox::after {
   border-color: #696969;
 }
diff --git a/components/security_interstitials/core/browser/resources/list_of_interstitials.html b/components/security_interstitials/core/browser/resources/list_of_interstitials.html
index 026903b..f9a07f19 100644
--- a/components/security_interstitials/core/browser/resources/list_of_interstitials.html
+++ b/components/security_interstitials/core/browser/resources/list_of_interstitials.html
@@ -61,9 +61,6 @@
     <li>
       <a href="blocked-interception">Blocked interception</a>
     </li>
-    <li>
-      <a href="legacy-tls">Legacy TLS</a>
-    </li>
   </ul>
   <h3>SafeBrowsing</h3>
   <h4>Loud</h4>
diff --git a/components/security_interstitials/core/legacy_tls_ui.cc b/components/security_interstitials/core/legacy_tls_ui.cc
deleted file mode 100644
index 63c9bd2..0000000
--- a/components/security_interstitials/core/legacy_tls_ui.cc
+++ /dev/null
@@ -1,144 +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.
-
-#include "components/security_interstitials/core/legacy_tls_ui.h"
-
-#include "base/i18n/number_formatting.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "components/security_interstitials/core/common_string_util.h"
-#include "components/security_interstitials/core/controller_client.h"
-#include "components/security_interstitials/core/metrics_helper.h"
-#include "components/ssl_errors/error_info.h"
-#include "components/strings/grit/components_strings.h"
-#include "net/base/escape.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-// Path to the relevant help center page.
-const char kHelpPath[] = "answer/6098869";
-
-}  // namespace
-
-namespace security_interstitials {
-
-LegacyTLSUI::LegacyTLSUI(const GURL& request_url,
-                         int cert_error,
-                         const net::SSLInfo& ssl_info,
-                         ControllerClient* controller)
-    : request_url_(request_url),
-      cert_error_(cert_error),
-      ssl_info_(ssl_info),
-      controller_(controller),
-      user_made_decision_(false) {
-  controller_->metrics_helper()->RecordUserInteraction(
-      security_interstitials::MetricsHelper::TOTAL_VISITS);
-}
-
-LegacyTLSUI::~LegacyTLSUI() {
-  // If the page is closing without an explicit decision, record it as not
-  // proceeding.
-  if (!user_made_decision_) {
-    controller_->metrics_helper()->RecordUserDecision(
-        MetricsHelper::DONT_PROCEED);
-  }
-  controller_->metrics_helper()->RecordShutdownMetrics();
-}
-
-void LegacyTLSUI::PopulateStringsForHTML(base::Value* load_time_data) {
-  CHECK(load_time_data);
-
-  // Shared with other SSL errors.
-  common_string_util::PopulateSSLLayoutStrings(cert_error_, load_time_data);
-  common_string_util::PopulateSSLDebuggingStrings(
-      ssl_info_, base::Time::NowFromSystemTime(), load_time_data);
-  load_time_data->SetBoolKey("overridable", true);
-  load_time_data->SetBoolKey("hide_primary_button", false);
-  load_time_data->SetBoolKey("bad_clock", false);
-  load_time_data->SetStringKey("type", "LEGACY_TLS");
-
-  const std::u16string hostname(
-      common_string_util::GetFormattedHostName(request_url_));
-
-  // Set strings that are shared between enterprise and non-enterprise
-  // interstitials.
-  load_time_data->SetStringKey("tabTitle",
-                               l10n_util::GetStringUTF16(IDS_SSL_V2_TITLE));
-  load_time_data->SetStringKey(
-      "heading", l10n_util::GetStringUTF16(IDS_LEGACY_TLS_HEADING));
-  load_time_data->SetStringKey(
-      "primaryButtonText",
-      l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_SAFETY_BUTTON));
-  load_time_data->SetStringKey(
-      "primaryParagraph",
-      l10n_util::GetStringUTF16(IDS_LEGACY_TLS_PRIMARY_PARAGRAPH));
-  load_time_data->SetStringKey(
-      "explanationParagraph",
-      l10n_util::GetStringUTF16(IDS_LEGACY_TLS_EXPLANATION));
-  load_time_data->SetStringKey(
-      "finalParagraph", l10n_util::GetStringFUTF16(
-                            IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH, hostname));
-}
-
-void LegacyTLSUI::HandleCommand(SecurityInterstitialCommand command) {
-  switch (command) {
-    case CMD_DONT_PROCEED: {
-      controller_->metrics_helper()->RecordUserDecision(
-          MetricsHelper::DONT_PROCEED);
-      user_made_decision_ = true;
-      controller_->GoBack();
-      break;
-    }
-    case CMD_PROCEED: {
-      controller_->metrics_helper()->RecordUserDecision(MetricsHelper::PROCEED);
-      controller_->Proceed();
-      user_made_decision_ = true;
-      break;
-    }
-    case CMD_SHOW_MORE_SECTION:
-      controller_->metrics_helper()->RecordUserInteraction(
-          security_interstitials::MetricsHelper::SHOW_ADVANCED);
-      break;
-    case CMD_OPEN_HELP_CENTER: {
-      controller_->metrics_helper()->RecordUserInteraction(
-          security_interstitials::MetricsHelper::SHOW_LEARN_MORE);
-      // Add cert error code as a ref to support URL, this is used to expand the
-      // right section if the user is redirected to chrome://connection-help.
-      GURL::Replacements replacements;
-      // This has to be stored in a separate variable, otherwise asan throws a
-      // use-after-scope error
-      std::string cert_error_string =
-          base::UTF16ToUTF8(base::FormatNumber(cert_error_));
-      replacements.SetRefStr(cert_error_string);
-      // If |support_url_| is invalid, use the default help center url.
-      controller_->OpenUrlInNewForegroundTab(
-          controller_->GetBaseHelpCenterUrl()
-              .Resolve(kHelpPath)
-              .ReplaceComponents(replacements));
-      break;
-    }
-
-    case CMD_RELOAD:
-    case CMD_OPEN_DATE_SETTINGS:
-    case CMD_OPEN_DIAGNOSTIC:
-    case CMD_OPEN_LOGIN:
-    case CMD_REPORT_PHISHING_ERROR:
-    case CMD_OPEN_WHITEPAPER:
-    case CMD_OPEN_REPORTING_PRIVACY:
-    case CMD_DO_REPORT:
-    case CMD_DONT_REPORT:
-    case CMD_OPEN_ENHANCED_PROTECTION_SETTINGS:
-      // Not supported by the legacy TLS error page.
-      NOTREACHED() << "Unsupported command: " << command;
-      break;
-    case CMD_ERROR:
-    case CMD_TEXT_FOUND:
-    case CMD_TEXT_NOT_FOUND:
-      // Commands are for testing.
-      break;
-  }
-}
-
-}  // namespace security_interstitials
diff --git a/components/security_interstitials/core/legacy_tls_ui.h b/components/security_interstitials/core/legacy_tls_ui.h
deleted file mode 100644
index 071d698..0000000
--- a/components/security_interstitials/core/legacy_tls_ui.h
+++ /dev/null
@@ -1,41 +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_SECURITY_INTERSTITIALS_CORE_LEGACY_TLS_UI_H_
-#define COMPONENTS_SECURITY_INTERSTITIALS_CORE_LEGACY_TLS_UI_H_
-
-#include "base/values.h"
-#include "components/security_interstitials/core/controller_client.h"
-#include "components/ssl_errors/error_classification.h"
-#include "net/ssl/ssl_info.h"
-#include "url/gurl.h"
-
-namespace security_interstitials {
-
-// Provides UI for SSL errors caused by legacy TLS versions.
-class LegacyTLSUI {
- public:
-  LegacyTLSUI(const GURL& request_url,
-              int cert_error,
-              const net::SSLInfo& ssl_info,
-              ControllerClient* controller_);
-
-  LegacyTLSUI(const LegacyTLSUI&) = delete;
-  LegacyTLSUI& operator=(const LegacyTLSUI&) = delete;
-
-  ~LegacyTLSUI();
-  void PopulateStringsForHTML(base::Value* load_time_data);
-  void HandleCommand(SecurityInterstitialCommand command);
-
- private:
-  const GURL request_url_;
-  const int cert_error_;
-  const net::SSLInfo ssl_info_;
-  ControllerClient* controller_;
-  bool user_made_decision_;
-};
-
-}  // namespace security_interstitials
-
-#endif  // COMPONENTS_SECURITY_INTERSTITIALS_CORE_LEGACY_TLS_UI_H_
diff --git a/components/security_interstitials/core/ssl_error_options_mask.cc b/components/security_interstitials/core/ssl_error_options_mask.cc
index bf4eb08..b6d658b 100644
--- a/components/security_interstitials/core/ssl_error_options_mask.cc
+++ b/components/security_interstitials/core/ssl_error_options_mask.cc
@@ -25,7 +25,6 @@
     case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED:
     case net::ERR_CERT_SYMANTEC_LEGACY:
     case net::ERR_CERT_KNOWN_INTERCEPTION_BLOCKED:
-    case net::ERR_SSL_OBSOLETE_VERSION:
       return false;
     case net::ERR_CERT_CONTAINS_ERRORS:
     case net::ERR_CERT_REVOKED:
diff --git a/components/services/app_service/public/cpp/instance.cc b/components/services/app_service/public/cpp/instance.cc
index 90fadac..ce8e1024 100644
--- a/components/services/app_service/public/cpp/instance.cc
+++ b/components/services/app_service/public/cpp/instance.cc
@@ -10,28 +10,12 @@
 namespace apps {
 
 // static
-Instance::InstanceKey Instance::InstanceKey::ForWebBasedApp(
-    aura::Window* window) {
-  return InstanceKey(window,
-                     /*is_web_contents_backed=*/true);
-}
-
-// static
 Instance::InstanceKey Instance::InstanceKey::ForWindowBasedApp(
     aura::Window* window) {
-  return InstanceKey(window,
-                     /*is_web_contents_backed=*/false);
+  return InstanceKey(window);
 }
 
-Instance::InstanceKey::InstanceKey(aura::Window* window,
-                                   bool is_web_contents_backed)
-    : window_(window), is_web_contents_backed_(is_web_contents_backed) {}
-
-aura::Window* Instance::InstanceKey::GetEnclosingAppWindow() const {
-  if (is_web_contents_backed_)
-    return window_->GetToplevelWindow();
-  return window_;
-}
+Instance::InstanceKey::InstanceKey(aura::Window* window) : window_(window) {}
 
 bool Instance::InstanceKey::operator<(const InstanceKey& other) const {
   return window_ < other.window_;
@@ -63,7 +47,10 @@
 Instance::Instance(const std::string& app_id,
                    const base::UnguessableToken& instance_id,
                    aura::Window* window)
-    : app_id_(app_id), instance_id_(instance_id), window_(window) {}
+    : app_id_(app_id),
+      instance_id_(instance_id),
+      window_(window),
+      instance_key_(window) {}
 
 Instance::~Instance() = default;
 
@@ -94,9 +81,7 @@
 
 std::ostream& operator<<(std::ostream& os,
                          const apps::Instance::InstanceKey& instance_key) {
-  return os << "InstanceKey {window: " << instance_key.window_
-            << ", is_web_contents_backed: "
-            << instance_key.is_web_contents_backed_ << "}";
+  return os << "InstanceKey {window: " << instance_key.window_ << "}";
 }
 
 size_t InstanceKeyHash::operator()(
diff --git a/components/services/app_service/public/cpp/instance.h b/components/services/app_service/public/cpp/instance.h
index f9cc4b4..949fb520 100644
--- a/components/services/app_service/public/cpp/instance.h
+++ b/components/services/app_service/public/cpp/instance.h
@@ -33,20 +33,14 @@
   // TODO(crbug.com/1251501): InstanceKey will be removed soon.
   class InstanceKey {
    public:
-    // Create an InstanceKey for an app instance backed by a WebContents.
-    static InstanceKey ForWebBasedApp(aura::Window* window);
-
     // Create an InstanceKey for any non-web app type.
     static InstanceKey ForWindowBasedApp(aura::Window* window);
 
-    InstanceKey() = default;
+    explicit InstanceKey(aura::Window* window);
     InstanceKey(const InstanceKey& instance_key) = default;
     InstanceKey(InstanceKey&& instance_key) = default;
     ~InstanceKey() = default;
 
-    // Return enclosing app windows for the |app_id|. If the app is in a browser
-    // tab, the window returned will be the window of the browser.
-    aura::Window* GetEnclosingAppWindow() const;
     aura::Window* Window() const { return window_; }
     bool IsValid() const { return window_ != nullptr; }
     bool operator<(const InstanceKey& other) const;
@@ -60,17 +54,11 @@
         const apps::Instance::InstanceKey& instance_key);
 
    private:
-    explicit InstanceKey(aura::Window* window, bool is_web_contents_backed);
-
     // window_ is owned by ash and will be deleted when the user closes the
     // window. Instance itself doesn't observe the window. The window's observer
     // is responsible to delete Instance from InstanceRegistry when the window
     // is destroyed.
     aura::Window* window_ = nullptr;
-
-    // Whether the app is a WebContents backed app. Will eventually be replaced
-    // by an ID representing the WebContents which may live remotely.
-    bool is_web_contents_backed_ = false;
   };
 
   Instance(const std::string& app_id,
diff --git a/components/services/app_service/public/cpp/instance_registry.cc b/components/services/app_service/public/cpp/instance_registry.cc
index c4f41660..27fa06f 100644
--- a/components/services/app_service/public/cpp/instance_registry.cc
+++ b/components/services/app_service/public/cpp/instance_registry.cc
@@ -56,58 +56,40 @@
   observers_.RemoveObserver(observer);
 }
 
-void InstanceRegistry::OnInstances(Instances deltas) {
+void InstanceRegistry::OnInstance(InstancePtr delta) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
 
-  for (auto& delta : deltas) {
-    if (delta->InstanceId()) {
-      // TODO(crbug.com/1251501): Implement updating the instance registry using
-      // instance ID as a key.
-      continue;
-    }
-    // If the instance state is not kDestroyed, adds to
-    // |app_id_to_app_instance_key_|, otherwise removes the instance key from
-    // |app_id_to_app_instance_key_|.
-    if (static_cast<InstanceState>(delta.get()->State() &
-                                   InstanceState::kDestroyed) ==
-        InstanceState::kUnknown) {
-      app_id_to_app_instance_key_[delta.get()->AppId()].insert(
-          delta.get()->GetInstanceKey());
-    } else {
-      app_id_to_app_instance_key_[delta.get()->AppId()].erase(
-          delta.get()->GetInstanceKey());
-      if (app_id_to_app_instance_key_[delta.get()->AppId()].size() == 0) {
-        app_id_to_app_instance_key_.erase(delta.get()->AppId());
-      }
+  if (!delta || delta->InstanceId()) {
+    // TODO(crbug.com/1251501): Implement updating the instance registry using
+    // instance ID as a key.
+    return;
+  }
+  // If the instance state is not kDestroyed, adds to
+  // |app_id_to_app_instance_key_|, otherwise removes the instance key from
+  // |app_id_to_app_instance_key_|.
+  if (static_cast<InstanceState>(delta->State() & InstanceState::kDestroyed) ==
+      InstanceState::kUnknown) {
+    app_id_to_app_instance_key_[delta->AppId()].insert(delta->GetInstanceKey());
+  } else {
+    app_id_to_app_instance_key_[delta->AppId()].erase(
+        delta.get()->GetInstanceKey());
+    if (app_id_to_app_instance_key_[delta->AppId()].size() == 0) {
+      app_id_to_app_instance_key_.erase(delta->AppId());
     }
   }
 
   if (in_progress_) {
-    for (auto& delta : deltas) {
-      deltas_pending_.push_back(delta.get()->Clone());
-    }
+    deltas_pending_.push_back(std::move(delta));
     return;
   }
-  DoOnInstances(std::move(deltas));
+  DoOnInstance(std::move(delta));
   while (!deltas_pending_.empty()) {
-    Instances pending;
-    pending.swap(deltas_pending_);
-    DoOnInstances(std::move(pending));
+    InstancePtr instance = std::move(*deltas_pending_.begin());
+    DoOnInstance(std::move(instance));
+    deltas_pending_.pop_front();
   }
 }
 
-std::set<aura::Window*> InstanceRegistry::GetEnclosingAppWindows(
-    const std::string& app_id) {
-  auto it = app_id_to_app_instance_key_.find(app_id);
-  auto windows = std::set<aura::Window*>{};
-  if (it != app_id_to_app_instance_key_.end()) {
-    for (auto instance_key : it->second) {
-      windows.insert(instance_key.GetEnclosingAppWindow());
-    }
-  }
-  return windows;
-}
-
 std::set<const Instance::InstanceKey> InstanceRegistry::GetInstanceKeys(
     const std::string& app_id) {
   auto it = app_id_to_app_instance_key_.find(app_id);
@@ -140,43 +122,43 @@
   return base::Contains(app_id_to_app_instance_key_, app_id);
 }
 
-void InstanceRegistry::DoOnInstances(const Instances& deltas) {
+void InstanceRegistry::DoOnInstance(InstancePtr delta) {
   in_progress_ = true;
 
-  // The remaining for loops range over the deltas vector, so that
-  // OninstanceUpdate is called for each updates, and notify the observers for
-  // every de-duplicated delta. Also update the states for every delta.
-  for (const auto& d_iter : deltas) {
-    if (d_iter->InstanceId()) {
-      // TODO(crbug.com/1251501): Implement updating the instance registry using
-      // instance ID as a key.
-      continue;
-    }
-    auto s_iter = instance_key_states_.find(d_iter->GetInstanceKey());
-    Instance* state =
-        (s_iter != instance_key_states_.end()) ? s_iter->second.get() : nullptr;
-    if (InstanceUpdate::Equals(state, d_iter.get())) {
-      continue;
-    }
+  if (delta->InstanceId()) {
+    // TODO(crbug.com/1251501): Implement updating the instance registry using
+    // instance ID as a key.
+    in_progress_ = false;
+    return;
+  }
+  auto s_iter = instance_key_states_.find(delta->GetInstanceKey());
+  Instance* state =
+      (s_iter != instance_key_states_.end()) ? s_iter->second.get() : nullptr;
+  if (InstanceUpdate::Equals(state, delta.get())) {
+    in_progress_ = false;
+    return;
+  }
 
-    std::unique_ptr<Instance> old_state;
-    if (state) {
-      old_state = state->Clone();
-      InstanceUpdate::Merge(state, d_iter.get());
-    } else {
-      instance_key_states_.insert(std::make_pair(d_iter.get()->GetInstanceKey(),
-                                                 (d_iter.get()->Clone())));
-    }
+  std::unique_ptr<Instance> old_state;
+  Instance* new_delta = delta.get();
+  if (state) {
+    old_state = state->Clone();
+    InstanceUpdate::Merge(state, delta.get());
+  } else {
+    // The content of `delta` is moved, however, `new_delta` is still valid,
+    // because `new_delta` is the pointer to the content of `delta`.
+    instance_key_states_.insert(
+        std::make_pair(delta->GetInstanceKey(), std::move(delta)));
+  }
 
-    for (auto& obs : observers_) {
-      obs.OnInstanceUpdate(InstanceUpdate(old_state.get(), d_iter.get()));
-    }
+  for (auto& obs : observers_) {
+    obs.OnInstanceUpdate(InstanceUpdate(old_state.get(), new_delta));
+  }
 
-    if (static_cast<InstanceState>(d_iter.get()->State() &
-                                   InstanceState::kDestroyed) !=
-        InstanceState::kUnknown) {
-      instance_key_states_.erase(d_iter.get()->GetInstanceKey());
-    }
+  if (static_cast<InstanceState>(new_delta->State() &
+                                 InstanceState::kDestroyed) !=
+      InstanceState::kUnknown) {
+    instance_key_states_.erase(new_delta->GetInstanceKey());
   }
   in_progress_ = false;
 }
diff --git a/components/services/app_service/public/cpp/instance_registry.h b/components/services/app_service/public/cpp/instance_registry.h
index b7567db..4a65eb7 100644
--- a/components/services/app_service/public/cpp/instance_registry.h
+++ b/components/services/app_service/public/cpp/instance_registry.h
@@ -5,11 +5,11 @@
 #ifndef COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INSTANCE_REGISTRY_H_
 #define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INSTANCE_REGISTRY_H_
 
+#include <list>
 #include <map>
 #include <memory>
 #include <set>
 #include <string>
-#include <vector>
 
 #include "ash/public/cpp/shelf_types.h"
 #include "base/observer_list.h"
@@ -75,25 +75,20 @@
   void RemoveObserver(Observer* observer);
 
   using InstancePtr = std::unique_ptr<Instance>;
-  using Instances = std::vector<InstancePtr>;
 
-  // Notification and merging might be delayed until after OnInstances returns.
+  // Notification and merging might be delayed until after OnInstance returns.
   // For example, suppose that the initial set of states is (a0, b0, c0) for
-  // three app_id's ("a", "b", "c"). Now suppose OnInstances is called with two
-  // updates (b1, c1), and when notified of b1, an observer calls OnInstances
-  // again with (c2, d2). The c1 delta should be processed before the c2 delta,
-  // as it was sent first, and both c1 and c2 will be updated to the observer
-  // following the sequence. This means that processing c2 (scheduled by the
-  // second OnInstances call) should wait until the first OnInstances call has
-  // finished processing b1, and then c1, which means that processing c2 is
-  // delayed until after the second OnInstances call returns.
+  // three app_id's ("a", "b", "c"). Now suppose OnInstance is called with an
+  // update (b1), and when notified of b1, an observer calls OnInstance
+  // again with (b2). The b1 delta should be processed before the b2 delta,
+  // as it was sent first, and both b1 and b2 will be updated to the observer
+  // following the sequence. This means that processing b2 (scheduled by the
+  // second OnInstance call) should wait until the first OnInstance call has
+  // finished processing b1, and then b2, which means that processing b2 is
+  // delayed until after the second OnInstance call returns.
   //
-  // The caller presumably calls OnInstances(std::move(deltas)).
-  void OnInstances(Instances deltas);
-
-  // Return enclosing app windows for the |app_id|. If the app is in a browser
-  // tab, the window returned will be the window of the browser.
-  std::set<aura::Window*> GetEnclosingAppWindows(const std::string& app_id);
+  // The caller presumably calls OnInstance(std::move(delta)).
+  void OnInstance(InstancePtr delta);
 
   // Return instance keys for the |app_id|.
   std::set<const Instance::InstanceKey> GetInstanceKeys(
@@ -159,27 +154,27 @@
   }
 
  private:
-  void DoOnInstances(const Instances& deltas);
+  void DoOnInstance(InstancePtr deltas);
 
   base::ObserverList<Observer> observers_;
 
-  // OnInstances calls DoOnInstances zero or more times. If we're nested,
-  // in_progress is true, so that there's multiple OnInstances call to this
+  // OnInstance calls DoOnInstance zero or more times. If we're nested,
+  // in_progress is true, so that there's multiple OnInstance call to this
   // InstanceRegistry in the call stack, the deeper OnInstances call simply adds
-  // work to deltas_pending_ and returns without calling DoOnInstances. If we're
-  // not nested, in_progress is false, OnInstances calls DoOnInstances one or
-  // more times; "more times" happens if DoOnInstances notifying observers leads
-  // to more OnInstances calls that enqueue deltas_pending_ work.
+  // work to deltas_pending_ and returns without calling DoOnInstance. If we're
+  // not nested, in_progress is false, OnInstance calls DoOnInstance one or
+  // more times; "more times" happens if DoOnInstance notifying observers leads
+  // to more OnInstance calls that enqueue deltas_pending_ work.
   //
-  // Nested OnInstances calls are expected to be rare (but still dealt with
-  // sensibly). In the typical case, OnInstances should call DoOnInstances
+  // Nested OnInstance calls are expected to be rare (but still dealt with
+  // sensibly). In the typical case, OnInstance should call DoOnInstance
   // exactly once, and deltas_pending_ will stay empty.
   bool in_progress_ = false;
 
   // Maps from instance key to the latest state: the "sum" of all previous
   // deltas.
   std::map<const Instance::InstanceKey, InstancePtr> instance_key_states_;
-  Instances deltas_pending_;
+  std::list<InstancePtr> deltas_pending_;
 
   // Maps from app id to app instance key.
   std::map<const std::string, std::set<const Instance::InstanceKey>>
diff --git a/components/services/app_service/public/cpp/instance_registry_unittest.cc b/components/services/app_service/public/cpp/instance_registry_unittest.cc
index 23c5dfb..34cc1ae 100644
--- a/components/services/app_service/public/cpp/instance_registry_unittest.cc
+++ b/components/services/app_service/public/cpp/instance_registry_unittest.cc
@@ -37,14 +37,8 @@
     return instance;
   }
 
-  static apps::Instance::InstanceKey MakeInstanceKeyNonWebApp(
-      aura::Window* window) {
-    return apps::Instance::InstanceKey::ForWindowBasedApp(window);
-  }
-
-  static apps::Instance::InstanceKey MakeInstanceKeyWebApp(
-      aura::Window* window) {
-    return apps::Instance::InstanceKey::ForWebBasedApp(window);
+  static apps::Instance::InstanceKey MakeInstanceKey(aura::Window* window) {
+    return apps::Instance::InstanceKey(window);
   }
 
   void CallForEachInstance(apps::InstanceRegistry& instance_registry) {
@@ -68,8 +62,7 @@
       num_running_apps_++;
     }
     updated_ids_.insert(update.AppId());
-    updated_enclosing_windows_.insert(
-        update.InstanceKey().GetEnclosingAppWindow());
+    updated_enclosing_windows_.insert(update.InstanceKey().Window());
   }
 
   void OnInstanceRegistryWillBeDestroyed(
@@ -83,11 +76,11 @@
   std::set<const aura::Window*> updated_enclosing_windows_;
 };
 
-// In the tests below, just "recursive" means that instance_registry.OnInstances
+// In the tests below, just "recursive" means that instance_registry.OnInstance
 // calls observer.OnInstanceUpdate which calls instance_registry.ForEachInstance
 // and instance_registry.ForOneInstance. "Super-recursive" means that
-// instance_registry.OnInstances calls observer.OnInstanceUpdate calls
-// instance_registry.OnInstances which calls observer.OnInstanceUpdate.
+// instance_registry.OnInstance calls observer.OnInstanceUpdate calls
+// instance_registry.OnInstance which calls observer.OnInstanceUpdate.
 class InstanceRecursiveObserver : public apps::InstanceRegistry::Observer {
  public:
   explicit InstanceRecursiveObserver(apps::InstanceRegistry* instance_registry)
@@ -133,7 +126,6 @@
       EXPECT_EQ(expected_num_instances_, num_instance);
     }
 
-    std::vector<std::unique_ptr<apps::Instance>> super_recursive;
     while (!super_recursive_instances_.empty()) {
       std::unique_ptr<apps::Instance> instance =
           std::move(super_recursive_instances_.back());
@@ -142,12 +134,9 @@
         super_recursive_instances_.pop_back();
         break;
       }
-      super_recursive.push_back(std::move(instance));
+      instance_registry_->OnInstance(std::move(instance));
       super_recursive_instances_.pop_back();
     }
-    if (!super_recursive.empty()) {
-      instance_registry_->OnInstances(std::move(super_recursive));
-    }
 
     num_instances_seen_on_instance_update_++;
   }
@@ -167,22 +156,21 @@
     EXPECT_EQ(outer.BrowserContext(), inner.BrowserContext());
   }
 
-  apps::InstanceRegistry* instance_registry_;
-  int expected_num_instances_;
-  int num_instances_seen_on_instance_update_;
+  apps::InstanceRegistry* instance_registry_ = nullptr;
+  int expected_num_instances_ = -1;
+  int num_instances_seen_on_instance_update_ = 0;
 
   // Non-empty when this.OnInstanceUpdate should trigger more
-  // instance_registry_.OnInstances calls.
+  // instance_registry_.OnInstance calls.
   //
   // During OnInstanceUpdate, this vector (a stack) is popped from the back
   // until a nullptr 'punctuation' element (a group terminator) is seen. If that
   // group of popped elements (in LIFO order) is non-empty, that group forms the
-  // vector of App's passed to instance_registry_.OnInstances.
+  // vector of App's passed to instance_registry_.OnInstance.
   std::vector<std::unique_ptr<apps::Instance>> super_recursive_instances_;
 };
 
 TEST_F(InstanceRegistryTest, ForEachInstance) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
   apps::InstanceRegistry instance_registry;
 
   updated_enclosing_windows_.clear();
@@ -193,23 +181,15 @@
   EXPECT_EQ(0u, updated_enclosing_windows_.size());
   EXPECT_EQ(0u, updated_ids_.size());
 
-  deltas.clear();
   aura::Window window1(nullptr);
   window1.Init(ui::LAYER_NOT_DRAWN);
   aura::Window window2(nullptr);
   window2.Init(ui::LAYER_NOT_DRAWN);
   aura::Window window3(nullptr);
   window3.Init(ui::LAYER_NOT_DRAWN);
-  deltas.push_back(MakeInstanceWithWindow("a", &window1));
-  deltas.push_back(MakeInstanceWithWindow("b", &window2));
-  deltas.push_back(MakeInstanceWithWindow("c", &window3));
-  instance_registry.OnInstances(std::move(deltas));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("a") ==
-              std::set<aura::Window*>{&window1});
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("b") ==
-              std::set<aura::Window*>{&window2});
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("c") ==
-              std::set<aura::Window*>{&window3});
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("b", &window2));
+  instance_registry.OnInstance(MakeInstanceWithWindow("c", &window3));
 
   updated_enclosing_windows_.clear();
   updated_ids_.clear();
@@ -227,17 +207,11 @@
   EXPECT_NE(updated_ids_.end(), updated_ids_.find("b"));
   EXPECT_NE(updated_ids_.end(), updated_ids_.find("c"));
 
-  deltas.clear();
   aura::Window window4(nullptr);
   window4.Init(ui::LAYER_NOT_DRAWN);
-  deltas.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("a", &window1, apps::InstanceState::kRunning));
-  deltas.push_back(MakeInstanceWithWindow("c", &window4));
-  instance_registry.OnInstances(std::move(deltas));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("a") ==
-              std::set<aura::Window*>{&window1});
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("c") ==
-              (std::set<aura::Window*>{&window3, &window4}));
+  instance_registry.OnInstance(MakeInstanceWithWindow("c", &window4));
 
   updated_enclosing_windows_.clear();
   updated_ids_.clear();
@@ -261,7 +235,7 @@
 
   bool found_window4 = false;
   EXPECT_TRUE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window4),
+      MakeInstanceKey(&window4),
       [&found_window4](const apps::InstanceUpdate& update) {
         found_window4 = true;
         EXPECT_EQ("c", update.AppId());
@@ -272,7 +246,7 @@
   aura::Window window5(nullptr);
   window5.Init(ui::LAYER_NOT_DRAWN);
   EXPECT_FALSE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window5),
+      MakeInstanceKey(&window5),
       [&found_window5](const apps::InstanceUpdate& update) {
         found_window5 = true;
       }));
@@ -297,10 +271,9 @@
   aura::Window window3(nullptr);
   window3.Init(ui::LAYER_NOT_DRAWN);
 
-  deltas.push_back(MakeInstanceWithWindow("a", &window1));
-  deltas.push_back(MakeInstanceWithWindow("c", &window2));
-  deltas.push_back(MakeInstanceWithWindow("a", &window3));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("c", &window2));
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window3));
 
   EXPECT_EQ(0, num_running_apps_);
   EXPECT_EQ(3u, updated_enclosing_windows_.size());
@@ -324,7 +297,9 @@
   deltas.push_back(MakeInstanceWithWindow("b", &window4));
   deltas.push_back(
       MakeInstanceWithWindow("c", &window2, apps::InstanceState::kRunning));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(MakeInstanceWithWindow("b", &window4));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("c", &window2, apps::InstanceState::kRunning));
 
   EXPECT_EQ(1, num_running_apps_);
   EXPECT_EQ(2u, updated_ids_.size());
@@ -344,9 +319,8 @@
 
   aura::Window window5(nullptr);
   window5.Init(ui::LAYER_NOT_DRAWN);
-  deltas.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("f", &window5, apps::InstanceState::kRunning));
-  instance_registry.OnInstances(std::move(deltas));
 
   EXPECT_EQ(0, num_running_apps_);
   EXPECT_EQ(0u, updated_enclosing_windows_.size());
@@ -354,29 +328,24 @@
 }
 
 TEST_F(InstanceRegistryTest, WholeProcessForOneWindow) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
   apps::InstanceRegistry instance_registry;
   InstanceRecursiveObserver observer(&instance_registry);
 
   apps::InstanceState instance_state = apps::InstanceState::kStarted;
-  deltas.clear();
   aura::Window window(nullptr);
   window.Init(ui::LAYER_NOT_DRAWN);
   observer.PrepareForOnInstances(1);
-  deltas.push_back(MakeInstanceWithWindow("p", &window, instance_state));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window, instance_state));
   EXPECT_EQ(1, observer.NumInstancesSeenOnInstanceUpdate());
 
   instance_state = static_cast<apps::InstanceState>(
       instance_state | apps::InstanceState::kRunning |
       apps::InstanceState::kActive | apps::InstanceState::kVisible);
   observer.PrepareForOnInstances(1);
-  deltas.clear();
-  deltas.push_back(MakeInstanceWithWindow("p", &window, instance_state));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window, instance_state));
   EXPECT_EQ(1, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("p") ==
-              std::set<aura::Window*>{&window});
 
   apps::InstanceState state1 = static_cast<apps::InstanceState>(
       apps::InstanceState::kStarted | apps::InstanceState::kRunning);
@@ -392,14 +361,13 @@
       apps::InstanceState::kVisible);
   apps::InstanceState state6 = apps::InstanceState::kDestroyed;
   observer.PrepareForOnInstances(1);
-  deltas.clear();
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state1));
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state2));
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state3));
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state4));
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state5));
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state6));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state2));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state3));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state4));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state5));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state6));
+
   // OnInstanceUpdate is called for state1, because state1 is different with
   // previous instance_state. state2 and state3 is not changed, so
   // OnInstanceUpdate is not called. OnInstanceUpdate is called for state4,
@@ -410,23 +378,19 @@
 
   bool found_window = false;
   EXPECT_FALSE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window),
+      MakeInstanceKey(&window),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
   EXPECT_FALSE(found_window);
 
   observer.PrepareForOnInstances(1);
-  deltas.clear();
-  deltas.push_back(MakeInstanceWithWindow("p", &window, state5));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(MakeInstanceWithWindow("p", &window, state5));
   EXPECT_EQ(1, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("p") ==
-              std::set<aura::Window*>{&window});
 
   found_window = false;
   EXPECT_TRUE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window),
+      MakeInstanceKey(&window),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
@@ -434,7 +398,6 @@
 }
 
 TEST_F(InstanceRegistryTest, Recursive) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
   apps::InstanceRegistry instance_registry;
   InstanceRecursiveObserver observer(&instance_registry);
 
@@ -442,20 +405,16 @@
       apps::InstanceState::kStarted | apps::InstanceState::kRunning);
   apps::InstanceState instance_state2 = static_cast<apps::InstanceState>(
       apps::InstanceState::kStarted | apps::InstanceState::kRunning);
-  deltas.clear();
   aura::Window window1(nullptr);
   window1.Init(ui::LAYER_NOT_DRAWN);
   aura::Window window2(nullptr);
   window2.Init(ui::LAYER_NOT_DRAWN);
   observer.PrepareForOnInstances(-1);
-  deltas.push_back(MakeInstanceWithWindow("o", &window1, instance_state1));
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state2));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("o", &window1, instance_state1));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state2));
   EXPECT_EQ(2, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("o") ==
-              std::set<aura::Window*>{&window1});
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("p") ==
-              std::set<aura::Window*>{&window2});
 
   apps::InstanceState instance_state3 = static_cast<apps::InstanceState>(
       apps::InstanceState::kStarted | apps::InstanceState::kRunning);
@@ -464,21 +423,18 @@
   std::vector<apps::InstanceState> latest_state;
   latest_state.push_back(instance_state3);
   latest_state.push_back(instance_state3);
-  deltas.clear();
   aura::Window window3(nullptr);
   window3.Init(ui::LAYER_NOT_DRAWN);
   aura::Window window4(nullptr);
   window4.Init(ui::LAYER_NOT_DRAWN);
   observer.PrepareForOnInstances(-1);
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state3));
-  deltas.push_back(MakeInstanceWithWindow("q", &window3, instance_state4));
-  deltas.push_back(MakeInstanceWithWindow("p", &window4, instance_state3));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state3));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("q", &window3, instance_state4));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window4, instance_state3));
   EXPECT_EQ(2, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("p") ==
-              (std::set<aura::Window*>{&window2, &window4}));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("q") ==
-              std::set<aura::Window*>{&window3});
 
   apps::InstanceState instance_state5 = static_cast<apps::InstanceState>(
       apps::InstanceState::kStarted | apps::InstanceState::kRunning);
@@ -489,24 +445,25 @@
       apps::InstanceState::kActive);
 
   observer.PrepareForOnInstances(4);
-  deltas.clear();
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state5));
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state6));
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state7));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state5));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state6));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state7));
   EXPECT_EQ(1, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("p") ==
-              (std::set<aura::Window*>{&window2, &window4}));
 
   apps::InstanceState instance_state8 =
       static_cast<apps::InstanceState>(apps::InstanceState::kDestroyed);
   observer.PrepareForOnInstances(-1);
-  deltas.clear();
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state8));
-  deltas.push_back(MakeInstanceWithWindow("p", &window4, instance_state8));
-  deltas.push_back(MakeInstanceWithWindow("q", &window3, instance_state8));
-  deltas.push_back(MakeInstanceWithWindow("o", &window1, instance_state8));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state8));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window4, instance_state8));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("q", &window3, instance_state8));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("o", &window1, instance_state8));
   EXPECT_EQ(4, observer.NumInstancesSeenOnInstanceUpdate());
   EXPECT_FALSE(instance_registry.ContainsAppId("o"));
   EXPECT_FALSE(instance_registry.ContainsAppId("p"));
@@ -514,7 +471,7 @@
 
   bool found_window = false;
   EXPECT_FALSE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window2),
+      MakeInstanceKey(&window2),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
@@ -522,7 +479,7 @@
 
   found_window = false;
   EXPECT_FALSE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window4),
+      MakeInstanceKey(&window4),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
@@ -530,7 +487,7 @@
 
   found_window = false;
   EXPECT_FALSE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window3),
+      MakeInstanceKey(&window3),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
@@ -538,23 +495,20 @@
 
   found_window = false;
   EXPECT_FALSE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window1),
+      MakeInstanceKey(&window1),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
   EXPECT_FALSE(found_window);
 
   observer.PrepareForOnInstances(1);
-  deltas.clear();
-  deltas.push_back(MakeInstanceWithWindow("p", &window2, instance_state7));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(
+      MakeInstanceWithWindow("p", &window2, instance_state7));
   EXPECT_EQ(1, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("p") ==
-              std::set<aura::Window*>{&window2});
 
   found_window = false;
   EXPECT_TRUE(instance_registry.ForOneInstance(
-      MakeInstanceKeyNonWebApp(&window2),
+      MakeInstanceKey(&window2),
       [&found_window](const apps::InstanceUpdate& update) {
         found_window = true;
       }));
@@ -562,11 +516,10 @@
 }
 
 TEST_F(InstanceRegistryTest, SuperRecursive) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
   apps::InstanceRegistry instance_registry;
   InstanceRecursiveObserver observer(&instance_registry);
 
-  // Set up a series of OnInstances to be called during
+  // Set up a series of OnInstance to be called during
   // observer.OnInstanceUpdate:
   //  - the 1st update is {'a', &window2, kActive}.
   //  - the 2nd update is {'b', &window3, kActive}.
@@ -575,7 +528,9 @@
   //  - the 5th update is {'c', &window4, kVisible}.
   //  - the 6td update is {'b', &window3, kRunning}.
   //  - the 7th update is {'a', &window2, kRunning}.
-  //  - the 8th update is {'b', &window1, kStarted}.
+  //  - the 7th update is {'a', &window2, kDestroyed}.
+  //  - the 7th update is {'a', &window2, kUnknown}.
+  //  - the 7th update is {'a', &window1, kDestroyed}.
   //
   // The vector is processed in LIFO order with nullptr punctuation to
   // terminate each group. See the comment on the
@@ -612,22 +567,14 @@
   super_recursive_apps.push_back(
       MakeInstanceWithWindow("b", &window5, apps::InstanceState::kVisible));
 
-  observer.PrepareForOnInstances(-1, &super_recursive_apps);
-  deltas.clear();
-  deltas.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("a", &window2, apps::InstanceState::kActive));
-  deltas.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("b", &window3, apps::InstanceState::kActive));
-  deltas.push_back(
+  observer.PrepareForOnInstances(-1, &super_recursive_apps);
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("c", &window4, apps::InstanceState::kActive));
-  instance_registry.OnInstances(std::move(deltas));
-  EXPECT_EQ(10, observer.NumInstancesSeenOnInstanceUpdate());
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("a") ==
-              (std::set<aura::Window*>{&window1, &window2}));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("b") ==
-              (std::set<aura::Window*>{&window3, &window5}));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("c") ==
-              std::set<aura::Window*>{&window4});
+  EXPECT_EQ(8, observer.NumInstancesSeenOnInstanceUpdate());
 
   // After all of that, check that for each window, the last delta won.
   EXPECT_EQ(apps::InstanceState::kStarted,
@@ -643,7 +590,6 @@
 }
 
 TEST_F(InstanceRegistryTest, GetInstanceKeys) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas1;
   apps::InstanceRegistry instance_registry;
 
   aura::Window window1(nullptr);
@@ -653,35 +599,30 @@
   aura::Window window3(nullptr);
   window3.Init(ui::LAYER_NOT_DRAWN);
 
-  deltas1.push_back(MakeInstanceWithWindow("a", &window1));
-  deltas1.push_back(MakeInstanceWithWindow("b", &window2));
-  deltas1.push_back(MakeInstanceWithWindow("a", &window3));
-  instance_registry.OnInstances(std::move(deltas1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("b", &window2));
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window3));
 
   EXPECT_TRUE(instance_registry.GetInstanceKeys("a") ==
               (std::set<const apps::Instance::InstanceKey>{
-                  MakeInstanceKeyNonWebApp(&window1),
-                  MakeInstanceKeyNonWebApp(&window3)}));
-  EXPECT_TRUE(instance_registry.GetInstanceKeys("b") ==
-              (std::set<const apps::Instance::InstanceKey>{
-                  MakeInstanceKeyNonWebApp(&window2)}));
+                  MakeInstanceKey(&window1), MakeInstanceKey(&window3)}));
+  EXPECT_TRUE(
+      instance_registry.GetInstanceKeys("b") ==
+      (std::set<const apps::Instance::InstanceKey>{MakeInstanceKey(&window2)}));
 
-  std::vector<std::unique_ptr<apps::Instance>> deltas2;
-  deltas2.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("a", &window1, apps::InstanceState::kDestroyed));
-  deltas2.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("b", &window2, apps::InstanceState::kDestroyed));
-  instance_registry.OnInstances(std::move(deltas2));
 
-  EXPECT_TRUE(instance_registry.GetInstanceKeys("a") ==
-              (std::set<const apps::Instance::InstanceKey>{
-                  MakeInstanceKeyNonWebApp(&window3)}));
+  EXPECT_TRUE(
+      instance_registry.GetInstanceKeys("a") ==
+      (std::set<const apps::Instance::InstanceKey>{MakeInstanceKey(&window3)}));
   EXPECT_TRUE(instance_registry.GetInstanceKeys("b") ==
               (std::set<const apps::Instance::InstanceKey>()));
 }
 
 TEST_F(InstanceRegistryTest, ContainsAppId) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas1;
   apps::InstanceRegistry instance_registry;
 
   aura::Window window1(nullptr);
@@ -691,28 +632,24 @@
   aura::Window window3(nullptr);
   window3.Init(ui::LAYER_NOT_DRAWN);
 
-  deltas1.push_back(MakeInstanceWithWindow("a", &window1));
-  deltas1.push_back(MakeInstanceWithWindow("b", &window2));
-  deltas1.push_back(MakeInstanceWithWindow("a", &window3));
-  instance_registry.OnInstances(std::move(deltas1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window1));
+  instance_registry.OnInstance(MakeInstanceWithWindow("b", &window2));
+  instance_registry.OnInstance(MakeInstanceWithWindow("a", &window3));
 
   EXPECT_TRUE(instance_registry.ContainsAppId("a"));
   EXPECT_TRUE(instance_registry.ContainsAppId("b"));
   EXPECT_FALSE(instance_registry.ContainsAppId("c"));
 
-  std::vector<std::unique_ptr<apps::Instance>> deltas2;
-  deltas2.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("a", &window1, apps::InstanceState::kDestroyed));
-  deltas2.push_back(
+  instance_registry.OnInstance(
       MakeInstanceWithWindow("b", &window2, apps::InstanceState::kDestroyed));
-  instance_registry.OnInstances(std::move(deltas2));
 
   EXPECT_TRUE(instance_registry.ContainsAppId("a"));
   EXPECT_FALSE(instance_registry.ContainsAppId("b"));
 }
 
 TEST_F(InstanceRegistryTest, GetEnclosingAppWindows) {
-  std::vector<std::unique_ptr<apps::Instance>> deltas;
   apps::InstanceRegistry instance_registry;
 
   aura::test::TestWindowDelegate window_delegate;
@@ -732,25 +669,17 @@
   aura::Window parent2(&window_delegate);
   parent2.Init(ui::LAYER_NOT_DRAWN);
 
-  deltas.push_back(MakeInstance("a", MakeInstanceKeyWebApp(&child1)));
-  deltas.push_back(MakeInstance("b", MakeInstanceKeyWebApp(&child2)));
-  deltas.push_back(MakeInstance("c", MakeInstanceKeyWebApp(&parent2)));
-  instance_registry.OnInstances(std::move(deltas));
+  instance_registry.OnInstance(MakeInstance("a", MakeInstanceKey(&child1)));
+  instance_registry.OnInstance(MakeInstance("b", MakeInstanceKey(&child2)));
+  instance_registry.OnInstance(MakeInstance("c", MakeInstanceKey(&parent2)));
 
-  EXPECT_TRUE(instance_registry.GetInstanceKeys("a") ==
-              (std::set<const apps::Instance::InstanceKey>{
-                  MakeInstanceKeyWebApp(&child1)}));
-  EXPECT_TRUE(instance_registry.GetInstanceKeys("b") ==
-              (std::set<const apps::Instance::InstanceKey>{
-                  MakeInstanceKeyWebApp(&child2)}));
-  EXPECT_TRUE(instance_registry.GetInstanceKeys("c") ==
-              (std::set<const apps::Instance::InstanceKey>{
-                  MakeInstanceKeyWebApp(&parent2)}));
-
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("a") ==
-              (std::set<aura::Window*>{&parent1}));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("b") ==
-              (std::set<aura::Window*>{&parent1}));
-  EXPECT_TRUE(instance_registry.GetEnclosingAppWindows("c") ==
-              std::set<aura::Window*>{&parent2});
-}
\ No newline at end of file
+  EXPECT_TRUE(
+      instance_registry.GetInstanceKeys("a") ==
+      (std::set<const apps::Instance::InstanceKey>{MakeInstanceKey(&child1)}));
+  EXPECT_TRUE(
+      instance_registry.GetInstanceKeys("b") ==
+      (std::set<const apps::Instance::InstanceKey>{MakeInstanceKey(&child2)}));
+  EXPECT_TRUE(
+      instance_registry.GetInstanceKeys("c") ==
+      (std::set<const apps::Instance::InstanceKey>{MakeInstanceKey(&parent2)}));
+}
diff --git a/components/services/app_service/public/cpp/instance_update.cc b/components/services/app_service/public/cpp/instance_update.cc
index 6634810..16be63cf 100644
--- a/components/services/app_service/public/cpp/instance_update.cc
+++ b/components/services/app_service/public/cpp/instance_update.cc
@@ -61,15 +61,11 @@
     return false;
   }
 
-  // TODO(crbug.com/1251501): Remove GetInstanceKey.
   if ((delta->AppId() != state->AppId()) ||
-      delta->InstanceId() != state->InstanceId() ||
-      delta->GetInstanceKey() != state->GetInstanceKey()) {
+      delta->InstanceId() != state->InstanceId()) {
     LOG(ERROR) << "inconsistent (app_id, instance_id, instance_key): ("
-               << delta->AppId() << ", " << delta->InstanceId() << ", "
-               << delta->GetInstanceKey() << ") vs (" << state->AppId() << ", "
-               << state->InstanceId() << ", " << state->GetInstanceKey()
-               << ") ";
+               << delta->AppId() << ", " << delta->InstanceId() << ") vs ("
+               << state->AppId() << ", " << state->InstanceId() << ") ";
     DCHECK(false);
     return false;
   }
diff --git a/components/shared_highlighting/core/common/BUILD.gn b/components/shared_highlighting/core/common/BUILD.gn
index 1ff96e6..30b33bf 100644
--- a/components/shared_highlighting/core/common/BUILD.gn
+++ b/components/shared_highlighting/core/common/BUILD.gn
@@ -6,16 +6,16 @@
   sources = [
     "disabled_sites.cc",
     "disabled_sites.h",
+    "fragment_directives_constants.cc",
+    "fragment_directives_constants.h",
+    "fragment_directives_utils.cc",
+    "fragment_directives_utils.h",
     "shared_highlighting_features.cc",
     "shared_highlighting_features.h",
     "shared_highlighting_metrics.cc",
     "shared_highlighting_metrics.h",
     "text_fragment.cc",
     "text_fragment.h",
-    "text_fragments_constants.cc",
-    "text_fragments_constants.h",
-    "text_fragments_utils.cc",
-    "text_fragments_utils.h",
   ]
 
   deps = [
@@ -31,9 +31,9 @@
   testonly = true
   sources = [
     "disabled_sites_unittest.cc",
+    "fragment_directives_utils_unittest.cc",
     "shared_highlighting_metrics_unittest.cc",
     "text_fragment_unittest.cc",
-    "text_fragments_utils_unittest.cc",
   ]
   deps = [
     "//base/test:test_support",
diff --git a/components/shared_highlighting/core/common/fragment_directives_constants.cc b/components/shared_highlighting/core/common/fragment_directives_constants.cc
new file mode 100644
index 0000000..65361fc
--- /dev/null
+++ b/components/shared_highlighting/core/common/fragment_directives_constants.cc
@@ -0,0 +1,46 @@
+// 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.
+
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
+
+namespace shared_highlighting {
+
+const char kAnchorDelimiter = '#';
+
+const char kFragmentsUrlDelimiter[] = ":~:";
+const int kFragmentsUrlDelimiterLength = strlen(kFragmentsUrlDelimiter);
+
+const char kTextDirectiveParameterName[] = "text=";
+const size_t kTextDirectiveParameterNameLength =
+    strlen(kTextDirectiveParameterName);
+
+const char kSelectorDirectiveParameterName[] = "selector(";
+const int kSelectorDirectiveParameterNameLength =
+    strlen(kSelectorDirectiveParameterName);
+
+const char kSelectorDirectiveSuffix[] = ")";
+const int kSelectorDirectiveSuffixLength = strlen(kSelectorDirectiveSuffix);
+
+const char kSelectorDirectiveValuePrefix[] = "value=";
+const int kSelectorDirectiveValuePrefixLength =
+    strlen(kSelectorDirectiveValuePrefix);
+
+const char kSelectorDirectiveTypePrefix[] = "type=";
+const int kSelectorDirectiveTypePrefixLength =
+    strlen(kSelectorDirectiveTypePrefix);
+
+const char kTypeCssSelector[] = "CssSelector";
+
+const char kFragmentPrefixKey[] = "prefix";
+const char kFragmentTextStartKey[] = "textStart";
+const char kFragmentTextEndKey[] = "textEnd";
+const char kFragmentSuffixKey[] = "suffix";
+
+// Light purple.
+const int kFragmentTextBackgroundColorARGB = 0xFFE9D2FD;
+
+// Black.
+const int kFragmentTextForegroundColorARGB = 0xFF000000;
+
+}  // namespace shared_highlighting
diff --git a/components/shared_highlighting/core/common/fragment_directives_constants.h b/components/shared_highlighting/core/common/fragment_directives_constants.h
new file mode 100644
index 0000000..8b9a689
--- /dev/null
+++ b/components/shared_highlighting/core/common/fragment_directives_constants.h
@@ -0,0 +1,53 @@
+// 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_SHARED_HIGHLIGHTING_CORE_COMMON_FRAGMENT_DIRECTIVES_CONSTANTS_H_
+#define COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_FRAGMENT_DIRECTIVES_CONSTANTS_H_
+
+#include <string.h>
+
+namespace shared_highlighting {
+
+// Delimiter indicating the start of an anchor in a URL.
+extern const char kAnchorDelimiter;
+
+// Delimiter indicating the start of the text fragments in a URL.
+extern const char kFragmentsUrlDelimiter[];
+extern const int kFragmentsUrlDelimiterLength;
+
+// Parameter name for a single text fragment directive in a URL.
+extern const char kTextDirectiveParameterName[];
+extern const size_t kTextDirectiveParameterNameLength;
+
+// Parameter name for a single selector fragment directive in a URL.
+extern const char kSelectorDirectiveParameterName[];
+extern const int kSelectorDirectiveParameterNameLength;
+
+extern const char kSelectorDirectiveSuffix[];
+extern const int kSelectorDirectiveSuffixLength;
+
+extern const char kSelectorDirectiveValuePrefix[];
+extern const int kSelectorDirectiveValuePrefixLength;
+
+extern const char kSelectorDirectiveTypePrefix[];
+extern const int kSelectorDirectiveTypePrefixLength;
+
+extern const char kTypeCssSelector[];
+
+// These values correspond to the keys used to store text fragment's values
+// in a dictionary Value.
+extern const char kFragmentPrefixKey[];
+extern const char kFragmentTextStartKey[];
+extern const char kFragmentTextEndKey[];
+extern const char kFragmentSuffixKey[];
+
+// Default highlight color stored as a hexadecimal number.
+extern const int kFragmentTextBackgroundColorARGB;
+
+// Default text color stored as a hexadecimal number.
+extern const int kFragmentTextForegroundColorARGB;
+
+}  // namespace shared_highlighting
+
+#endif  // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_FRAGMENT_DIRECTIVES_CONSTANTS_H_
diff --git a/components/shared_highlighting/core/common/text_fragments_utils.cc b/components/shared_highlighting/core/common/fragment_directives_utils.cc
similarity index 71%
rename from components/shared_highlighting/core/common/text_fragments_utils.cc
rename to components/shared_highlighting/core/common/fragment_directives_utils.cc
index d77e21aa..a331e93 100644
--- a/components/shared_highlighting/core/common/text_fragments_utils.cc
+++ b/components/shared_highlighting/core/common/fragment_directives_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 "components/shared_highlighting/core/common/text_fragments_utils.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
 
 #include <string.h>
 
@@ -10,10 +10,11 @@
 
 #include "base/json/json_writer.h"
 #include "base/strings/escape.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #include "components/shared_highlighting/core/common/text_fragment.h"
-#include "components/shared_highlighting/core/common/text_fragments_constants.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace shared_highlighting {
@@ -55,8 +56,8 @@
   *webpage_url = GURL(full_url.substr(0, pos - 1));
 
   // We only want to keep what's after the delimiter.
-  *highlight_directive = full_url.substr(pos + strlen(kFragmentsUrlDelimiter) +
-                                         strlen(kFragmentParameterName));
+  *highlight_directive = full_url.substr(pos + kFragmentsUrlDelimiterLength +
+                                         kTextDirectiveParameterNameLength);
   return true;
 }
 
@@ -64,15 +65,15 @@
   size_t start_pos = ref_string.find(kFragmentsUrlDelimiter);
   if (start_pos == std::string::npos)
     return {};
-  ref_string.erase(0, start_pos + strlen(kFragmentsUrlDelimiter));
+  ref_string.erase(0, start_pos + kFragmentsUrlDelimiterLength);
 
   std::vector<std::string> fragment_strings;
   while (ref_string.size()) {
     // Consume everything up to and including the text= prefix
-    size_t prefix_pos = ref_string.find(kFragmentParameterName);
+    size_t prefix_pos = ref_string.find(kTextDirectiveParameterName);
     if (prefix_pos == std::string::npos)
       break;
-    ref_string.erase(0, prefix_pos + strlen(kFragmentParameterName));
+    ref_string.erase(0, prefix_pos + kTextDirectiveParameterNameLength);
 
     // A & indicates the end of the fragment (and the start of the next).
     // Save everything up to this point, and then consume it (including the &).
@@ -86,7 +87,9 @@
   return fragment_strings;
 }
 
-GURL RemoveTextFragments(const GURL& url) {
+GURL RemoveFragmentSelectorDirectives(const GURL& url) {
+  const std::vector<base::StringPiece> directive_parameter_names{
+      kTextDirectiveParameterName, kSelectorDirectiveParameterName};
   size_t start_pos = url.ref().find(kFragmentsUrlDelimiter);
   if (start_pos == std::string::npos)
     return url;
@@ -94,29 +97,35 @@
   // Split url before and after the ":~:" delimiter.
   std::string fragment_prefix = url.ref().substr(0, start_pos);
   std::string fragment_directive =
-      url.ref().substr(start_pos + strlen(kFragmentsUrlDelimiter));
+      url.ref().substr(start_pos + kFragmentsUrlDelimiterLength);
 
-  // Split fragment directive on "&" and remove all pieces that start with
-  // "text="
-  std::vector<std::string> fragment_strings;
-  for (const std::string& fragment :
+  // Split fragment directive on "&" and remove any piece that starts with
+  // one of the directive_parameter_names
+  std::vector<std::string> should_keep_directives;
+  for (const std::string& directive :
        base::SplitString(fragment_directive, "&", base::TRIM_WHITESPACE,
                          base::SPLIT_WANT_ALL)) {
-    if (fragment.substr(0, strlen(kFragmentParameterName)) !=
-        kFragmentParameterName) {
-      fragment_strings.push_back(fragment);
+    if (std::none_of(
+            directive_parameter_names.begin(), directive_parameter_names.end(),
+            [&directive](const base::StringPiece& directive_parameter_name) {
+              return base::StartsWith(directive, directive_parameter_name);
+            })) {
+      should_keep_directives.push_back(directive);
     }
   }
 
   // Join remaining pieces and append to the url.
-  std::string new_fragment = fragment_prefix;
-  if (!fragment_strings.empty()) {
-    new_fragment +=
-        kFragmentsUrlDelimiter + base::JoinString(fragment_strings, "&");
-  }
+  std::string new_fragment =
+      should_keep_directives.empty()
+          ? fragment_prefix
+          : base::StrCat({fragment_prefix, kFragmentsUrlDelimiter,
+                          base::JoinString(should_keep_directives, "&")});
 
   GURL::Replacements replacements;
-  replacements.SetRefStr(new_fragment);
+  if (new_fragment.empty())
+    replacements.ClearRef();
+  else
+    replacements.SetRefStr(new_fragment);
   return url.ReplaceComponents(replacements);
 }
 
@@ -144,7 +153,7 @@
   std::vector<std::string> fragment_strings;
   for (std::string& selector : selectors) {
     if (!selector.empty()) {
-      fragment_strings.push_back(kFragmentParameterName + selector);
+      fragment_strings.push_back(kTextDirectiveParameterName + selector);
     }
   }
 
@@ -165,8 +174,8 @@
   } else {
     // The URL already had the :~: delimiter, so remove what comes after before
     // adding the new fragment(s).
-    new_ref = new_ref.substr(0, new_ref.find(kFragmentsUrlDelimiter) +
-                                    strlen(kFragmentsUrlDelimiter));
+    new_ref = new_ref.substr(
+        0, new_ref.find(kFragmentsUrlDelimiter) + kFragmentsUrlDelimiterLength);
   }
 
   new_ref += fragments_string;
diff --git a/components/shared_highlighting/core/common/text_fragments_utils.h b/components/shared_highlighting/core/common/fragment_directives_utils.h
similarity index 85%
rename from components/shared_highlighting/core/common/text_fragments_utils.h
rename to components/shared_highlighting/core/common/fragment_directives_utils.h
index 25de3d2d..efc95098 100644
--- a/components/shared_highlighting/core/common/text_fragments_utils.h
+++ b/components/shared_highlighting/core/common/fragment_directives_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 COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_UTILS_H_
-#define COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_UTILS_H_
+#ifndef COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_FRAGMENT_DIRECTIVES_UTILS_H_
+#define COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_FRAGMENT_DIRECTIVES_UTILS_H_
 
 #include <vector>
 
@@ -27,14 +27,14 @@
 
 // Checks the fragment portion of the URL for Text Fragments. Returns zero or
 // more dictionaries containing the parsed parameters used by the fragment-
-// finding algorithm, as defined in the spec.J
+// finding algorithm, as defined in the spec.
 base::Value ParseTextFragments(const GURL& url);
 
 // Extracts the text fragments, if any, from a ref string.
 std::vector<std::string> ExtractTextFragments(std::string ref_string);
 
-// Remove the text fragment selectors, if any, from url.
-GURL RemoveTextFragments(const GURL& url);
+// Remove fragment selector directives, if any, from url.
+GURL RemoveFragmentSelectorDirectives(const GURL& url);
 
 // Appends a set of text |fragments| with the correct format to the given
 // |base_url|. Returns an empty GURL if |base_url| is invalid.
@@ -66,4 +66,4 @@
 
 }  // namespace shared_highlighting
 
-#endif  // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_UTILS_H_
+#endif  // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_FRAGMENT_DIRECTIVES_UTILS_H_
diff --git a/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc b/components/shared_highlighting/core/common/fragment_directives_utils_unittest.cc
similarity index 88%
rename from components/shared_highlighting/core/common/text_fragments_utils_unittest.cc
rename to components/shared_highlighting/core/common/fragment_directives_utils_unittest.cc
index 9a28da49..11643166 100644
--- a/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc
+++ b/components/shared_highlighting/core/common/fragment_directives_utils_unittest.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 "components/shared_highlighting/core/common/text_fragments_utils.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
 
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #include "components/shared_highlighting/core/common/text_fragment.h"
-#include "components/shared_highlighting/core/common/text_fragments_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -93,46 +93,47 @@
 TEST(TextFragmentsUtilsTest, RemoveTextFragments) {
   GURL url_with_fragment(
       "https://www.example.com/#idFrag:~:text=text%201&text=text%202");
-  GURL result = RemoveTextFragments(url_with_fragment);
+  GURL result = RemoveFragmentSelectorDirectives(url_with_fragment);
   EXPECT_EQ("https://www.example.com/#idFrag", result.spec());
 }
 
-TEST(TextFragmentsUtilsTest, RemoveTextFragmentsAndKeepOtherSelectors) {
+TEST(TextFragmentsUtilsTest,
+     RemoveTextFragmentsAndSelectorFragmentsAndKeepOtherSelectors) {
   GURL url_with_fragment(R"(
-      https://www.example.org#:~:text=foo&selector(type=CssSelector,value=img[src$="example.org"]))");
+      https://www.example.org#:~:text=foo&lorem_directive_string&selector(type=CssSelector,value=img[src$="example.org"]))");
   GURL url_with_fragment_removed(R"(
-      https://www.example.org#:~:selector(type=CssSelector,value=img[src$="example.org"]))");
-  GURL result = RemoveTextFragments(url_with_fragment);
+      https://www.example.org#:~:lorem_directive_string)");
+  GURL result = RemoveFragmentSelectorDirectives(url_with_fragment);
   EXPECT_EQ(url_with_fragment_removed.spec(), result.spec());
 
   url_with_fragment = GURL{
-      R"(https://www.example.org#:~:selector(type=CssSelector,value=img[src$="example.org"]))"};
-  result = RemoveTextFragments(url_with_fragment);
+      R"(https://www.example.org#:~:lorem_directive_string&selector(type=CssSelector,value=img[src$="example.org"]))"};
+  result = RemoveFragmentSelectorDirectives(url_with_fragment);
   EXPECT_EQ(url_with_fragment_removed.spec(), result.spec());
 }
 
 TEST(TextFragmentsUtilsTest, RemoveTextFragmentsWithNoFragments) {
   GURL url_without_fragment("https://www.example.com/no_fragment");
-  GURL result = RemoveTextFragments(url_without_fragment);
+  GURL result = RemoveFragmentSelectorDirectives(url_without_fragment);
   EXPECT_EQ("https://www.example.com/no_fragment", result.spec());
 }
 
 TEST(TextFragmentsUtilsTest, RemoveTextFragmentsParameterBeforeDelimiter) {
   GURL url("https://www.example.com/?text=foo#:~:bar");
-  GURL result = RemoveTextFragments(url);
+  GURL result = RemoveFragmentSelectorDirectives(url);
   EXPECT_EQ("https://www.example.com/?text=foo#:~:bar", result.spec());
 }
 
 TEST(TextFragmentsUtilsTest, RemoveTextFragmentsParameterIsSubstring) {
   GURL url("https://www.example.com/#:~:case_insensitive_text=foo");
-  GURL result = RemoveTextFragments(url);
+  GURL result = RemoveFragmentSelectorDirectives(url);
   EXPECT_EQ("https://www.example.com/#:~:case_insensitive_text=foo",
             result.spec());
 }
 
 TEST(TextFragmentsUtilsTest, RemoveTextFragmentsWithNonTextFragment) {
   GURL url("https://example.com/?not_a_frag_directive:~:#no_text_fragments");
-  GURL result = RemoveTextFragments(url);
+  GURL result = RemoveFragmentSelectorDirectives(url);
   EXPECT_EQ("https://example.com/?not_a_frag_directive:~:#no_text_fragments",
             result.spec());
 }
@@ -141,7 +142,7 @@
   GURL url(
       "https://example.com/"
       "?not_a_frag_directive:~:#no_text_fragments:~:text=test,frag");
-  GURL result = RemoveTextFragments(url);
+  GURL result = RemoveFragmentSelectorDirectives(url);
   EXPECT_EQ("https://example.com/?not_a_frag_directive:~:#no_text_fragments",
             result.spec());
 }
diff --git a/components/shared_highlighting/core/common/text_fragment.cc b/components/shared_highlighting/core/common/text_fragment.cc
index f7eeb49d..24b09b8 100644
--- a/components/shared_highlighting/core/common/text_fragment.cc
+++ b/components/shared_highlighting/core/common/text_fragment.cc
@@ -8,7 +8,7 @@
 
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "components/shared_highlighting/core/common/text_fragments_constants.h"
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #include "net/base/escape.h"
 
 namespace {
@@ -137,7 +137,7 @@
     return std::string();
   }
   std::stringstream ss;
-  ss << kFragmentParameterName;
+  ss << kTextDirectiveParameterName;
 
   if (!prefix_.empty()) {
     ss << Escape(prefix_) << "-,";
diff --git a/components/shared_highlighting/core/common/text_fragment_unittest.cc b/components/shared_highlighting/core/common/text_fragment_unittest.cc
index e9cec761..c46db6cc 100644
--- a/components/shared_highlighting/core/common/text_fragment_unittest.cc
+++ b/components/shared_highlighting/core/common/text_fragment_unittest.cc
@@ -5,7 +5,7 @@
 #include "components/shared_highlighting/core/common/text_fragment.h"
 
 #include "base/values.h"
-#include "components/shared_highlighting/core/common/text_fragments_constants.h"
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
diff --git a/components/shared_highlighting/core/common/text_fragments_constants.cc b/components/shared_highlighting/core/common/text_fragments_constants.cc
deleted file mode 100644
index 8299573..0000000
--- a/components/shared_highlighting/core/common/text_fragments_constants.cc
+++ /dev/null
@@ -1,26 +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.
-
-#include "components/shared_highlighting/core/common/text_fragments_constants.h"
-
-namespace shared_highlighting {
-
-const char kAnchorDelimiter = '#';
-
-const char kFragmentsUrlDelimiter[] = ":~:";
-
-const char kFragmentParameterName[] = "text=";
-
-const char kFragmentPrefixKey[] = "prefix";
-const char kFragmentTextStartKey[] = "textStart";
-const char kFragmentTextEndKey[] = "textEnd";
-const char kFragmentSuffixKey[] = "suffix";
-
-// Light purple.
-const int kFragmentTextBackgroundColorARGB = 0xFFE9D2FD;
-
-// Black.
-const int kFragmentTextForegroundColorARGB = 0xFF000000;
-
-}  // namespace shared_highlighting
diff --git a/components/shared_highlighting/core/common/text_fragments_constants.h b/components/shared_highlighting/core/common/text_fragments_constants.h
deleted file mode 100644
index 096cdfd..0000000
--- a/components/shared_highlighting/core/common/text_fragments_constants.h
+++ /dev/null
@@ -1,34 +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_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_CONSTANTS_H_
-#define COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_CONSTANTS_H_
-
-namespace shared_highlighting {
-
-// Delimiter indicating the start of an anchor in a URL.
-extern const char kAnchorDelimiter;
-
-// Delimiter indicating the start of the text fragments in a URL.
-extern const char kFragmentsUrlDelimiter[];
-
-// Parameter name for a single text fragment in a URL.
-extern const char kFragmentParameterName[];
-
-// These values correspond to the keys used to store text fragment's values
-// in a dictionary Value.
-extern const char kFragmentPrefixKey[];
-extern const char kFragmentTextStartKey[];
-extern const char kFragmentTextEndKey[];
-extern const char kFragmentSuffixKey[];
-
-// Default highlight color stored as a hexadecimal number.
-extern const int kFragmentTextBackgroundColorARGB;
-
-// Default text color stored as a hexadecimal number.
-extern const int kFragmentTextForegroundColorARGB;
-
-}  // namespace shared_highlighting
-
-#endif  // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_CONSTANTS_H_
diff --git a/components/site_engagement/content/site_engagement_service.h b/components/site_engagement/content/site_engagement_service.h
index 16dacd63..ceb1980 100644
--- a/components/site_engagement/content/site_engagement_service.h
+++ b/components/site_engagement/content/site_engagement_service.h
@@ -16,6 +16,7 @@
 #include "components/browsing_data/core/browsing_data_utils.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/site_engagement/core/mojom/site_engagement_details.mojom.h"
+#include "components/site_engagement/core/site_engagement_score_provider.h"
 #include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
 #include "ui/base/page_transition_types.h"
 
@@ -50,16 +51,6 @@
 class SiteEngagementServiceAndroid;
 #endif
 
-class SiteEngagementScoreProvider {
- public:
-  // Returns a non-negative integer representing the engagement score of the
-  // origin for this URL.
-  virtual double GetScore(const GURL& url) const = 0;
-
-  // Returns the sum of engagement points awarded to all sites.
-  virtual double GetTotalEngagementPoints() const = 0;
-};
-
 // Stores and retrieves the engagement score of an origin.
 //
 // An engagement score is a non-negative double that represents how much a user
diff --git a/components/site_engagement/core/BUILD.gn b/components/site_engagement/core/BUILD.gn
index dbf7d35..50fe627 100644
--- a/components/site_engagement/core/BUILD.gn
+++ b/components/site_engagement/core/BUILD.gn
@@ -6,5 +6,6 @@
   sources = [
     "pref_names.cc",
     "pref_names.h",
+    "site_engagement_score_provider.h",
   ]
 }
diff --git a/components/site_engagement/core/site_engagement_score_provider.h b/components/site_engagement/core/site_engagement_score_provider.h
new file mode 100644
index 0000000..f80bd44b
--- /dev/null
+++ b/components/site_engagement/core/site_engagement_score_provider.h
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SITE_ENGAGEMENT_CORE_SITE_ENGAGEMENT_SCORE_PROVIDER_H_
+#define COMPONENTS_SITE_ENGAGEMENT_CORE_SITE_ENGAGEMENT_SCORE_PROVIDER_H_
+
+class GURL;
+
+namespace site_engagement {
+
+class SiteEngagementScoreProvider {
+ public:
+  // Returns a non-negative integer representing the engagement score of the
+  // origin for this URL.
+  virtual double GetScore(const GURL& url) const = 0;
+
+  // Returns the sum of engagement points awarded to all sites.
+  virtual double GetTotalEngagementPoints() const = 0;
+};
+
+}  // namespace site_engagement
+
+#endif  // COMPONENTS_SITE_ENGAGEMENT_CORE_SITE_ENGAGEMENT_SCORE_PROVIDER_H_
diff --git a/components/ssl_errors/error_info.cc b/components/ssl_errors/error_info.cc
index 5e3dfa0..79dda76 100644
--- a/components/ssl_errors/error_info.cc
+++ b/components/ssl_errors/error_info.cc
@@ -177,12 +177,6 @@
       short_description = l10n_util::GetStringUTF16(
           IDS_CERT_ERROR_CERTIFICATE_TRANSPARENCY_REQUIRED_DESCRIPTION);
       break;
-    case LEGACY_TLS:
-      details =
-          l10n_util::GetStringUTF16(IDS_SSL_ERROR_OBSOLETE_VERSION_DETAILS);
-      short_description =
-          l10n_util::GetStringUTF16(IDS_SSL_ERROR_OBSOLETE_VERSION_DESCRIPTION);
-      break;
     case UNKNOWN:
       details = l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS);
       short_description =
@@ -231,8 +225,6 @@
       return CERT_SYMANTEC_LEGACY;
     case net::ERR_CERT_KNOWN_INTERCEPTION_BLOCKED:
       return CERT_KNOWN_INTERCEPTION_BLOCKED;
-    case net::ERR_SSL_OBSOLETE_VERSION:
-      return LEGACY_TLS;
     default:
       NOTREACHED();
       return UNKNOWN;
@@ -260,7 +252,6 @@
       net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED,
       net::CERT_STATUS_SYMANTEC_LEGACY,
       net::CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED,
-      net::CERT_STATUS_LEGACY_TLS,
   };
 
   const ErrorType kErrorTypes[] = {
@@ -278,7 +269,6 @@
       CERTIFICATE_TRANSPARENCY_REQUIRED,
       CERT_SYMANTEC_LEGACY,
       CERT_KNOWN_INTERCEPTION_BLOCKED,
-      LEGACY_TLS,
   };
   DCHECK(base::size(kErrorFlags) == base::size(kErrorTypes));
 
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index f9d0c20..3b494843 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -266,7 +266,7 @@
       "display_embedder/gl_output_surface_chromeos.cc",
       "display_embedder/gl_output_surface_chromeos.h",
     ]
-    deps += [ "//components/arc/video_accelerator" ]
+    deps += [ "//ash/components/arc/video_accelerator" ]
   }
 
   if (is_chromecast) {
@@ -442,7 +442,7 @@
 
   if (is_chromeos_ash) {
     deps += [
-      "//components/arc/video_accelerator",
+      "//ash/components/arc/video_accelerator",
       "//components/chromeos_camera:jpeg_encode_accelerator_service",
       "//components/chromeos_camera:mjpeg_decode_accelerator_service",
       "//gpu/command_buffer/service:gles2",
diff --git a/components/viz/service/display/display_resource_provider_skia.cc b/components/viz/service/display/display_resource_provider_skia.cc
index e013ffb..ff13003 100644
--- a/components/viz/service/display/display_resource_provider_skia.cc
+++ b/components/viz/service/display/display_resource_provider_skia.cc
@@ -146,8 +146,13 @@
         // HDR video color conversion is handled externally in SkiaRenderer
         // using a special color filter and |color_space| is set to destination
         // color space so that Skia doesn't perform implicit color conversion.
+
+        // TODO(https://crbug.com/1271212): Skia doesn't support limited range
+        // color spaces, so we treat it as fullrange, resulting color difference
+        // is very subtle.
         image_color_space =
-            override_color_space.value_or(resource.transferable.color_space)
+            override_color_space
+                .value_or(resource.transferable.color_space.GetAsFullRangeRGB())
                 .ToSkColorSpace();
       }
       resource.image_context =
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index e4566609..fde8c1b2 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -2644,7 +2644,11 @@
                       const PrimaryPlane* primary_plane,
                       OverlayCandidateList* candidates,
                       std::vector<gfx::Rect>* content_bounds,
-                      OverlayProposedCandidate* proposed_candidate));
+                      const OverlayProposedCandidate& proposed_candidate));
+
+    MOCK_METHOD2(CommitCandidate,
+                 void(const OverlayProposedCandidate& proposed_candidate,
+                      AggregatedRenderPass* render_pass));
   };
 
   bool IsOverlaySupported() const override { return true; }
@@ -3877,12 +3881,15 @@
         const PrimaryPlane* primary_plane,
         OverlayCandidateList* candidates,
         std::vector<gfx::Rect>* content_bounds,
-        OverlayProposedCandidate* proposed_candidate) override {
+        const OverlayProposedCandidate& proposed_candidate) override {
       content_bounds->insert(content_bounds->end(), content_bounds_.begin(),
                              content_bounds_.end());
       return true;
     }
 
+    void CommitCandidate(const OverlayProposedCandidate& proposed_candidate,
+                         AggregatedRenderPass* render_pass) override {}
+
    private:
     const std::vector<gfx::Rect> content_bounds_;
   };
diff --git a/components/viz/service/display/overlay_processor_using_strategy.cc b/components/viz/service/display/overlay_processor_using_strategy.cc
index bd0c247..b9a333f 100644
--- a/components/viz/service/display/overlay_processor_using_strategy.cc
+++ b/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -483,7 +483,7 @@
     bool used_overlay = candidate.strategy->AttemptPrioritized(
         output_color_matrix, render_pass_backdrop_filters, resource_provider,
         render_pass_list, surface_damage_rect_list, primary_plane, candidates,
-        content_bounds, &candidate);
+        content_bounds, candidate);
     if (!used_overlay && candidate.candidate.requires_overlay) {
       // Check if we likely failed due to scaling capabilities, and if so, try
       // to adjust things to make it work. We do this by tracking what scale
@@ -512,7 +512,7 @@
           if (candidate.strategy->AttemptPrioritized(
                   output_color_matrix, render_pass_backdrop_filters,
                   resource_provider, render_pass_list, surface_damage_rect_list,
-                  primary_plane, candidates, content_bounds, &candidate)) {
+                  primary_plane, candidates, content_bounds, candidate)) {
             used_overlay = true;
             break;
           } else {
diff --git a/components/viz/service/display/overlay_processor_using_strategy.h b/components/viz/service/display/overlay_processor_using_strategy.h
index 7b1a7d4..4aab7a2 100644
--- a/components/viz/service/display/overlay_processor_using_strategy.h
+++ b/components/viz/service/display/overlay_processor_using_strategy.h
@@ -99,7 +99,13 @@
         const PrimaryPlane* primary_plane,
         OverlayCandidateList* candidates,
         std::vector<gfx::Rect>* content_bounds,
-        OverlayProposedCandidate* proposed_candidate) = 0;
+        const OverlayProposedCandidate& proposed_candidate) = 0;
+
+    // Commits to using the proposed candidate by updating |render_pass| as
+    // appropriate when this candidate is presented in an overlay plane.
+    virtual void CommitCandidate(
+        const OverlayProposedCandidate& proposed_candidate,
+        AggregatedRenderPass* render_pass) = 0;
 
     // Currently this is only overridden by the Underlay strategy: the underlay
     // strategy needs to enable blending for the primary plane in order to show
diff --git a/components/viz/service/display/overlay_strategy_fullscreen.cc b/components/viz/service/display/overlay_strategy_fullscreen.cc
index 8f00510f..3dcbaf9 100644
--- a/components/viz/service/display/overlay_strategy_fullscreen.cc
+++ b/components/viz/service/display/overlay_strategy_fullscreen.cc
@@ -72,7 +72,9 @@
 
   candidate_list->swap(new_candidate_list);
 
-  render_pass->quad_list = QuadList();  // Remove all the quads
+  OverlayProposedCandidate proposed_candidate(front, candidate, this);
+  CommitCandidate(proposed_candidate, render_pass);
+
   return true;
 }
 
@@ -131,22 +133,28 @@
     const PrimaryPlane* primary_plane,
     OverlayCandidateList* candidate_list,
     std::vector<gfx::Rect>* content_bounds,
-    OverlayProposedCandidate* proposed_candidate) {
+    const OverlayProposedCandidate& proposed_candidate) {
   // Before we attempt an overlay strategy, the candidate list should be empty.
   DCHECK(candidate_list->empty());
 
   OverlayCandidateList new_candidate_list;
-  new_candidate_list.push_back(proposed_candidate->candidate);
+  new_candidate_list.push_back(proposed_candidate.candidate);
   capability_checker_->CheckOverlaySupport(primary_plane, &new_candidate_list);
   if (!new_candidate_list.front().overlay_handled)
     return false;
 
   candidate_list->swap(new_candidate_list);
   auto* render_pass = render_pass_list->back().get();
-  render_pass->quad_list = QuadList();  // Remove all the quads
+  CommitCandidate(proposed_candidate, render_pass);
   return true;
 }
 
+void OverlayStrategyFullscreen::CommitCandidate(
+    const OverlayProposedCandidate& proposed_candidate,
+    AggregatedRenderPass* render_pass) {
+  render_pass->quad_list = QuadList();  // Remove all the quads
+}
+
 OverlayStrategy OverlayStrategyFullscreen::GetUMAEnum() const {
   return OverlayStrategy::kFullscreen;
 }
diff --git a/components/viz/service/display/overlay_strategy_fullscreen.h b/components/viz/service/display/overlay_strategy_fullscreen.h
index a98f565..3b30d52f 100644
--- a/components/viz/service/display/overlay_strategy_fullscreen.h
+++ b/components/viz/service/display/overlay_strategy_fullscreen.h
@@ -56,7 +56,10 @@
       const PrimaryPlane* primary_plane,
       OverlayCandidateList* candidates,
       std::vector<gfx::Rect>* content_bounds,
-      OverlayProposedCandidate* proposed_candidate) override;
+      const OverlayProposedCandidate& proposed_candidate) override;
+
+  void CommitCandidate(const OverlayProposedCandidate& proposed_candidate,
+                       AggregatedRenderPass* render_pass) override;
 
   bool RemoveOutputSurfaceAsOverlay() override;
   OverlayStrategy GetUMAEnum() const override;
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.cc b/components/viz/service/display/overlay_strategy_single_on_top.cc
index 9f38592b..8dd4ca5 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -62,8 +62,10 @@
   if (best_quad_it == quad_list->end())
     return false;
 
-  if (TryOverlay(quad_list, primary_plane, candidate_list, best_candidate,
-                 best_quad_it)) {
+  OverlayProposedCandidate proposed_candidate(best_quad_it, best_candidate,
+                                              this);
+  if (TryOverlay(render_pass, primary_plane, candidate_list,
+                 proposed_candidate)) {
     if (previous_frame_resource_id_ != best_candidate.resource_id) {
       previous_frame_resource_id_ = best_candidate.resource_id;
       same_resource_id_frames_count_ = 1;
@@ -113,27 +115,24 @@
     const PrimaryPlane* primary_plane,
     OverlayCandidateList* candidate_list,
     std::vector<gfx::Rect>* content_bounds,
-    OverlayProposedCandidate* proposed_candidate) {
+    const OverlayProposedCandidate& proposed_candidate) {
   // Before we attempt an overlay strategy, we shouldn't have a candidate.
   DCHECK(candidate_list->empty());
   auto* render_pass = render_pass_list->back().get();
-  QuadList* quad_list = &render_pass->quad_list;
-  return TryOverlay(quad_list, primary_plane, candidate_list,
-                    proposed_candidate->candidate,
-                    proposed_candidate->quad_iter);
+  return TryOverlay(render_pass, primary_plane, candidate_list,
+                    proposed_candidate);
 }
 
 bool OverlayStrategySingleOnTop::TryOverlay(
-    QuadList* quad_list,
+    AggregatedRenderPass* render_pass,
     const PrimaryPlane* primary_plane,
     OverlayCandidateList* candidate_list,
-    const OverlayCandidate& candidate,
-    QuadList::Iterator candidate_iterator) {
+    const OverlayProposedCandidate& proposed_candidate) {
   // SingleOnTop strategy means we should have one candidate.
   DCHECK(candidate_list->empty());
   // Add the overlay.
   OverlayCandidateList new_candidate_list = *candidate_list;
-  new_candidate_list.push_back(candidate);
+  new_candidate_list.push_back(proposed_candidate.candidate);
   new_candidate_list.back().plane_z_order = 1;
 
   // Check for support.
@@ -142,7 +141,7 @@
   const OverlayCandidate& overlay_candidate = new_candidate_list.back();
   // If the candidate can be handled by an overlay, create a pass for it.
   if (overlay_candidate.overlay_handled) {
-    quad_list->EraseAndInvalidateAllPointers(candidate_iterator);
+    CommitCandidate(proposed_candidate, render_pass);
     candidate_list->swap(new_candidate_list);
     return true;
   }
@@ -150,6 +149,13 @@
   return false;
 }
 
+void OverlayStrategySingleOnTop::CommitCandidate(
+    const OverlayProposedCandidate& proposed_candidate,
+    AggregatedRenderPass* render_pass) {
+  render_pass->quad_list.EraseAndInvalidateAllPointers(
+      proposed_candidate.quad_iter);
+}
+
 OverlayStrategy OverlayStrategySingleOnTop::GetUMAEnum() const {
   return OverlayStrategy::kSingleOnTop;
 }
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.h b/components/viz/service/display/overlay_strategy_single_on_top.h
index d3958d0..3c0122e 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.h
+++ b/components/viz/service/display/overlay_strategy_single_on_top.h
@@ -55,18 +55,20 @@
       const PrimaryPlane* primary_plane,
       OverlayCandidateList* candidates,
       std::vector<gfx::Rect>* content_bounds,
-      OverlayProposedCandidate* proposed_candidate) override;
+      const OverlayProposedCandidate& proposed_candidate) override;
+
+  void CommitCandidate(const OverlayProposedCandidate& proposed_candidate,
+                       AggregatedRenderPass* render_pass) override;
 
   OverlayStrategy GetUMAEnum() const override;
 
  private:
   static constexpr size_t kMaxFrameCandidateWithSameResourceId = 3;
 
-  bool TryOverlay(QuadList* quad_list,
+  bool TryOverlay(AggregatedRenderPass* render_pass,
                   const PrimaryPlane* primary_plane,
                   OverlayCandidateList* candidate_list,
-                  const OverlayCandidate& candidate,
-                  QuadList::Iterator candidate_iterator);
+                  const OverlayProposedCandidate& proposed_candidate);
 
   OverlayProcessorUsingStrategy* capability_checker_;  // Weak.
 
diff --git a/components/viz/service/display/overlay_strategy_underlay.cc b/components/viz/service/display/overlay_strategy_underlay.cc
index cf65382c..9a59522b 100644
--- a/components/viz/service/display/overlay_strategy_underlay.cc
+++ b/components/viz/service/display/overlay_strategy_underlay.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "components/viz/common/quads/aggregated_render_pass.h"
 #include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/service/display/display_resource_provider.h"
@@ -77,13 +78,8 @@
     // If the candidate can be handled by an overlay, create a pass for it. We
     // need to switch out the video quad with an underlay hole quad.
     if (new_candidate_list.back().overlay_handled) {
-      if (candidate.has_mask_filter) {
-        render_pass->ReplaceExistingQuadWithSolidColor(it, SK_ColorBLACK,
-                                                       SkBlendMode::kDstOut);
-      } else {
-        render_pass->ReplaceExistingQuadWithSolidColor(it, SK_ColorTRANSPARENT,
-                                                       SkBlendMode::kSrcOver);
-      }
+      OverlayProposedCandidate proposed_candidate(it, candidate, this);
+      CommitCandidate(proposed_candidate, render_pass);
       candidate_list->swap(new_candidate_list);
       return true;
     }
@@ -144,14 +140,14 @@
     const PrimaryPlane* primary_plane,
     OverlayCandidateList* candidate_list,
     std::vector<gfx::Rect>* content_bounds,
-    OverlayProposedCandidate* proposed_candidate) {
+    const OverlayProposedCandidate& proposed_candidate) {
   // Before we attempt an overlay strategy, the candidate list should be empty.
   DCHECK(candidate_list->empty());
   auto* render_pass = render_pass_list->back().get();
 
   // Add the overlay.
   OverlayCandidateList new_candidate_list = *candidate_list;
-  new_candidate_list.push_back(proposed_candidate->candidate);
+  new_candidate_list.push_back(proposed_candidate.candidate);
   new_candidate_list.back().plane_z_order = -1;
 
   if (primary_plane) {
@@ -169,25 +165,30 @@
     capability_checker_->CheckOverlaySupport(nullptr, &new_candidate_list);
   }
 
-  // If the candidate can be handled by an overlay, create a pass for it. We
-  // need to switch out the video quad with an underlay hole quad.
   if (new_candidate_list.back().overlay_handled) {
-    if (proposed_candidate->candidate.has_mask_filter) {
-      render_pass->ReplaceExistingQuadWithSolidColor(
-          proposed_candidate->quad_iter, SK_ColorBLACK, SkBlendMode::kDstOut);
-    } else {
-      render_pass->ReplaceExistingQuadWithSolidColor(
-          proposed_candidate->quad_iter, SK_ColorTRANSPARENT,
-          SkBlendMode::kSrcOver);
-    }
+    CommitCandidate(proposed_candidate, render_pass);
     candidate_list->swap(new_candidate_list);
-
     return true;
   }
 
   return false;
 }
 
+void OverlayStrategyUnderlay::CommitCandidate(
+    const OverlayProposedCandidate& proposed_candidate,
+    AggregatedRenderPass* render_pass) {
+  // If the candidate can be handled by an overlay, create a pass for it. We
+  // need to switch out the video quad with an underlay hole quad.
+  if (proposed_candidate.candidate.has_mask_filter) {
+    render_pass->ReplaceExistingQuadWithSolidColor(
+        proposed_candidate.quad_iter, SK_ColorBLACK, SkBlendMode::kDstOut);
+  } else {
+    render_pass->ReplaceExistingQuadWithSolidColor(proposed_candidate.quad_iter,
+                                                   SK_ColorTRANSPARENT,
+                                                   SkBlendMode::kSrcOver);
+  }
+}
+
 // Turn on blending for the output surface plane so the underlay could show
 // through.
 void OverlayStrategyUnderlay::AdjustOutputSurfaceOverlay(
diff --git a/components/viz/service/display/overlay_strategy_underlay.h b/components/viz/service/display/overlay_strategy_underlay.h
index 8d5fda81..87618d4 100644
--- a/components/viz/service/display/overlay_strategy_underlay.h
+++ b/components/viz/service/display/overlay_strategy_underlay.h
@@ -69,7 +69,10 @@
       const PrimaryPlane* primary_plane,
       OverlayCandidateList* candidates,
       std::vector<gfx::Rect>* content_bounds,
-      OverlayProposedCandidate* proposed_candidate) override;
+      const OverlayProposedCandidate& proposed_candidate) override;
+
+  void CommitCandidate(const OverlayProposedCandidate& proposed_candidate,
+                       AggregatedRenderPass* render_pass) override;
 
   void AdjustOutputSurfaceOverlay(
       OverlayProcessorInterface::OutputSurfaceOverlayPlane*
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.cc b/components/viz/service/display/overlay_strategy_underlay_cast.cc
index f8c4e3b1..58c2c16 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.cc
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.cc
@@ -115,20 +115,8 @@
         continue;
       }
 
-#if BUILDFLAG(IS_CHROMECAST)
-      DCHECK(GetVideoGeometrySetter());
-      GetVideoGeometrySetter()->SetVideoGeometry(
-          candidate.display_rect, candidate.transform,
-          VideoHoleDrawQuad::MaterialCast(*it)->overlay_plane_id);
-#endif
-
-      if (candidate.has_mask_filter) {
-        render_pass->ReplaceExistingQuadWithSolidColor(it, SK_ColorBLACK,
-                                                       SkBlendMode::kDstOut);
-      } else {
-        render_pass->ReplaceExistingQuadWithSolidColor(it, SK_ColorTRANSPARENT,
-                                                       SkBlendMode::kSrcOver);
-      }
+      OverlayProposedCandidate proposed_candidate(it, candidate, this);
+      CommitCandidate(proposed_candidate, render_pass);
 
       break;
     }
@@ -192,7 +180,7 @@
     const PrimaryPlane* primary_plane,
     OverlayCandidateList* candidate_list,
     std::vector<gfx::Rect>* content_bounds,
-    OverlayProposedCandidate* proposed_candidate) {
+    const OverlayProposedCandidate& proposed_candidate) {
   // Before we attempt an overlay strategy, the candidate list should be empty.
   DCHECK(candidate_list->empty());
   auto* render_pass = render_pass_list->back().get();
@@ -254,20 +242,8 @@
         continue;
       }
 
-#if BUILDFLAG(IS_CHROMECAST)
-      DCHECK(GetVideoGeometrySetter());
-      GetVideoGeometrySetter()->SetVideoGeometry(
-          candidate.display_rect, candidate.transform,
-          VideoHoleDrawQuad::MaterialCast(*it)->overlay_plane_id);
-#endif
-
-      if (candidate.has_mask_filter) {
-        render_pass->ReplaceExistingQuadWithSolidColor(it, SK_ColorBLACK,
-                                                       SkBlendMode::kDstOut);
-      } else {
-        render_pass->ReplaceExistingQuadWithSolidColor(it, SK_ColorTRANSPARENT,
-                                                       SkBlendMode::kSrcOver);
-      }
+      OverlayProposedCandidate proposed_to_commit(it, candidate, this);
+      CommitCandidate(proposed_to_commit, render_pass);
 
       break;
     }
@@ -280,6 +256,28 @@
   return found_underlay;
 }
 
+void OverlayStrategyUnderlayCast::CommitCandidate(
+    const OverlayProposedCandidate& proposed_candidate,
+    AggregatedRenderPass* render_pass) {
+#if BUILDFLAG(IS_CHROMECAST)
+  DCHECK(GetVideoGeometrySetter());
+  GetVideoGeometrySetter()->SetVideoGeometry(
+      proposed_candidate.candidate.display_rect,
+      proposed_candidate.candidate.transform,
+      VideoHoleDrawQuad::MaterialCast(*proposed_candidate.quad_iter)
+          ->overlay_plane_id);
+#endif
+
+  if (proposed_candidate.candidate.has_mask_filter) {
+    render_pass->ReplaceExistingQuadWithSolidColor(
+        proposed_candidate.quad_iter, SK_ColorBLACK, SkBlendMode::kDstOut);
+  } else {
+    render_pass->ReplaceExistingQuadWithSolidColor(proposed_candidate.quad_iter,
+                                                   SK_ColorTRANSPARENT,
+                                                   SkBlendMode::kSrcOver);
+  }
+}
+
 OverlayStrategy OverlayStrategyUnderlayCast::GetUMAEnum() const {
   return OverlayStrategy::kUnderlayCast;
 }
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.h b/components/viz/service/display/overlay_strategy_underlay_cast.h
index 64020b5c..96310b0 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.h
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.h
@@ -61,7 +61,10 @@
       const PrimaryPlane* primary_plane,
       OverlayCandidateList* candidates,
       std::vector<gfx::Rect>* content_bounds,
-      OverlayProposedCandidate* proposed_candidate) override;
+      const OverlayProposedCandidate& proposed_candidate) override;
+
+  void CommitCandidate(const OverlayProposedCandidate& proposed_candidate,
+                       AggregatedRenderPass* render_pass) override;
 
 #if BUILDFLAG(IS_CHROMECAST)
   // In Chromecast build, OverlayStrategyUnderlayCast needs a valid mojo
diff --git a/components/viz/service/gl/DEPS b/components/viz/service/gl/DEPS
index 9ebbd4c8..e67db49 100644
--- a/components/viz/service/gl/DEPS
+++ b/components/viz/service/gl/DEPS
@@ -1,7 +1,7 @@
 # Please consult components/viz/README.md about allowable dependencies.
 
 include_rules = [
-  "+components/arc/video_accelerator",
+  "+ash/components/arc/video_accelerator",
   "+components/chromeos_camera",
   "+components/crash/core/common/crash_key.h",
   "+components/viz/service/service_jni_headers",
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 7186651..1492ea8 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -77,11 +77,11 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
-#include "components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
-#include "components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h"
-#include "components/arc/video_accelerator/protected_buffer_manager.h"
-#include "components/arc/video_accelerator/protected_buffer_manager_proxy.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
+#include "ash/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager.h"
+#include "ash/components/arc/video_accelerator/protected_buffer_manager_proxy.h"
 #include "components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.h"
 #include "components/chromeos_camera/mojo_jpeg_encode_accelerator_service.h"
 #include "components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index b4d1db8..5dc383f 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/buildflag_header.gni")
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/chromeos/ui_mode.gni")
+import("//build/config/compiler/pgo/pgo.gni")
 import("//build/config/features.gni")
 import("//build/config/linux/pangocairo/pangocairo.gni")
 import("//build/config/ozone.gni")
@@ -54,6 +55,7 @@
     "//build:branding_buildflags",
     "//build:chromecast_buildflags",
     "//build:chromeos_buildflags",
+    "//build/config/compiler:compiler_buildflags",
     "//cc",
     "//cc/animation",
     "//cc/mojo_embedder",
@@ -1773,6 +1775,8 @@
     "service_worker/service_worker_script_cache_map.h",
     "service_worker/service_worker_script_loader_factory.cc",
     "service_worker/service_worker_script_loader_factory.h",
+    "service_worker/service_worker_security_utils.cc",
+    "service_worker/service_worker_security_utils.h",
     "service_worker/service_worker_single_script_update_checker.cc",
     "service_worker/service_worker_single_script_update_checker.h",
     "service_worker/service_worker_type_converters.cc",
@@ -2670,6 +2674,8 @@
     sources += [
       "accessibility/accessibility_tree_formatter_android.cc",
       "accessibility/accessibility_tree_formatter_android.h",
+      "accessibility/accessibility_tree_formatter_android_external.cc",
+      "accessibility/accessibility_tree_formatter_android_external.h",
       "accessibility/browser_accessibility_android.cc",
       "accessibility/browser_accessibility_android.h",
       "accessibility/browser_accessibility_manager_android.cc",
@@ -3049,6 +3055,16 @@
       "//services/metrics/public/cpp:ukm_builders",
     ]
   }
+
+  if (use_clang_profiling_inside_sandbox && chrome_pgo_phase == 1) {
+    sources += [
+      "$target_gen_dir/devtools/protocol/native_profiling.cc",
+      "$target_gen_dir/devtools/protocol/native_profiling.h",
+      "devtools/protocol/native_profiling_handler.cc",
+      "devtools/protocol/native_profiling_handler.h",
+      "profiling_utils.cc",
+    ]
+  }
 }
 
 if (is_android) {
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android_external.cc b/content/browser/accessibility/accessibility_tree_formatter_android_external.cc
new file mode 100644
index 0000000..0fa77ce
--- /dev/null
+++ b/content/browser/accessibility/accessibility_tree_formatter_android_external.cc
@@ -0,0 +1,72 @@
+// 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 "content/browser/accessibility/accessibility_tree_formatter_android_external.h"
+
+#include <string>
+
+#include "content/browser/accessibility/browser_accessibility_android.h"
+
+static const char kStringKey[] = "key";
+static const char kErrorMessage[] = "Error";
+
+namespace content {
+
+AccessibilityTreeFormatterAndroidExternal::
+    AccessibilityTreeFormatterAndroidExternal() = default;
+
+AccessibilityTreeFormatterAndroidExternal::
+    ~AccessibilityTreeFormatterAndroidExternal() = default;
+
+base::Value AccessibilityTreeFormatterAndroidExternal::BuildTree(
+    ui::AXPlatformNodeDelegate* root) const {
+  CHECK(root);
+
+  BrowserAccessibility* root_internal =
+      BrowserAccessibility::FromAXPlatformNodeDelegate(root);
+
+  base::DictionaryValue dict;
+  RecursiveBuildTree(*root_internal, &dict);
+  return std::move(dict);
+}
+
+void AccessibilityTreeFormatterAndroidExternal::RecursiveBuildTree(
+    const BrowserAccessibility& node,
+    base::DictionaryValue* dict) const {
+  const BrowserAccessibilityAndroid* android_node =
+      static_cast<const BrowserAccessibilityAndroid*>(&node);
+
+  // If a null string is returned, web contents likely doesn't exist, and it is
+  // a sign that an accessibility service was disable. Print warning and escape.
+  // TODO: It would be interesting to allow filtering here in the future.
+  std::u16string str = android_node->GenerateAccessibilityNodeInfoString();
+  if (str.empty()) {
+    dict->SetString(kStringKey, kErrorMessage);
+    return;
+  }
+
+  dict->SetString(kStringKey, str);
+
+  base::ListValue children;
+
+  for (size_t i = 0; i < node.PlatformChildCount(); ++i) {
+    BrowserAccessibility* child_node = node.PlatformGetChild(i);
+    std::unique_ptr<base::DictionaryValue> child_dict(
+        new base::DictionaryValue);
+    RecursiveBuildTree(*child_node, child_dict.get());
+    children.Append(std::move(child_dict));
+  }
+  dict->SetKey(kChildrenDictAttr, std::move(children));
+}
+
+std::string AccessibilityTreeFormatterAndroidExternal::ProcessTreeForOutput(
+    const base::DictionaryValue& dict) const {
+  std::string line;
+  if (dict.GetString(kStringKey, &line))
+    return line;
+
+  return std::string();
+}
+
+}  // namespace content
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android_external.h b/content/browser/accessibility/accessibility_tree_formatter_android_external.h
new file mode 100644
index 0000000..671a6f0
--- /dev/null
+++ b/content/browser/accessibility/accessibility_tree_formatter_android_external.h
@@ -0,0 +1,33 @@
+// 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 CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_ANDROID_EXTERNAL_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_ANDROID_EXTERNAL_H_
+
+#include "content/browser/accessibility/accessibility_tree_formatter_android.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class BrowserAccessibility;
+
+class CONTENT_EXPORT AccessibilityTreeFormatterAndroidExternal
+    : public AccessibilityTreeFormatterAndroid {
+ public:
+  AccessibilityTreeFormatterAndroidExternal();
+  ~AccessibilityTreeFormatterAndroidExternal() override;
+
+  base::Value BuildTree(ui::AXPlatformNodeDelegate* root) const override;
+
+ private:
+  void RecursiveBuildTree(const BrowserAccessibility& node,
+                          base::DictionaryValue* dict) const;
+
+  std::string ProcessTreeForOutput(
+      const base::DictionaryValue& node) const override;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_ANDROID_EXTERNAL_H_
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 60ca848..1492a176 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -2564,4 +2564,11 @@
   return std::u16string();
 }
 
+std::u16string
+BrowserAccessibilityAndroid::GenerateAccessibilityNodeInfoString() const {
+  auto* manager =
+      static_cast<BrowserAccessibilityManagerAndroid*>(this->manager());
+  return manager->GenerateAccessibilityNodeInfoString(unique_id());
+}
+
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h
index 6258170..b191d7a 100644
--- a/content/browser/accessibility/browser_accessibility_android.h
+++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -195,6 +195,11 @@
   void GetSuggestions(std::vector<int>* suggestion_starts,
                       std::vector<int>* suggestion_ends) const;
 
+  // Used for tree dumps, generate a string representation of the
+  // AccessibilityNodeInfo object for this node by calling through the
+  // manager to the web_contents_accessibility_android JNI.
+  std::u16string GenerateAccessibilityNodeInfoString() const;
+
  protected:
   BrowserAccessibilityAndroid(BrowserAccessibilityManager* manager,
                               ui::AXNode* node);
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index 30a601a..6dfa04d 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -593,4 +593,14 @@
   return parent_manager->GetWebContentsAXFromRootManager();
 }
 
+std::u16string
+BrowserAccessibilityManagerAndroid::GenerateAccessibilityNodeInfoString(
+    int32_t unique_id) {
+  WebContentsAccessibilityAndroid* wcax = GetWebContentsAXFromRootManager();
+  if (!wcax)
+    return nullptr;
+
+  return wcax->GenerateAccessibilityNodeInfoString(unique_id);
+}
+
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h
index bb13dc8..a3907d5 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -130,6 +130,8 @@
   void EnableTouchPassthrough() { touch_passthrough_enabled_ = true; }
   bool touch_passthrough_enabled() const { return touch_passthrough_enabled_; }
 
+  std::u16string GenerateAccessibilityNodeInfoString(int32_t unique_id);
+
  private:
   // AXTreeObserver overrides.
   void OnAtomicUpdateFinished(
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index c4f225e..0f3f23b9 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -612,6 +612,19 @@
                                                                  unique_id);
 }
 
+std::u16string
+WebContentsAccessibilityAndroid::GenerateAccessibilityNodeInfoString(
+    int32_t unique_id) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return nullptr;
+
+  return base::android::ConvertJavaStringToUTF16(
+      Java_WebContentsAccessibilityImpl_generateAccessibilityNodeInfoString(
+          env, obj, unique_id));
+}
+
 base::android::ScopedJavaLocalRef<jstring>
 WebContentsAccessibilityAndroid::GetSupportedHtmlElementTypes(
     JNIEnv* env,
diff --git a/content/browser/accessibility/web_contents_accessibility_android.h b/content/browser/accessibility/web_contents_accessibility_android.h
index 95a6603..38e206a 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.h
+++ b/content/browser/accessibility/web_contents_accessibility_android.h
@@ -375,6 +375,7 @@
   void HandleNavigate();
   void ClearNodeInfoCacheForGivenId(int32_t unique_id);
   void HandleEndOfTestSignal();
+  std::u16string GenerateAccessibilityNodeInfoString(int32_t unique_id);
 
   base::WeakPtr<WebContentsAccessibilityAndroid> GetWeakPtr();
 
diff --git a/content/browser/attribution_reporting/attribution_host_unittest.cc b/content/browser/attribution_reporting/attribution_host_unittest.cc
index eb0859e..37f6ff1f 100644
--- a/content/browser/attribution_reporting/attribution_host_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_host_unittest.cc
@@ -49,6 +49,12 @@
 
 namespace {
 
+using testing::AllOf;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::Property;
+using testing::SizeIs;
+
 const char kConversionUrl[] = "https://b.com";
 const char kConversionUrlWithFragment[] = "https://b.com/#fragment";
 const char kConversionUrlWithSubDomain[] = "https://sub.b.com";
@@ -124,10 +130,11 @@
   // triggered.
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(bad_message_observer.got_bad_message());
-  EXPECT_EQ(1u, test_manager_.num_triggers());
 
-  EXPECT_EQ(net::SchemefulSite(GURL("https://www.example.com")),
-            test_manager_.last_conversion_destination());
+  EXPECT_THAT(test_manager_.handled_triggers(),
+              ElementsAre(Property(
+                  &StorableTrigger::conversion_destination,
+                  net::SchemefulSite(GURL("https://www.example.com")))));
 }
 
 TEST_F(AttributionHostTest,
@@ -156,10 +163,11 @@
   // triggered.
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(bad_message_observer.got_bad_message());
-  EXPECT_EQ(1u, test_manager_.num_triggers());
 
-  EXPECT_EQ(net::SchemefulSite(GURL("https://www.example.com")),
-            test_manager_.last_conversion_destination());
+  EXPECT_THAT(test_manager_.handled_triggers(),
+              ElementsAre(Property(
+                  &StorableTrigger::conversion_destination,
+                  net::SchemefulSite(GURL("https://www.example.com")))));
 }
 
 TEST_F(AttributionHostTest, ConversionInSubframeOnInsecurePage_BadMessage) {
@@ -186,7 +194,7 @@
       "blink.mojom.ConversionHost can only be used in secure contexts with a "
       "secure conversion registration origin.",
       bad_message_observer.WaitForBadMessage());
-  EXPECT_EQ(0u, test_manager_.num_triggers());
+  EXPECT_THAT(test_manager_.handled_triggers(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest,
@@ -233,8 +241,8 @@
         url::Origin::Create(test_case.reporting_origin);
     conversion_host_mojom()->RegisterConversion(std::move(conversion));
 
-    EXPECT_EQ(static_cast<size_t>(test_case.conversion_allowed),
-              test_manager_.num_triggers())
+    EXPECT_THAT(test_manager_.handled_triggers(),
+                SizeIs(test_case.conversion_allowed))
         << "Top frame url: " << test_case.top_frame_url
         << ", reporting origin: " << test_case.reporting_origin;
 
@@ -261,7 +269,7 @@
       "blink.mojom.ConversionHost can only be used in secure contexts with a "
       "secure conversion registration origin.",
       bad_message_observer.WaitForBadMessage());
-  EXPECT_EQ(0u, test_manager_.num_triggers());
+  EXPECT_THAT(test_manager_.handled_triggers(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest, ConversionWithInsecureReportingOrigin_BadMessage) {
@@ -280,7 +288,7 @@
       "blink.mojom.ConversionHost can only be used in secure contexts with a "
       "secure conversion registration origin.",
       bad_message_observer.WaitForBadMessage());
-  EXPECT_EQ(0u, test_manager_.num_triggers());
+  EXPECT_THAT(test_manager_.handled_triggers(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest, ValidConversion_NoBadMessage) {
@@ -301,7 +309,7 @@
   // triggered.
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(bad_message_observer.got_bad_message());
-  EXPECT_EQ(1u, test_manager_.num_triggers());
+  EXPECT_THAT(test_manager_.handled_triggers(), SizeIs(1));
 }
 
 TEST_F(AttributionHostTest, ValidConversionWithEmbedderDisable_NoConversion) {
@@ -318,7 +326,7 @@
       url::Origin::Create(GURL("https://secure.com"));
   conversion_host_mojom()->RegisterConversion(std::move(conversion));
 
-  EXPECT_EQ(0u, test_manager_.num_triggers());
+  EXPECT_THAT(test_manager_.handled_triggers(), IsEmpty());
   SetBrowserClientForTesting(old_browser_client);
 }
 
@@ -351,8 +359,8 @@
         url::Origin::Create(test_case.reporting_origin);
     conversion_host_mojom()->RegisterConversion(std::move(conversion));
 
-    EXPECT_EQ(static_cast<size_t>(test_case.conversion_allowed),
-              test_manager_.num_triggers())
+    EXPECT_THAT(test_manager_.handled_triggers(),
+                SizeIs(test_case.conversion_allowed))
         << "Top frame url: " << test_case.top_frame_url
         << ", reporting origin: " << test_case.reporting_origin;
 
@@ -396,8 +404,8 @@
     navigation->set_impression(std::move(impression));
     navigation->Commit();
 
-    EXPECT_EQ(static_cast<size_t>(test_case.impression_allowed),
-              test_manager_.num_sources())
+    EXPECT_THAT(test_manager_.handled_sources(),
+                SizeIs(test_case.impression_allowed))
         << "Top frame url: " << test_case.top_frame_url
         << ", reporting origin: " << test_case.reporting_origin;
 
@@ -419,7 +427,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
   SetBrowserClientForTesting(old_browser_client);
 }
 
@@ -432,12 +440,13 @@
   conversion->reporting_origin =
       url::Origin::Create(GURL("https://secure.com"));
   conversion_host_mojom()->RegisterConversion(std::move(conversion));
-  EXPECT_EQ(1u, test_manager_.num_triggers());
 
   // Verify that we use the domain of the page where the conversion occurred
   // instead of the origin.
-  EXPECT_EQ(net::SchemefulSite(GURL("https://conversion.com")),
-            test_manager_.last_conversion_destination());
+  EXPECT_THAT(test_manager_.handled_triggers(),
+              ElementsAre(Property(
+                  &StorableTrigger::conversion_destination,
+                  net::SchemefulSite(GURL("https://conversion.com")))));
 }
 
 TEST_F(AttributionHostTest, PerPageConversionMetrics) {
@@ -457,14 +466,14 @@
 
   for (size_t i = 0u; i < 8u; i++) {
     conversion_host_mojom()->RegisterConversion(conversion->Clone());
-    EXPECT_EQ(1u, test_manager_.num_triggers());
+    EXPECT_THAT(test_manager_.handled_triggers(), SizeIs(1));
     test_manager_.Reset();
   }
 
   conversion->reporting_origin =
       url::Origin::Create(GURL("https://anothersecure.com"));
   conversion_host_mojom()->RegisterConversion(conversion->Clone());
-  EXPECT_EQ(1u, test_manager_.num_triggers());
+  EXPECT_THAT(test_manager_.handled_triggers(), SizeIs(1));
   test_manager_.Reset();
 
   // Same document navs should not reset the counter.
@@ -530,7 +539,7 @@
     // Run loop to allow the bad message code to run if a bad message was
     // triggered.
     base::RunLoop().RunUntilIdle();
-    EXPECT_EQ(1u, test_manager_.num_sources());
+    EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
     test_manager_.Reset();
   }
 
@@ -540,7 +549,7 @@
   // Run loop to allow the bad message code to run if a bad message was
   // triggered.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
   test_manager_.Reset();
 
   // Same document navs should not reset the counter.
@@ -605,7 +614,7 @@
   NavigationSimulatorImpl::NavigateAndCommitFromDocument(GURL(kConversionUrl),
                                                          main_rfh());
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest, ValidImpression_ForwardedToManager) {
@@ -616,7 +625,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 }
 
 TEST_F(AttributionHostTest, ImpressionWithNoManagerAvilable_NoCrash) {
@@ -648,7 +657,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 // Test that if we cannot access the initiator frame of the navigation, we
@@ -665,7 +674,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   histograms.ExpectUniqueSample(
       "Conversions.ImpressionNavigationHasDeadInitiator", true, 2);
@@ -681,7 +690,7 @@
   navigation->Fail(net::ERR_FAILED);
   navigation->CommitErrorPage();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest, ImpressionNavigationAborts_Ignored) {
@@ -693,7 +702,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->AbortCommit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest,
@@ -706,7 +715,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 TEST_F(AttributionHostTest,
@@ -759,7 +768,8 @@
     navigation->SetInitiatorFrame(main_rfh());
     navigation->Commit();
 
-    EXPECT_EQ(test_case.impression_expected, test_manager_.num_sources())
+    EXPECT_THAT(test_manager_.handled_sources(),
+                SizeIs(test_case.impression_expected))
         << "For test case: " << test_case.impression_origin << " | "
         << test_case.conversion_origin << " | " << test_case.reporting_origin;
     test_manager_.Reset();
@@ -790,10 +800,11 @@
   // triggered.
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(bad_message_observer.got_bad_message());
-  EXPECT_EQ(1u, test_manager_.num_sources());
 
-  EXPECT_EQ(url::Origin::Create(GURL("https://www.example.com")),
-            test_manager_.last_impression_origin());
+  EXPECT_THAT(test_manager_.handled_sources(),
+              ElementsAre(Property(
+                  &StorableSource::impression_origin,
+                  url::Origin::Create(GURL("https://www.example.com")))));
 }
 
 TEST_F(AttributionHostTest, ValidImpression_NoBadMessage) {
@@ -812,10 +823,10 @@
   // triggered.
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(bad_message_observer.got_bad_message());
-  EXPECT_EQ(1u, test_manager_.num_sources());
-  EXPECT_EQ(StorableSource::SourceType::kEvent,
-            test_manager_.last_impression_source_type());
-  EXPECT_EQ(10, test_manager_.last_attribution_source_priority());
+  EXPECT_THAT(test_manager_.handled_sources(),
+              ElementsAre(AllOf(Property(&StorableSource::source_type,
+                                         StorableSource::SourceType::kEvent),
+                                Property(&StorableSource::priority, 10))));
 }
 
 TEST_F(AttributionHostTest, RegisterImpression_RecordsAllowedMetric) {
@@ -896,16 +907,16 @@
       GURL(kConversionUrl), contents());
   navigation->Start();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   conversion_host()->ReportAttributionForCurrentNavigation(
       url::Origin::Create(GURL(origin)), CreateValidImpression());
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   navigation->Commit();
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 }
 
 // In pre-loaded CCT navigations, the attribution can arrive after the
@@ -925,18 +936,18 @@
       GURL(kConversionUrl), contents());
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   conversion_host()->ReportAttributionForCurrentNavigation(
       url::Origin::Create(GURL(origin)), CreateValidImpression());
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 
   // Make sure we don't allow repeated attributions for the same navigation.
   conversion_host()->ReportAttributionForCurrentNavigation(
       url::Origin::Create(GURL(origin)), CreateValidImpression());
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 }
 
 TEST_F(AttributionHostTest, AndroidConversion_AfterNavigation_SubDomain) {
@@ -956,7 +967,7 @@
   conversion_host()->ReportAttributionForCurrentNavigation(
       url::Origin::Create(GURL(origin)), CreateValidImpression());
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 }
 
 // In pre-loaded CCT navigations, the attribution can arrive after the
@@ -979,7 +990,7 @@
   conversion_host()->ReportAttributionForCurrentNavigation(
       url::Origin::Create(GURL(origin)), CreateValidImpression());
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   // Navigating to the correct URL after navigation to the wrong one still
   // shouldn't allow the attribution.
@@ -987,7 +998,7 @@
       GURL(kConversionUrl), contents());
   good_navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 // Ensure we don't re-use pending Impressions after an aborted commit. Currently
@@ -1011,14 +1022,14 @@
 
   navigation_abort->AbortCommit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   auto navigation_commit = NavigationSimulatorImpl::CreateBrowserInitiated(
       GURL(kConversionUrl), contents());
 
   navigation_commit->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 // Ensure we don't re-use pending Impressions after an Error page commit.
@@ -1043,14 +1054,14 @@
   navigation_error->Fail(net::ERR_UNEXPECTED);
   navigation_error->CommitErrorPage();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   auto navigation_commit = NavigationSimulatorImpl::CreateBrowserInitiated(
       GURL(kConversionUrl), contents());
 
   navigation_commit->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 // We don't allow attributions before a navigation begins. Currently only used
@@ -1073,7 +1084,7 @@
 
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
 // We ignore same-document navigations.
@@ -1096,7 +1107,7 @@
   conversion_host()->ReportAttributionForCurrentNavigation(
       url::Origin::Create(GURL(origin)), CreateValidImpression());
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 }
 
 #if defined(OS_ANDROID)
@@ -1110,7 +1121,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), SizeIs(1));
 }
 
 TEST_F(AttributionHostTest, AndroidConversion_BadScheme) {
@@ -1121,7 +1132,7 @@
   navigation->set_impression(CreateValidImpression());
   navigation->Commit();
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 #endif
 
diff --git a/content/browser/attribution_reporting/attribution_host_utils_unittest.cc b/content/browser/attribution_reporting/attribution_host_utils_unittest.cc
index f50f696..899bb0c 100644
--- a/content/browser/attribution_reporting/attribution_host_utils_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_host_utils_unittest.cc
@@ -4,19 +4,20 @@
 
 #include "content/browser/attribution_reporting/attribution_host_utils.h"
 
-#include <memory>
-
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/origin.h"
 
 namespace content {
 
 namespace attribution_host_utils {
 
-class ConversionHostUtilsTest : public ::testing::Test {};
+namespace {
 
-TEST(ConversionHostUtilsTest, AppImpression_Valid) {
+class AttributionHostUtilsTest : public ::testing::Test {};
+
+TEST(AttributionHostUtilsTest, AppImpression_Valid) {
   absl::optional<blink::Impression> impression =
       ParseImpressionFromApp("9223372036854775807", "https://example.com",
                              "https://example2.com", 1234);
@@ -26,7 +27,7 @@
   EXPECT_EQ(base::Milliseconds(1234), impression->expiry);
 }
 
-TEST(ConversionHostUtilsTest, AppImpression_Valid_NoOptionals) {
+TEST(AttributionHostUtilsTest, AppImpression_Valid_NoOptionals) {
   absl::optional<blink::Impression> impression = ParseImpressionFromApp(
       "9223372036854775807", "https://example.com", "", 0);
   EXPECT_EQ(9223372036854775807ull, impression->impression_data);
@@ -35,21 +36,22 @@
   EXPECT_EQ(absl::nullopt, impression->expiry);
 }
 
-TEST(ConversionHostUtilsTest, AppImpression_Invalid_Destination) {
+TEST(AttributionHostUtilsTest, AppImpression_Invalid_Destination) {
   EXPECT_EQ(absl::nullopt,
             ParseImpressionFromApp("12345", "http://bad.com", "", 0));
 }
 
-TEST(ConversionHostUtilsTest, AppImpression_Invalid_ReportTo) {
+TEST(AttributionHostUtilsTest, AppImpression_Invalid_ReportTo) {
   EXPECT_EQ(absl::nullopt,
             ParseImpressionFromApp("12345", "https://example.com",
                                    "http://bad.com", 0));
 }
 
-TEST(ConversionHostUtilsTest, AppImpression_Invalid_EventId) {
+TEST(AttributionHostUtilsTest, AppImpression_Invalid_EventId) {
   EXPECT_EQ(absl::nullopt,
             ParseImpressionFromApp("-12345", "https://example.com", "", 0));
 }
 
+}  // namespace
 }  // namespace attribution_host_utils
 }  // namespace content
diff --git a/content/browser/attribution_reporting/attribution_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom
index e710968..379f74e 100644
--- a/content/browser/attribution_reporting/attribution_internals.mojom
+++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -28,6 +28,7 @@
     kPending,
     kDroppedDueToLowPriority,
     kDroppedForNoise,
+    kProhibitedByBrowserPolicy,
     kSent,
   };
 
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
index 09449726..b42e19d1 100644
--- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc
+++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -315,6 +315,13 @@
                          .Build(),
                      SentReportInfo::Status::kSent,
                      /*http_response_code=*/200));
+  manager_.NotifyReportSent(
+      SentReportInfo(ReportBuilder(SourceBuilder(now).Build())
+                         .SetReportTime(now + base::Hours(4))
+                         .SetPriority(-1)
+                         .Build(),
+                     SentReportInfo::Status::kDropped,
+                     /*http_response_code=*/0));
   manager_.SetReportsForWebUI(
       {ReportBuilder(
            SourceBuilder(now)
@@ -341,7 +348,7 @@
     static constexpr char wait_script[] = R"(
       let table = document.querySelector("#report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
-        if (table.children.length === 4 &&
+        if (table.children.length === 5 &&
             table.children[0].children[1].innerText === "https://conversion.test" &&
             table.children[0].children[2].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-attribution" &&
@@ -354,7 +361,8 @@
             table.children[2].children[7].innerText === "Dropped for noise" &&
             table.children[3].children[5].innerText === "0" &&
             table.children[3].children[6].innerText === "no" &&
-            table.children[3].children[7].innerText === "Sent: HTTP 200") {
+            table.children[3].children[7].innerText === "Sent: HTTP 200" &&
+            table.children[4].children[7].innerText === "Prohibited by browser policy") {
           document.title = $1;
         }
       });
@@ -370,20 +378,21 @@
     static constexpr char wait_script[] = R"(
       let table = document.querySelector("#report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
-        if (table.children.length === 4 &&
-            table.children[3].children[1].innerText === "https://conversion.test" &&
-            table.children[3].children[2].innerText ===
+        if (table.children.length === 5 &&
+            table.children[4].children[1].innerText === "https://conversion.test" &&
+            table.children[4].children[2].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-attribution" &&
-            table.children[3].children[5].innerText === "13" &&
-            table.children[3].children[6].innerText === "yes" &&
-            table.children[3].children[7].innerText === "Pending" &&
-            table.children[2].children[5].innerText === "12" &&
-            table.children[2].children[7].innerText === "Dropped for noise" &&
-            table.children[1].children[5].innerText === "11" &&
-            table.children[1].children[7].innerText === "Dropped due to low priority" &&
-            table.children[0].children[5].innerText === "0" &&
-            table.children[0].children[6].innerText === "no" &&
-            table.children[0].children[7].innerText === "Sent: HTTP 200") {
+            table.children[4].children[5].innerText === "13" &&
+            table.children[4].children[6].innerText === "yes" &&
+            table.children[4].children[7].innerText === "Pending" &&
+            table.children[3].children[5].innerText === "12" &&
+            table.children[3].children[7].innerText === "Dropped for noise" &&
+            table.children[2].children[5].innerText === "11" &&
+            table.children[2].children[7].innerText === "Dropped due to low priority" &&
+            table.children[1].children[5].innerText === "0" &&
+            table.children[1].children[6].innerText === "no" &&
+            table.children[1].children[7].innerText === "Sent: HTTP 200" &&
+            table.children[0].children[7].innerText === "Prohibited by browser policy") {
           document.title = $1;
         }
       });
@@ -401,7 +410,7 @@
     static constexpr char wait_script[] = R"(
       let table = document.querySelector("#report-table-wrapper tbody");
       let obs = new MutationObserver(() => {
-        if (table.children.length === 4 &&
+        if (table.children.length === 5 &&
             table.children[0].children[1].innerText === "https://conversion.test" &&
             table.children[0].children[2].innerText ===
               "https://report.test/.well-known/attribution-reporting/report-attribution" &&
@@ -414,7 +423,8 @@
             table.children[2].children[7].innerText === "Dropped due to low priority" &&
             table.children[3].children[5].innerText === "0" &&
             table.children[3].children[6].innerText === "no" &&
-            table.children[3].children[7].innerText === "Sent: HTTP 200") {
+            table.children[3].children[7].innerText === "Sent: HTTP 200" &&
+            table.children[4].children[7].innerText === "Prohibited by browser policy") {
           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 135de31..8de9afb 100644
--- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
+++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -211,9 +211,25 @@
 }
 
 void AttributionInternalsHandlerImpl::OnReportSent(const SentReportInfo& info) {
+  mojom::WebUIAttributionReport::Status status;
+  switch (info.status) {
+    case SentReportInfo::Status::kSent:
+    case SentReportInfo::Status::kFailure:
+      status = mojom::WebUIAttributionReport::Status::kSent;
+      break;
+    case SentReportInfo::Status::kDropped:
+      status =
+          mojom::WebUIAttributionReport::Status::kProhibitedByBrowserPolicy;
+      break;
+    case SentReportInfo::Status::kTransientFailure:
+    case SentReportInfo::Status::kOffline:
+    case SentReportInfo::Status::kRemovedFromQueue:
+      NOTREACHED();
+      return;
+  }
+
   auto report =
-      WebUIAttributionReport(info.report, info.http_response_code,
-                             mojom::WebUIAttributionReport::Status::kSent);
+      WebUIAttributionReport(info.report, info.http_response_code, status);
 
   for (auto& observer : observers_) {
     observer->OnReportSent(report.Clone());
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc
index 955dee6..b59d7a3 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -480,8 +480,10 @@
 
   // TODO(apaseltiner): Consider surfacing retry attempts in internals UI.
   if (info.status != SentReportInfo::Status::kSent &&
-      info.status != SentReportInfo::Status::kFailure)
+      info.status != SentReportInfo::Status::kFailure &&
+      info.status != SentReportInfo::Status::kDropped) {
     return;
+  }
 
   for (Observer& observer : observers_)
     observer.OnReportSent(info);
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
index 93f3c5d8..ae4202d6 100644
--- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -505,7 +505,7 @@
   task_environment_.FastForwardBy(kFirstReportingWindow -
                                   kAttributionManagerQueueReportsInterval);
 
-  // This one shouldn't be stored, as its status is `kDropped`.
+  // This one should be stored, as its status is `kDropped`.
   test_reporter_->SetSentReportInfoStatus(SentReportInfo::Status::kDropped);
   attribution_manager_->HandleSource(SourceBuilder(clock().Now())
                                          .SetSourceEventId(2)
@@ -543,6 +543,9 @@
                       Property(&StorableSource::source_event_id, 1u))),
           Field(&SentReportInfo::report,
                 Field(&AttributionReport::impression,
+                      Property(&StorableSource::source_event_id, 2u))),
+          Field(&SentReportInfo::report,
+                Field(&AttributionReport::impression,
                       Property(&StorableSource::source_event_id, 3u)))));
 
   // kSent = 0.
diff --git a/content/browser/attribution_reporting/attribution_reporter_android_unittest.cc b/content/browser/attribution_reporting/attribution_reporter_android_unittest.cc
index a9f86181..806650e 100644
--- a/content/browser/attribution_reporting/attribution_reporter_android_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_reporter_android_unittest.cc
@@ -18,6 +18,12 @@
 
 namespace content {
 
+namespace {
+using testing::AllOf;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::Property;
+
 const char kPackageName[] = "org.chromium.chrome.test";
 const char kConversionUrl[] = "https://b.com";
 const char kInvalidUrl[] = "http://insecure.com";
@@ -32,8 +38,6 @@
     url::AddStandardScheme(kAndroidAppScheme, url::SCHEME_WITH_HOST);
   }
 
-  void TearDown() override {}
-
  protected:
   TestAttributionManager test_manager_;
 
@@ -47,13 +51,13 @@
       test_manager_, nullptr, kPackageName, kEventId, kConversionUrl,
       kReportToUrl, 56789, time);
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
-
-  EXPECT_EQ(OriginFromAndroidPackageName(kPackageName),
-            test_manager_.last_impression_origin());
-  EXPECT_EQ(StorableSource::SourceType::kEvent,
-            test_manager_.last_impression_source_type());
-  EXPECT_EQ(time, test_manager_.last_impression_time());
+  EXPECT_THAT(
+      test_manager_.handled_sources(),
+      ElementsAre(AllOf(Property(&StorableSource::impression_origin,
+                                 OriginFromAndroidPackageName(kPackageName)),
+                        Property(&StorableSource::source_type,
+                                 StorableSource::SourceType::kEvent),
+                        Property(&StorableSource::impression_time, time))));
 }
 
 TEST_F(AttributionReporterTest, ValidImpression_Allowed_NoOptionals) {
@@ -61,12 +65,12 @@
       test_manager_, nullptr, kPackageName, kEventId, kConversionUrl, "", 0,
       base::Time::Now());
 
-  EXPECT_EQ(1u, test_manager_.num_sources());
-
-  EXPECT_EQ(OriginFromAndroidPackageName(kPackageName),
-            test_manager_.last_impression_origin());
-  EXPECT_EQ(StorableSource::SourceType::kEvent,
-            test_manager_.last_impression_source_type());
+  EXPECT_THAT(
+      test_manager_.handled_sources(),
+      ElementsAre(AllOf(Property(&StorableSource::impression_origin,
+                                 OriginFromAndroidPackageName(kPackageName)),
+                        Property(&StorableSource::source_type,
+                                 StorableSource::SourceType::kEvent))));
 }
 
 TEST_F(AttributionReporterTest, ValidImpression_Disallowed) {
@@ -79,7 +83,7 @@
       test_manager_, nullptr, kPackageName, kEventId, kConversionUrl,
       kReportToUrl, 56789, base::Time::Now());
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 
   SetBrowserClientForTesting(old_browser_client);
 }
@@ -89,7 +93,8 @@
       test_manager_, nullptr, kPackageName, kEventId, kInvalidUrl, kReportToUrl,
       56789, base::Time::Now());
 
-  EXPECT_EQ(0u, test_manager_.num_sources());
+  EXPECT_THAT(test_manager_.handled_sources(), IsEmpty());
 }
 
+}  // namespace
 }  // namespace content
diff --git a/content/browser/attribution_reporting/attribution_test_utils.cc b/content/browser/attribution_reporting/attribution_test_utils.cc
index 9bb6a8b..5a9defc 100644
--- a/content/browser/attribution_reporting/attribution_test_utils.cc
+++ b/content/browser/attribution_reporting/attribution_test_utils.cc
@@ -16,7 +16,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/task/task_runner_util.h"
 #include "base/test/bind.h"
-#include "content/browser/attribution_reporting/storable_trigger.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -162,17 +161,11 @@
 }
 
 void TestAttributionManager::HandleSource(StorableSource source) {
-  num_sources_++;
-  last_impression_source_type_ = source.source_type();
-  last_impression_origin_ = source.impression_origin();
-  last_attribution_source_priority_ = source.priority();
-  last_impression_time_ = source.impression_time();
+  handled_sources_.push_back(std::move(source));
 }
 
 void TestAttributionManager::HandleTrigger(StorableTrigger trigger) {
-  num_triggers_++;
-
-  last_conversion_destination_ = trigger.conversion_destination();
+  handled_triggers_.push_back(std::move(trigger));
 }
 
 void TestAttributionManager::GetActiveSourcesForWebUI(
@@ -232,8 +225,8 @@
 }
 
 void TestAttributionManager::Reset() {
-  num_sources_ = 0u;
-  num_triggers_ = 0u;
+  handled_sources_.clear();
+  handled_triggers_.clear();
 }
 
 // Builds an impression with default values. This is done as a builder because
diff --git a/content/browser/attribution_reporting/attribution_test_utils.h b/content/browser/attribution_reporting/attribution_test_utils.h
index 9640cba..184df39 100644
--- a/content/browser/attribution_reporting/attribution_test_utils.h
+++ b/content/browser/attribution_reporting/attribution_test_utils.h
@@ -24,6 +24,7 @@
 #include "content/browser/attribution_reporting/rate_limit_table.h"
 #include "content/browser/attribution_reporting/sent_report_info.h"
 #include "content/browser/attribution_reporting/storable_source.h"
+#include "content/browser/attribution_reporting/storable_trigger.h"
 #include "content/test/test_content_browser_client.h"
 #include "net/base/schemeful_site.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -201,37 +202,21 @@
   // Resets all counters on this.
   void Reset();
 
-  size_t num_sources() const { return num_sources_; }
-  size_t num_triggers() const { return num_triggers_; }
-
-  const net::SchemefulSite& last_conversion_destination() {
-    return last_conversion_destination_;
+  const std::vector<StorableSource>& handled_sources() const
+      WARN_UNUSED_RESULT {
+    return handled_sources_;
   }
 
-  const absl::optional<StorableSource::SourceType>&
-  last_impression_source_type() {
-    return last_impression_source_type_;
-  }
-
-  const absl::optional<url::Origin>& last_impression_origin() {
-    return last_impression_origin_;
-  }
-
-  const base::Time last_impression_time() { return last_impression_time_; }
-
-  const absl::optional<int64_t>& last_attribution_source_priority() {
-    return last_attribution_source_priority_;
+  const std::vector<StorableTrigger>& handled_triggers() const
+      WARN_UNUSED_RESULT {
+    return handled_triggers_;
   }
 
  private:
   AttributionPolicy policy_;
-  net::SchemefulSite last_conversion_destination_;
-  absl::optional<StorableSource::SourceType> last_impression_source_type_;
-  absl::optional<url::Origin> last_impression_origin_;
-  absl::optional<int64_t> last_attribution_source_priority_;
-  base::Time last_impression_time_;
-  size_t num_sources_ = 0;
-  size_t num_triggers_ = 0;
+
+  std::vector<StorableSource> handled_sources_;
+  std::vector<StorableTrigger> handled_triggers_;
 
   std::vector<StorableSource> sources_;
   std::vector<AttributionReport> reports_;
diff --git a/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc b/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
index 2a89211..d011ae1 100644
--- a/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
+++ b/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
@@ -108,12 +108,14 @@
   }
 
   void ResetService0() {
-    service0_->ClearState();
+    delete service0_;
+    service0_ = nullptr;
     map0_ = nullptr;
   }
 
   void ResetService1() {
-    service1_->ClearState();
+    delete service1_;
+    service1_ = nullptr;
     map1_ = nullptr;
   }
 
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 0595191..bd3bbbc 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -261,7 +261,7 @@
           blink::mojom::WebBluetoothAdvertisementClient> client_info)
       : client_(std::move(client_info)),
         web_contents_(static_cast<WebContentsImpl*>(
-            WebContents::FromRenderFrameHost(service->render_frame_host_))),
+            WebContents::FromRenderFrameHost(service->render_frame_host()))),
         service_(service) {
     // Using base::Unretained() is safe here because all instances of this class
     // will be owned by |service|.
@@ -516,16 +516,26 @@
       characteristic_client;
 };
 
+// static
+WebBluetoothServiceImpl* WebBluetoothServiceImpl::Create(
+    RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(render_frame_host);
+  return new WebBluetoothServiceImpl(render_frame_host, std::move(receiver));
+}
+
 WebBluetoothServiceImpl::WebBluetoothServiceImpl(
     RenderFrameHost* render_frame_host,
     mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver)
-    : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
-      connected_devices_(new FrameConnectedBluetoothDevices(render_frame_host)),
-      render_frame_host_(render_frame_host),
+    : DocumentService(render_frame_host, std::move(receiver)),
+      WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
+      connected_devices_(new FrameConnectedBluetoothDevices(render_frame_host))
 #if PAIR_BLUETOOTH_ON_DEMAND()
-      pairing_manager_(std::make_unique<WebBluetoothPairingManagerImpl>(this)),
+      ,
+      pairing_manager_(std::make_unique<WebBluetoothPairingManagerImpl>(this))
 #endif
-      receiver_(this, std::move(receiver)) {
+{
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   CHECK(web_contents());
 
@@ -541,18 +551,16 @@
 
 WebBluetoothServiceImpl::~WebBluetoothServiceImpl() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  ClearState();
-}
+  // Releasing the adapter will drop references to callbacks that have not yet
+  // been executed. The receiver must be closed first so that this is allowed.
+  receiver()->reset();
 
-void WebBluetoothServiceImpl::SetClientConnectionErrorHandler(
-    base::OnceClosure closure) {
-  receiver_.set_disconnect_handler(std::move(closure));
+  BluetoothAdapterFactoryWrapper::Get().ReleaseAdapter(this);
 }
 
 blink::mojom::WebBluetoothResult
 WebBluetoothServiceImpl::GetBluetoothAllowed() {
-  const url::Origin& requesting_origin =
-      render_frame_host_->GetLastCommittedOrigin();
+  const url::Origin& requesting_origin = origin();
   const url::Origin& embedding_origin =
       web_contents()->GetMainFrame()->GetLastCommittedOrigin();
 
@@ -608,8 +616,7 @@
     StoreAllowedScanOptions(client->scan_options());
   } else if (event == BluetoothScanningPrompt::Event::kBlock) {
     result = blink::mojom::WebBluetoothResult::SCANNING_BLOCKED;
-    const url::Origin requesting_origin =
-        render_frame_host_->GetLastCommittedOrigin();
+    const url::Origin requesting_origin = origin();
     const url::Origin embedding_origin =
         web_contents()->GetMainFrame()->GetLastCommittedOrigin();
     GetContentClient()->browser()->BlockBluetoothScanning(
@@ -641,7 +648,7 @@
 }
 
 void WebBluetoothServiceImpl::OnPermissionRevoked(const url::Origin& origin) {
-  if (render_frame_host_->GetMainFrame()->GetLastCommittedOrigin() != origin) {
+  if (render_frame_host()->GetMainFrame()->GetLastCommittedOrigin() != origin) {
     return;
   }
 
@@ -651,7 +658,7 @@
     return;
 
   std::set<blink::WebBluetoothDeviceId> permitted_ids;
-  for (const auto& device : delegate->GetPermittedDevices(render_frame_host_))
+  for (const auto& device : delegate->GetPermittedDevices(render_frame_host()))
     permitted_ids.insert(device->id);
 
   connected_devices_->CloseConnectionsToDevicesNotInList(permitted_ids);
@@ -665,16 +672,7 @@
 }
 
 content::RenderFrameHost* WebBluetoothServiceImpl::GetRenderFrameHost() {
-  return render_frame_host_;
-}
-
-void WebBluetoothServiceImpl::DidFinishNavigation(
-    NavigationHandle* navigation_handle) {
-  if (navigation_handle->HasCommitted() &&
-      navigation_handle->GetRenderFrameHost() == render_frame_host_ &&
-      !navigation_handle->IsSameDocument()) {
-    ClearState();
-  }
+  return render_frame_host();
 }
 
 void WebBluetoothServiceImpl::OnVisibilityChanged(Visibility visibility) {
@@ -748,7 +746,8 @@
         GetContentClient()->browser()->GetBluetoothDelegate();
     if (!delegate)
       return;
-    device->id = delegate->AddScannedDevice(render_frame_host_, device_address);
+    device->id =
+        delegate->AddScannedDevice(render_frame_host(), device_address);
   } else {
     device->id = allowed_devices().AddDevice(device_address);
   }
@@ -926,7 +925,7 @@
         GetContentClient()->browser()->GetBluetoothDelegate();
     if (delegate) {
       is_connect_allowed =
-          delegate->HasDevicePermission(render_frame_host_, device_id);
+          delegate->HasDevicePermission(render_frame_host(), device_id);
     }
   } else {
     is_connect_allowed = allowed_devices().IsAllowedToGATTConnect(device_id);
@@ -1479,8 +1478,7 @@
     RequestScanningStartCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  const url::Origin requesting_origin =
-      render_frame_host_->GetLastCommittedOrigin();
+  const url::Origin requesting_origin = origin();
   const url::Origin embedding_origin =
       web_contents()->GetMainFrame()->GetLastCommittedOrigin();
 
@@ -1612,7 +1610,7 @@
     // there are duplicate calls to RequestScanningStart().
     device_scanning_prompt_controller_ =
         std::make_unique<BluetoothDeviceScanningPromptController>(
-            this, render_frame_host_);
+            this, render_frame_host());
     scanning_client->SetPromptController(
         device_scanning_prompt_controller_.get());
     scanning_clients_.push_back(std::move(scanning_client));
@@ -1660,7 +1658,7 @@
 
   device_scanning_prompt_controller_ =
       std::make_unique<BluetoothDeviceScanningPromptController>(
-          this, render_frame_host_);
+          this, render_frame_host());
   scanning_client->SetPromptController(
       device_scanning_prompt_controller_.get());
   scanning_clients_.push_back(std::move(scanning_client));
@@ -1697,7 +1695,7 @@
 
   device_chooser_controller_ =
       std::make_unique<BluetoothDeviceChooserController>(
-          this, render_frame_host_, std::move(adapter));
+          this, render_frame_host(), std::move(adapter));
   device_chooser_controller_->GetDevice(
       std::move(options),
       base::BindOnce(&WebBluetoothServiceImpl::OnGetDevice,
@@ -1716,7 +1714,7 @@
       return;
     }
 
-    std::move(callback).Run(delegate->GetPermittedDevices(render_frame_host_));
+    std::move(callback).Run(delegate->GetPermittedDevices(render_frame_host()));
     return;
   }
 
@@ -1806,7 +1804,7 @@
             features::kWebBluetoothNewPermissionsBackend) &&
         (!delegate ||
          !delegate->HasDevicePermission(
-             render_frame_host_, callback_and_client.second->device_id()))) {
+             render_frame_host(), callback_and_client.second->device_id()))) {
       std::move(callback_and_client.first)
           .Run(blink::mojom::WebBluetoothResult::
                    NOT_ALLOWED_TO_ACCESS_ANY_SERVICE);
@@ -1953,7 +1951,7 @@
       return;
     }
     web_bluetooth_device->id = delegate->GrantServiceAccessPermission(
-        render_frame_host_, device, options.get());
+        render_frame_host(), device, options.get());
   } else {
     web_bluetooth_device->id =
         allowed_devices().AddDevice(device_address, options);
@@ -2212,7 +2210,7 @@
         GetContentClient()->browser()->GetBluetoothDelegate();
     if (delegate) {
       device_address =
-          delegate->GetDeviceAddress(render_frame_host_, device_id);
+          delegate->GetDeviceAddress(render_frame_host(), device_id);
     }
   } else {
     device_address = allowed_devices().GetDeviceAddress(device_id);
@@ -2347,7 +2345,7 @@
 }
 
 RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() {
-  return render_frame_host_->GetProcess();
+  return render_frame_host()->GetProcess();
 }
 
 BluetoothAdapter* WebBluetoothServiceImpl::GetAdapter() {
@@ -2357,18 +2355,14 @@
 void WebBluetoothServiceImpl::CrashRendererAndClosePipe(
     bad_message::BadMessageReason reason) {
   bad_message::ReceivedBadMessage(GetRenderProcessHost(), reason);
-  receiver_.reset();
-}
-
-url::Origin WebBluetoothServiceImpl::GetOrigin() {
-  return render_frame_host_->GetLastCommittedOrigin();
+  receiver()->reset();
 }
 
 BluetoothAllowedDevices& WebBluetoothServiceImpl::allowed_devices() {
   StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
       web_contents()->GetBrowserContext()->GetDefaultStoragePartition());
   return partition->GetBluetoothAllowedDevicesMap()->GetOrCreateAllowedDevices(
-      GetOrigin());
+      origin());
 }
 
 void WebBluetoothServiceImpl::StoreAllowedScanOptions(
@@ -2415,25 +2409,6 @@
   return true;
 }
 
-void WebBluetoothServiceImpl::ClearState() {
-  // Releasing the adapter will drop references to callbacks that have not yet
-  // been executed. The receiver must be closed first so that this is allowed.
-  receiver_.reset();
-
-  characteristic_id_to_notify_session_.clear();
-  pending_primary_services_requests_.clear();
-  descriptor_id_to_characteristic_id_.clear();
-  characteristic_id_to_service_id_.clear();
-  service_id_to_device_address_.clear();
-  connected_devices_ =
-      std::make_unique<FrameConnectedBluetoothDevices>(render_frame_host_);
-  device_chooser_controller_.reset();
-  device_scanning_prompt_controller_.reset();
-  ClearAdvertisementClients();
-  BluetoothAdapterFactoryWrapper::Get().ReleaseAdapter(this);
-  characteristic_id_to_deferred_start_.clear();
-}
-
 void WebBluetoothServiceImpl::ClearAdvertisementClients() {
   scanning_clients_.clear();
   watch_advertisements_clients_.clear();
@@ -2449,7 +2424,7 @@
         GetContentClient()->browser()->GetBluetoothDelegate();
     if (!delegate)
       return false;
-    return delegate->IsAllowedToAccessAtLeastOneService(render_frame_host_,
+    return delegate->IsAllowedToAccessAtLeastOneService(render_frame_host(),
                                                         device_id);
   }
   return allowed_devices().IsAllowedToAccessAtLeastOneService(device_id);
@@ -2464,7 +2439,7 @@
         GetContentClient()->browser()->GetBluetoothDelegate();
     if (!delegate)
       return false;
-    return delegate->IsAllowedToAccessService(render_frame_host_, device_id,
+    return delegate->IsAllowedToAccessService(render_frame_host(), device_id,
                                               service);
   }
   return allowed_devices().IsAllowedToAccessService(device_id, service);
@@ -2480,7 +2455,7 @@
     if (!delegate)
       return false;
     return delegate->IsAllowedToAccessManufacturerData(
-        render_frame_host_, device_id, manufacturer_code);
+        render_frame_host(), device_id, manufacturer_code);
   }
   return allowed_devices().IsAllowedToAccessManufacturerData(device_id,
                                                              manufacturer_code);
@@ -2537,7 +2512,7 @@
         GetContentClient()->browser()->GetBluetoothDelegate();
     if (!delegate)
       return blink::WebBluetoothDeviceId();
-    return delegate->GetWebBluetoothDeviceId(render_frame_host_,
+    return delegate->GetWebBluetoothDeviceId(render_frame_host(),
                                              device_address);
   }
 
@@ -2603,7 +2578,7 @@
     return;
   }
   delegate->ShowDeviceCredentialsPrompt(
-      render_frame_host_, device_identifier,
+      render_frame_host(), device_identifier,
       base::BindOnce(&BluetoothDelegateCredentialsCallback,
                      std::move(callback)));
 }
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h
index 982ef844..b7a1051 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -19,6 +19,7 @@
 #include "content/common/content_export.h"
 #include "content/public/browser/bluetooth_delegate.h"
 #include "content/public/browser/bluetooth_scanning_prompt.h"
+#include "content/public/browser/document_service.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -64,9 +65,9 @@
 // This class is instantiated on-demand via Mojo's ConnectToRemoteService
 // from the renderer when the first Web Bluetooth API request is handled.
 // RenderFrameHostImpl will create an instance of this class and keep
-// ownership of it.
+// ownership of it through content::DocumentService.
 class CONTENT_EXPORT WebBluetoothServiceImpl
-    : public blink::mojom::WebBluetoothService,
+    : public content::DocumentService<blink::mojom::WebBluetoothService>,
       public WebContentsObserver,
       public device::BluetoothAdapter::Observer,
       public BluetoothDelegate::FramePermissionObserver,
@@ -75,22 +76,19 @@
   static blink::mojom::WebBluetoothResult TranslateConnectErrorAndRecord(
       device::BluetoothDevice::ConnectErrorCode error_code);
 
-  // |render_frame_host|: The RFH that owns this instance.
-  // |receiver|: The instance will be bound to this receiver's pipe.
-  WebBluetoothServiceImpl(
+  // Tries to attach |receiver| to an implementation of the
+  // WebBluetoothService for |render_frame_host|. The object returned is
+  // bound to the lifetime of |render_frame_host| and the Mojo connection.
+  // See DocumentService for details.
+  static WebBluetoothServiceImpl* Create(
       RenderFrameHost* render_frame_host,
       mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver);
 
   WebBluetoothServiceImpl(const WebBluetoothServiceImpl&) = delete;
   WebBluetoothServiceImpl& operator=(const WebBluetoothServiceImpl&) = delete;
 
-  ~WebBluetoothServiceImpl() override;
-
   void CrashRendererAndClosePipe(bad_message::BadMessageReason reason);
 
-  // Sets the connection error handler for WebBluetoothServiceImpl's Binding.
-  void SetClientConnectionErrorHandler(base::OnceClosure closure);
-
   // Checks the current requesting and embedding origins as well as the policy
   // or global Web Bluetooth block to determine if Web Bluetooth is allowed.
   // Returns |SUCCESS| if Bluetooth is allowed.
@@ -116,10 +114,18 @@
 #endif  // PAIR_BLUETOOTH_ON_DEMAND()
 
  private:
+  // |render_frame_host|: The RFH that owns this instance.
+  // |receiver|: The instance will be bound to this receiver's pipe.
+  WebBluetoothServiceImpl(
+      RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver);
+
+  ~WebBluetoothServiceImpl() override;
+
   FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
-                           ClearStateDuringRequestDevice);
+                           DestroyedDuringRequestDevice);
   FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
-                           ClearStateDuringRequestScanningStart);
+                           DestroyedDuringRequestScanningStart);
   FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest, PermissionAllowed);
   FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
                            PermissionPromptCanceled);
@@ -155,8 +161,7 @@
 
   // WebContentsObserver:
   // These functions should always check that the affected RenderFrameHost
-  // is this->render_frame_host_ and not some other frame in the same tab.
-  void DidFinishNavigation(NavigationHandle* navigation_handle) override;
+  // is this->render_frame_host() and not some other frame in the same tab.
   void OnVisibilityChanged(Visibility visibility) override;
   void OnWebContentsLostFocus(RenderWidgetHost* render_widget_host) override;
 
@@ -407,16 +412,12 @@
 
   RenderProcessHost* GetRenderProcessHost();
   device::BluetoothAdapter* GetAdapter();
-  url::Origin GetOrigin();
   BluetoothAllowedDevices& allowed_devices();
 
   void StoreAllowedScanOptions(
       const blink::mojom::WebBluetoothRequestLEScanOptions& options);
   bool AreScanFiltersAllowed(const absl::optional<ScanFilters>& filters) const;
 
-  // Clears all state (maps, sets, etc).
-  void ClearState();
-
   // Clears state associated with Bluetooth LE Scanning.
   void ClearAdvertisementClients();
 
@@ -480,9 +481,6 @@
       base::queue<std::unique_ptr<DeferredStartNotificationData>>>
       characteristic_id_to_deferred_start_;
 
-  // The RFH that owns this instance.
-  RenderFrameHost* render_frame_host_;
-
   // Keeps track of our BLE scanning session.
   std::unique_ptr<device::BluetoothDiscoverySession>
       ble_scan_discovery_session_;
@@ -520,11 +518,6 @@
   std::unique_ptr<WebBluetoothPairingManager> pairing_manager_;
 #endif
 
-  // The lifetime of this instance is exclusively managed by the RFH that owns
-  // it so we use a "Receiver" as opposed to a "SelfOwnedReceiver" which deletes
-  // the service on pipe connection errors.
-  mojo::Receiver<blink::mojom::WebBluetoothService> receiver_;
-
   base::ScopedObservation<BluetoothDelegate,
                           BluetoothDelegate::FramePermissionObserver,
                           &BluetoothDelegate::AddFramePermissionObserver,
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc
index e86e631..b3b67be 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_browsertest.cc
@@ -19,6 +19,7 @@
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/prerender_test_util.h"
+#include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/test_web_contents.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
@@ -421,10 +422,17 @@
   // Loading a new primary page removes observer and stops scanning.
   EXPECT_CALL(*adapter(), RemoveObserver(_));
 
+  RenderFrameDeletedObserver rfh_observer(GetWebContents()->GetMainFrame());
+
   // Navigates the primary page to the URL.
   prerender_helper()->NavigatePrimaryPage(prerender_url);
   // The page should be activated from the prerendering.
   EXPECT_TRUE(host_observer.was_activated());
+
+  // Wait until the previous RFH to be disposed of, so a new bluetooth adapter
+  // can be set after that.
+  rfh_observer.WaitUntilDeleted();
+
   // Sets BluetoothAdapter for the new primary page since the previous
   // adapter is released by BluetoothAdapterFactoryWrapper::ReleaseAdapter().
   BluetoothAdapterFactoryWrapper::Get().SetBluetoothAdapterForTesting(
@@ -456,14 +464,8 @@
 
 // Tests that navigator.bluetooth.requestDevice() has an error without a user
 // gesture in the prerendering and works in the prerendering activation.
-// TODO(crbug.com/1269285): Fix flakiness on Linux and ChromeOS then reenable.
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
-#define MAYBE_RequestDeviceInPrerendering DISABLED_RequestDeviceInPrerendering
-#else
-#define MAYBE_RequestDeviceInPrerendering RequestDeviceInPrerendering
-#endif
 IN_PROC_BROWSER_TEST_F(WebBluetoothServiceImplBrowserTest,
-                       MAYBE_RequestDeviceInPrerendering) {
+                       RequestDeviceInPrerendering) {
   GURL url = embedded_test_server()->GetURL("/hello.html");
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
@@ -514,11 +516,17 @@
   // Loading a new primary page removes observer.
   EXPECT_CALL(*adapter(), RemoveObserver(_));
 
+  RenderFrameDeletedObserver rfh_observer(GetWebContents()->GetMainFrame());
+
   // Navigate to the prerendered page.
   prerender_helper()->NavigatePrimaryPage(prerender_url);
   // The page should be activated from the prerendering.
   EXPECT_TRUE(host_observer.was_activated());
 
+  // Wait until the previous RFH to be disposed of, so a new bluetooth adapter
+  // can be set after that.
+  rfh_observer.WaitUntilDeleted();
+
   // Sets BluetoothAdapter for the new primary page since the previous
   // adapter is released by BluetoothAdapterFactoryWrapper::ReleaseAdapter().
   BluetoothAdapterFactoryWrapper::Get().SetBluetoothAdapterForTesting(
@@ -539,16 +547,8 @@
 
 // Tests that GetBluetoothAllowed() only works with the main page in order to
 // ensure that it's no problem to get the main frame from the WebContents.
-// TODO(crbug.com/1269285): Fix flakiness on Linux and ChromeOS then reenable.
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
-#define MAYBE_GetBluetoothAllowedNotCalledInPrerendering \
-  DISABLED_GetBluetoothAllowedNotCalledInPrerendering
-#else
-#define MAYBE_GetBluetoothAllowedNotCalledInPrerendering \
-  GetBluetoothAllowedNotCalledInPrerendering
-#endif
 IN_PROC_BROWSER_TEST_F(WebBluetoothServiceImplBrowserTest,
-                       MAYBE_GetBluetoothAllowedNotCalledInPrerendering) {
+                       GetBluetoothAllowedNotCalledInPrerendering) {
   GURL url = embedded_test_server()->GetURL("/hello.html");
   EXPECT_TRUE(NavigateToURL(shell(), url));
 
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
index 06e3306..4b42ebe 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/test/bind.h"
+#include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/bluetooth/bluetooth_adapter_factory_wrapper.h"
 #include "content/browser/bluetooth/bluetooth_allowed_devices.h"
@@ -641,18 +642,17 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-TEST_F(WebBluetoothServiceImplTest, ClearStateDuringRequestDevice) {
+TEST_F(WebBluetoothServiceImplTest, DestroyedDuringRequestDevice) {
   auto options = blink::mojom::WebBluetoothRequestDeviceOptions::New();
   options->accept_all_devices = true;
 
+  base::MockCallback<WebBluetoothServiceImpl::RequestDeviceCallback> callback;
+  EXPECT_CALL(callback, Run).Times(0);
+  service_->RequestDevice(std::move(options), callback.Get());
+
   base::RunLoop loop;
-  service_->RequestDevice(
-      std::move(options),
-      base::BindLambdaForTesting(
-          [&loop](blink::mojom::WebBluetoothResult,
-                  blink::mojom::WebBluetoothDevicePtr) { loop.Quit(); }));
-  service_->ClearState();
-  loop.Run();
+  delete service_;
+  loop.RunUntilIdle();
 }
 
 TEST_F(WebBluetoothServiceImplTest, PermissionAllowed) {
@@ -671,7 +671,7 @@
   EXPECT_TRUE(service_->AreScanFiltersAllowed(filters));
 }
 
-TEST_F(WebBluetoothServiceImplTest, ClearStateDuringRequestScanningStart) {
+TEST_F(WebBluetoothServiceImplTest, DestroyedDuringRequestScanningStart) {
   blink::mojom::WebBluetoothLeScanFilterPtr filter = CreateScanFilter("a", "b");
   absl::optional<WebBluetoothServiceImpl::ScanFilters> filters;
 
@@ -684,33 +684,22 @@
   options->filters.emplace();
   options->filters->push_back(std::move(filter));
 
-  // Use two RunLoops to guarantee the order of operations for this test.
-  // |callback_loop| guarantees that RequestScanningStartCallback has finished
-  // executing and |result| has been populated. |request_loop| ensures that the
-  // entire RequestScanningStart flow has finished before |result| is checked.
-  base::RunLoop callback_loop, request_loop;
-  blink::mojom::WebBluetoothResult result;
-  service_->RequestScanningStart(
-      std::move(client), std::move(options),
-      base::BindLambdaForTesting(
-          [&callback_loop, &result](blink::mojom::WebBluetoothResult r) {
-            result = std::move(r);
-            callback_loop.Quit();
-          }));
+  // Check that a the callback is never called, as the service gets deleted
+  // during the scanning request.
+  base::RunLoop loop;
+  base::MockCallback<WebBluetoothServiceImpl::RequestScanningStartCallback>
+      callback;
+  EXPECT_CALL(callback, Run).Times(0);
+  service_->RequestScanningStart(std::move(client), std::move(options),
+                                 callback.Get());
 
-  // Post a task to clear the WebBluetoothService state during a call to
-  // RequestScanningStart(). This should cause the RequestScanningStartCallback
-  // to be run with an error result.
+  // Post a task to delete the WebBluetoothService state during a call to
+  // RequestScanningStart(). This should cause the callback to be dropped
+  // without being called.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindLambdaForTesting([&callback_loop, this, &request_loop]() {
-        service_->ClearState();
-        callback_loop.Run();
-        request_loop.Quit();
-      }));
-  request_loop.Run();
+      FROM_HERE, base::BindLambdaForTesting([this]() { delete service_; }));
 
-  EXPECT_NE(result, blink::mojom::WebBluetoothResult::SUCCESS);
+  loop.RunUntilIdle();
 }
 
 TEST_F(WebBluetoothServiceImplTest, PermissionPromptCanceled) {
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index c720660..bde99da 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -153,7 +153,7 @@
 
 base::debug::CrashKeyString* GetCanAccessDataFailureReasonKey() {
   static auto* crash_key = base::debug::AllocateCrashKeyString(
-      "can_access_data_failure_reason", base::debug::CrashKeySize::Size64);
+      "can_access_data_failure_reason", base::debug::CrashKeySize::Size256);
   return crash_key;
 }
 
@@ -1453,6 +1453,15 @@
   return state->HasPermissionsForFile(file, permissions);
 }
 
+size_t ChildProcessSecurityPolicyImpl::BrowsingInstanceIdCountForTesting(
+    int child_id) {
+  base::AutoLock lock(lock_);
+  SecurityState* security_state = GetSecurityState(child_id);
+  if (security_state)
+    return security_state->browsing_instance_ids().size();
+  return 0;
+}
+
 CanCommitStatus ChildProcessSecurityPolicyImpl::CanCommitOriginAndUrl(
     int child_id,
     const IsolationContext& isolation_context,
@@ -1544,9 +1553,6 @@
   DCHECK(IsRunningOnExpectedThread());
   base::AutoLock lock(lock_);
 
-  // TODO(wjmaclean): The following call to GetSecurityState can retrieve the
-  // wrong one if there are multiple browsing instances in one renderer process.
-  // https://crbug.com/1099718
   SecurityState* security_state = GetSecurityState(child_id);
   BrowserOrResourceContext browser_or_resource_context;
   if (security_state)
@@ -1576,7 +1582,53 @@
       // do not agree, the check might be slightly weaker (as the least common
       // denominator), but the differences must never violate the ProcessLock.
       if (security_state->browsing_instance_ids().empty()) {
-        failure_reason = "No BrowsingInstanceIDs.";
+        // If no BrowsingInstances are found, then the some of the state we need
+        // to perform an accurate check is unexpectedly missing, because there
+        // should always be a BrowsingInstance for such requests, even from
+        // workers. Thus, we should usually kill the process in this case, so
+        // that a compromised renderer can't bypass checks by sending IPCs when
+        // no BrowsingInstances are left.
+        //
+        // However, if the requested `url` is compatible with the current
+        // ProcessLock, then there is no need to kill the process because the
+        // checks would have passed anyway. To reduce the number of crashes
+        // while we debug why no BrowsingInstances were found (in
+        // https://crbug.com/1148542), we'll allow requests with an acceptable
+        // process lock to proceed.
+        // TODO(1148542): Remove this when known cases of having no
+        // BrowsingInstance IDs are solved.
+        url::Origin origin(url::Origin::Create(url));
+        bool matches_origin_keyed_process =
+            actual_process_lock.is_origin_keyed_process() &&
+            actual_process_lock.lock_url() == origin.GetURL();
+        bool matches_site_keyed_process =
+            !actual_process_lock.is_origin_keyed_process() &&
+            actual_process_lock.lock_url() ==
+                SiteInfo::GetSiteForOrigin(origin);
+        // ProcessLocks with is_pdf() = true actually means that the process is
+        // not supposed to access certain resources from the lock's site/origin,
+        // so it's safest here to fall through in that case. See discussion of
+        // https://crbug.com/1271197 below.
+        if (!actual_process_lock.is_pdf()) {
+          // If the ProcessLock isn't locked to a site, we should fall through
+          // since we have no way of knowing if the requested url was expecting
+          // to be in a locked process.
+          if (actual_process_lock.is_locked_to_site()) {
+            if (matches_origin_keyed_process || matches_site_keyed_process) {
+              return true;
+            } else {
+              failure_reason = base::StringPrintf(
+                  "No BrowsingInstanceIDs: Lock Mismatch. lock = %s vs. "
+                  "requested_url = %s ",
+                  actual_process_lock.ToString().c_str(), url.spec().c_str());
+            }
+          } else {
+            failure_reason =
+                "No BrowsingInstanceIDs: process not locked to site";
+          }
+        } else {
+          failure_reason = "No BrowsingInstanceIDs: process lock is_pdf";
+        }
         // This will fall through to the call to
         // LogCanAccessDataForOriginCrashKeys below, then return false.
       }
@@ -1618,6 +1670,10 @@
         // require COOP/COEP handling, to pass in their COOP/COEP information
         // so it can be used here instead of the values in
         // |actual_process_lock|.
+        // TODO(crbug.com/1271197): The code below is subtly incorrect in cases
+        // where actual_process_lock.is_pdf() is true, since in the case of PDFs
+        // the lock is intended to prevent access to the lock's site/origin,
+        // while still allowing the navigation to commit.
         expected_process_lock = ProcessLock::Create(
             isolation_context,
             UrlInfo(UrlInfoInit(url)
diff --git a/content/browser/child_process_security_policy_impl.h b/content/browser/child_process_security_policy_impl.h
index e797cafe..6e49488 100644
--- a/content/browser/child_process_security_policy_impl.h
+++ b/content/browser/child_process_security_policy_impl.h
@@ -524,6 +524,10 @@
     browsing_instance_cleanup_delay_ = base::Seconds(delay_in_seconds);
   }
 
+  // Allows tests to query the number of BrowsingInstanceIds associated with a
+  // child process.
+  size_t BrowsingInstanceIdCountForTesting(int child_id);
+
  private:
   friend class ChildProcessSecurityPolicyInProcessBrowserTest;
   friend class ChildProcessSecurityPolicyTest;
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc
index b125892a..e47ea22 100644
--- a/content/browser/child_process_security_policy_unittest.cc
+++ b/content/browser/child_process_security_policy_unittest.cc
@@ -13,16 +13,22 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/test/bind.h"
 #include "base/test/mock_log.h"
+#include "base/test/scoped_command_line.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/isolated_origin_util.h"
+#include "content/browser/origin_agent_cluster_isolation_state.h"
 #include "content/browser/process_lock.h"
 #include "content/browser/site_info.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/site_isolation_policy.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_browser_context.h"
@@ -119,6 +125,7 @@
     // protocols as this is the responsibility of the browser (which is
     // responsible for adding the appropriate ProtocolHandler).
     test_browser_client_.AddScheme(url::kFileScheme);
+    SiteIsolationPolicy::DisableFlagCachingForTesting();
   }
 
   void TearDown() override {
@@ -3011,4 +3018,186 @@
   p->ClearIsolatedOriginsForTesting();
 }
 
+// This test verifies that CanAccessDataForOrigin returns true for a process id
+// even if all BrowsingInstanceIDs for that process have been deleted, so long
+// as the request matches the process' lock. This test sets an origin-keyed
+// lock.
+TEST_F(ChildProcessSecurityPolicyTest, NoBrowsingInstanceIDs_OriginKeyed) {
+  url::Origin foo = url::Origin::Create(GURL("https://sub.foo.com/"));
+  ChildProcessSecurityPolicyImpl* p =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+  p->SetBrowsingInstanceCleanupDelayForTesting(0);
+
+  // Create a SiteInstance for sub.foo.com in a new BrowsingInstance.
+  TestBrowserContext context;
+  {
+    auto origin_isolation_request =
+        static_cast<UrlInfo::OriginIsolationRequest>(
+            UrlInfo::OriginIsolationRequest::kOriginAgentCluster |
+            UrlInfo::OriginIsolationRequest::kRequiresOriginKeyedProcess);
+    UrlInfo url_info(UrlInfoInit(foo.GetURL())
+                         .WithOrigin(foo)
+                         .WithOriginIsolationRequest(origin_isolation_request));
+    scoped_refptr<SiteInstanceImpl> foo_instance =
+        SiteInstanceImpl::CreateForUrlInfo(&context, url_info);
+
+    p->Add(kRendererID, &context);
+    p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
+                   foo_instance->GetProcessLock());
+
+    EXPECT_TRUE(p->GetProcessLock(kRendererID).is_locked_to_site());
+    EXPECT_TRUE(p->GetProcessLock(kRendererID).is_origin_keyed_process());
+    EXPECT_EQ(foo.GetURL(), p->GetProcessLock(kRendererID).lock_url());
+
+    EXPECT_TRUE(foo_instance->GetProcessLock().is_origin_keyed_process());
+    EXPECT_TRUE(p->DetermineOriginAgentClusterIsolation(
+                     foo_instance->GetIsolationContext(), foo,
+                     OriginAgentClusterIsolationState::CreateNonIsolated())
+                    .requires_origin_keyed_process());
+  }
+  // At this point foo_instance has gone away, and all BrowsingInstanceIDs
+  // associated with kRendererID have been cleaned up.
+  EXPECT_EQ(static_cast<size_t>(0),
+            p->BrowsingInstanceIdCountForTesting(kRendererID));
+
+  // Because the ProcessLock is origin-keyed, we expect sub.foo.com to match but
+  // not foo.com.
+  EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, foo));
+  EXPECT_FALSE(p->CanAccessDataForOrigin(
+      kRendererID, url::Origin::Create(GURL("https://foo.com/"))));
+  EXPECT_FALSE(p->CanAccessDataForOrigin(
+      kRendererID, url::Origin::Create(GURL("https://bar.com/"))));
+
+  // We need to remove it otherwise other tests may fail.
+  p->Remove(kRendererID);
+}
+
+// This test verifies that CanAccessDataForOrigin returns true for a process id
+// even if all BrowsingInstanceIDs for that process have been deleted, so long
+// as the request matches the process' lock. This test sets a site-keyed lock.
+TEST_F(ChildProcessSecurityPolicyTest, NoBrowsingInstanceIDs_SiteKeyed) {
+  url::Origin foo = url::Origin::Create(GURL("https://sub.foo.com/"));
+  ChildProcessSecurityPolicyImpl* p =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+  p->SetBrowsingInstanceCleanupDelayForTesting(0);
+
+  // Create a SiteInstance for sub.foo.com in a new BrowsingInstance.
+  TestBrowserContext context;
+  {
+    p->Add(kRendererID, &context);
+    // Isolate foo.com so we can't get a default SiteInstance. This will mean
+    // that https://sub.foo.com will end up in a site-keyed SiteInstance, which
+    // is what we need.
+    p->AddFutureIsolatedOrigins({url::Origin::Create(GURL("https://foo.com"))},
+                                IsolatedOriginSource::TEST, &context);
+
+    UrlInfo url_info(UrlInfoInit(foo.GetURL()).WithOrigin(foo));
+    scoped_refptr<SiteInstanceImpl> foo_instance =
+        SiteInstanceImpl::CreateForUrlInfo(&context, url_info);
+    p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
+                   foo_instance->GetProcessLock());
+
+    EXPECT_TRUE(p->GetProcessLock(kRendererID).is_locked_to_site());
+    EXPECT_FALSE(p->GetProcessLock(kRendererID).is_origin_keyed_process());
+    EXPECT_EQ(SiteInfo::GetSiteForOrigin(foo),
+              p->GetProcessLock(kRendererID).lock_url());
+
+    EXPECT_FALSE(foo_instance->GetProcessLock().is_origin_keyed_process());
+    EXPECT_FALSE(p->DetermineOriginAgentClusterIsolation(
+                      foo_instance->GetIsolationContext(), foo,
+                      OriginAgentClusterIsolationState::CreateNonIsolated())
+                     .requires_origin_keyed_process());
+  }
+  // At this point foo_instance has gone away, and all BrowsingInstanceIDs
+  // associated with kRendererID have been cleaned up.
+  EXPECT_EQ(static_cast<size_t>(0),
+            p->BrowsingInstanceIdCountForTesting(kRendererID));
+
+  // Because the ProcessLock is site-keyed, it should match foo.com and all
+  // sub-origins.
+  EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, foo));
+  EXPECT_TRUE(p->CanAccessDataForOrigin(
+      kRendererID, url::Origin::Create(GURL("https://foo.com/"))));
+  EXPECT_FALSE(p->CanAccessDataForOrigin(
+      kRendererID, url::Origin::Create(GURL("https://bar.com/"))));
+
+  // We need to remove it otherwise other tests may fail.
+  p->Remove(kRendererID);
+}
+
+// This test verifies that CanAccessDataForOrigin returns false for a process id
+// when all BrowsingInstanceIDs for that process have been deleted, and the
+// ProcessLock has is_locked_to_site() = false, regardless of the url requested.
+TEST_F(ChildProcessSecurityPolicyTest, NoBrowsingInstanceIDs_UnlockedProcess) {
+  GURL foo_url = GURL("https://foo.com/");
+  url::Origin foo = url::Origin::Create(foo_url);
+
+  ChildProcessSecurityPolicyImpl* p =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+  p->SetBrowsingInstanceCleanupDelayForTesting(0);
+
+  // Make sure feature list command-line options are set in a way that forces
+  // default SiteInstance creation on all platforms.
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitWithFeatures(
+      /* enable */ {features::kProcessSharingWithDefaultSiteInstances},
+      /* disable */ {features::kProcessSharingWithStrictSiteInstances});
+  EXPECT_TRUE(base::FeatureList::IsEnabled(
+      features::kProcessSharingWithDefaultSiteInstances));
+  EXPECT_FALSE(base::FeatureList::IsEnabled(
+      features::kProcessSharingWithStrictSiteInstances));
+
+  base::test::ScopedCommandLine scoped_command_line;
+  // Disable site isolation so we can get default SiteInstances on all
+  // platforms.
+  scoped_command_line.GetProcessCommandLine()->AppendSwitch(
+      switches::kDisableSiteIsolation);
+  // If --site-per-process was manually appended, remove it; this interferes
+  // with default SiteInstances.
+  scoped_command_line.GetProcessCommandLine()->RemoveSwitch(
+      switches::kSitePerProcess);
+
+  EXPECT_FALSE(SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
+  EXPECT_EQ(static_cast<size_t>(0),
+            p->BrowsingInstanceIdCountForTesting(kRendererID));
+
+  TestBrowserContext context;
+  {
+    scoped_refptr<SiteInstanceImpl> foo_instance =
+        SiteInstanceImpl::CreateForUrlInfo(&context,
+                                           UrlInfo::CreateForTesting(foo_url));
+    // Adds the process with an "allow_any_site" lock.
+    // The next two statements are basically AddForTesting(...), but with a
+    // BrowsingInstanceId based on `foo_instance` and not pinned to '1'.
+    // This is important when this test is run with other tests, as then
+    // BrowsingInstanceId will not be '1' in general.
+    p->Add(kRendererID, &context);
+    p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
+                   ProcessLock::CreateAllowAnySite(
+                       StoragePartitionConfig::CreateDefault(&context),
+                       WebExposedIsolationInfo::CreateNonIsolated()));
+
+    EXPECT_TRUE(foo_instance->IsDefaultSiteInstance());
+    EXPECT_TRUE(foo_instance->HasSite());
+    EXPECT_EQ(foo_instance->GetSiteInfo(),
+              SiteInfo::CreateForDefaultSiteInstance(
+                  &context, StoragePartitionConfig::CreateDefault(&context),
+                  WebExposedIsolationInfo::CreateNonIsolated()));
+    EXPECT_FALSE(foo_instance->RequiresDedicatedProcess());
+  }
+  // At this point foo_instance has gone away, and all BrowsingInstanceIDs
+  // associated with kRendererID have been cleaned up.
+  EXPECT_EQ(static_cast<size_t>(0),
+            p->BrowsingInstanceIdCountForTesting(kRendererID));
+
+  EXPECT_FALSE(p->GetProcessLock(kRendererID).is_locked_to_site());
+  // Ensure that we don't allow the process to keep accessing data for foo after
+  // all of the BrowsingInstances are gone, since that would require checking
+  // whether foo itself requires a dedicated process.
+  EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID, foo));
+
+  // We need to remove it otherwise other tests may fail.
+  p->Remove(kRendererID);
+}
+
 }  // namespace content
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn
index 74cdc14..365a4dd 100644
--- a/content/browser/devtools/BUILD.gn
+++ b/content/browser/devtools/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/compiler/pgo/pgo.gni")
 import("//build/config/devtools.gni")
 import("//components/viz/common/debugger/viz_debugger.gni")
 import("//third_party/inspector_protocol/inspector_protocol.gni")
@@ -40,8 +41,9 @@
   }
 }
 
-# Here we concatenate the viz_debugger.pdl into our browser protocol.
-# This technique is nearly identical to what is done for cros_protocol.pdl in chrome/browser/devtools
+# Here we concatenate the viz_debugger.pdl and native_profiling.pdl
+# into our browser protocol. This technique is nearly identical to what is
+# done for cros_protocol.pdl in chrome/browser/devtools
 _concatenated_protocol_path =
     "$root_gen_dir/content/browser/devtools/protocol.json"
 action("concatenate_protocols") {
@@ -61,6 +63,12 @@
     args += [ rebase_path(_visual_debugger_pdl, root_build_dir) ]
   }
 
+  if (use_clang_profiling_inside_sandbox && chrome_pgo_phase == 1) {
+    native_profiling_pdl = "//content/browser/native_profiling.pdl"
+    inputs += [ native_profiling_pdl ]
+    args += [ rebase_path(native_profiling_pdl, root_build_dir) ]
+  }
+
   args += [ rebase_path(output_file, root_build_dir) ]
 }
 
@@ -141,6 +149,13 @@
       "protocol/visual_debugger.h",
     ]
   }
+
+  if (chrome_pgo_phase == 1) {
+    outputs += [
+      "protocol/native_profiling.cc",
+      "protocol/native_profiling.h",
+    ]
+  }
 }
 
 proto_library("devtools_background_services_proto") {
diff --git a/content/browser/devtools/browser_devtools_agent_host.cc b/content/browser/devtools/browser_devtools_agent_host.cc
index eac2ba99..a5983fc 100644
--- a/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/content/browser/devtools/browser_devtools_agent_host.cc
@@ -5,11 +5,13 @@
 #include "content/browser/devtools/browser_devtools_agent_host.h"
 
 #include "base/bind.h"
+#include "base/clang_profiling_buildflags.h"
 #include "base/guid.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
 #include "base/task/single_thread_task_runner.h"
+#include "build/config/compiler/compiler_buildflags.h"
 #include "components/viz/common/buildflags.h"
 #include "content/browser/devtools/devtools_session.h"
 #include "content/browser/devtools/protocol/browser_handler.h"
@@ -32,6 +34,10 @@
 #include "content/browser/devtools/protocol/visual_debugger_handler.h"
 #endif
 
+#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) && BUILDFLAG(CLANG_PGO)
+#include "content/browser/devtools/protocol/native_profiling_handler.h"
+#endif
+
 namespace content {
 
 scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::CreateForBrowser(
@@ -188,6 +194,11 @@
   }
   session->AddHandler(
       std::make_unique<protocol::TracingHandler>(GetIOContext()));
+
+#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) && BUILDFLAG(CLANG_PGO)
+  session->AddHandler(std::make_unique<protocol::NativeProfilingHandler>());
+#endif
+
   return true;
 }
 
diff --git a/content/browser/devtools/protocol/native_profiling_handler.cc b/content/browser/devtools/protocol/native_profiling_handler.cc
new file mode 100644
index 0000000..853151f
--- /dev/null
+++ b/content/browser/devtools/protocol/native_profiling_handler.cc
@@ -0,0 +1,29 @@
+// 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 "content/browser/devtools/protocol/native_profiling_handler.h"
+
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/public/browser/profiling_utils.h"
+
+namespace content {
+namespace protocol {
+
+NativeProfilingHandler::NativeProfilingHandler()
+    : DevToolsDomainHandler(NativeProfiling::Metainfo::domainName) {}
+NativeProfilingHandler::~NativeProfilingHandler() = default;
+
+void NativeProfilingHandler::Wire(UberDispatcher* dispatcher) {
+  frontend_ =
+      std::make_unique<NativeProfiling::Frontend>(dispatcher->channel());
+  NativeProfiling::Dispatcher::wire(dispatcher, this);
+}
+
+DispatchResponse NativeProfilingHandler::DumpProfilingDataOfAllProcesses() {
+  content::WaitForAllChildrenToDumpProfilingData();
+  return Response::Success();
+}
+
+}  // namespace protocol
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/devtools/protocol/native_profiling_handler.h b/content/browser/devtools/protocol/native_profiling_handler.h
new file mode 100644
index 0000000..b973ca7
--- /dev/null
+++ b/content/browser/devtools/protocol/native_profiling_handler.h
@@ -0,0 +1,39 @@
+// 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NATIVE_PROFILING_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NATIVE_PROFILING_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_domain_handler.h"
+#include "content/browser/devtools/protocol/native_profiling.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace content {
+namespace protocol {
+
+// Handle the DevTool native profiling commands. This is currently used only
+// for the PGO instrumented build.
+class NativeProfilingHandler final : public DevToolsDomainHandler,
+                                     public NativeProfiling::Backend {
+ public:
+  NativeProfilingHandler();
+  NativeProfilingHandler(const NativeProfilingHandler& other) = delete;
+  NativeProfilingHandler& operator=(const NativeProfilingHandler& other) =
+      delete;
+  ~NativeProfilingHandler() override;
+
+  // DevToolsDomainHandler implementation.
+  void Wire(UberDispatcher* dispatcher) override;
+
+  // NativeProfiling::Backend.
+  DispatchResponse DumpProfilingDataOfAllProcesses() override;
+
+ private:
+  std::unique_ptr<NativeProfiling::Frontend> frontend_;
+};
+
+}  // namespace protocol
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NATIVE_PROFILING_HANDLER_H_
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
index 0dde926..95023d3 100644
--- a/content/browser/devtools/protocol/target_handler.cc
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -1149,6 +1149,23 @@
     }
   }
 
+  // Pre-process universal network access origins before actual context creation
+  // in case we need to bail out with error.
+  std::vector<url::Origin> originsToGrantUniversalNetworkAccess;
+  if (in_originsToGrantUniversalNetworkAccess.isJust()) {
+    for (const auto& origin_str :
+         *in_originsToGrantUniversalNetworkAccess.fromJust()) {
+      GURL url(origin_str);
+      url::Origin origin = url::Origin::Create(url);
+      if (!url.is_valid() || origin.opaque()) {
+        callback->sendFailure(
+            Response::InvalidParams("Invalid origin " + origin_str));
+        return;
+      }
+      originsToGrantUniversalNetworkAccess.push_back(std::move(origin));
+    }
+  }
+
   BrowserContext* context = delegate->CreateBrowserContext();
   if (!context) {
     callback->sendFailure(
@@ -1157,7 +1174,7 @@
     return;
   }
 
-  if (in_originsToGrantUniversalNetworkAccess.isJust()) {
+  for (const auto& origin : originsToGrantUniversalNetworkAccess) {
     std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns;
     allow_patterns.push_back(network::mojom::CorsOriginPattern::New());
     allow_patterns.back()->protocol = "http";
@@ -1168,19 +1185,10 @@
     allow_patterns.back()->priority =
         network::mojom::CorsOriginAccessMatchPriority::kMaxPriority;
 
-    for (const auto& origin_str :
-         *in_originsToGrantUniversalNetworkAccess.fromJust()) {
-      GURL url(origin_str);
-      url::Origin origin = url::Origin::Create(url);
-      if (!url.is_valid() || origin.opaque()) {
-        delegate->DisposeBrowserContext(context, base::DoNothing());
-        callback->sendFailure(Response::InvalidParams("Invalid origin"));
-        return;
-      }
-      content::CorsOriginPatternSetter::Set(context, std::move(origin),
-                                            mojo::Clone(allow_patterns), {},
-                                            base::DoNothing());
-    }
+    // It's fine to not await the completion here -- this is implicitly
+    // serialized with the actual URLLoaderFactory / URLLoader creation.
+    content::CorsOriginPatternSetter::Set(
+        context, origin, std::move(allow_patterns), {}, base::DoNothing());
   }
 
   if (pending_proxy_config_) {
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json
index cbc7a81..f47e589 100644
--- a/content/browser/devtools/protocol_config.json
+++ b/content/browser/devtools/protocol_config.json
@@ -52,6 +52,10 @@
                 "async": ["prepareForLeakDetection"]
             },
             {
+                "domain": "NativeProfiling",
+                "include": ["dumpProfilingDataOfAllProcesses"]
+            },
+            {
                 "domain": "Network",
                 "include": ["enable", "disable", "clearBrowserCache", "clearBrowserCookies", "getCookies", "getAllCookies", "deleteCookies", "setCookie", "setCookies", "setExtraHTTPHeaders", "canEmulateNetworkConditions", "emulateNetworkConditions", "setBypassServiceWorker", "setRequestInterception", "continueInterceptedRequest", "getResponseBodyForInterception", "setCacheDisabled", "takeResponseBodyForInterceptionAsStream", "getSecurityIsolationStatus", "loadNetworkResource", "setAcceptedEncodings", "clearAcceptedEncodingsOverride", "enableReportingApi"],
                 "include_events": ["requestWillBeSent", "responseReceived", "loadingFinished", "loadingFailed", "requestIntercepted", "signedExchangeReceived", "requestWillBeSentExtraInfo", "responseReceivedExtraInfo", "trustTokenOperationDone", "subresourceWebBundleMetadataReceived", "subresourceWebBundleMetadataError", "subresourceWebBundleInnerResponseParsed", "subresourceWebBundleInnerResponseError", "reportingApiReportAdded", "reportingApiReportUpdated", "reportingApiEndpointsChangedForOrigin"],
diff --git a/content/browser/media/cdm_registry_impl_unittest.cc b/content/browser/media/cdm_registry_impl_unittest.cc
index 5387e680..a0d5738 100644
--- a/content/browser/media/cdm_registry_impl_unittest.cc
+++ b/content/browser/media/cdm_registry_impl_unittest.cc
@@ -33,7 +33,7 @@
 
 const char kTestCdmName[] = "Test CDM";
 const char kAlternateCdmName[] = "Alternate CDM";
-const base::Token kTestCdmGuid{1234, 5678};
+const base::Token kTestCdmType{1234, 5678};
 const char kTestPath[] = "/aa/bb";
 const char kVersion1[] = "1.1.1.1";
 const char kVersion2[] = "1.1.1.2";
@@ -90,7 +90,7 @@
     return CdmInfo(kTestKeySystem, CdmInfo::Robustness::kSoftwareSecure,
                    GetTestCdmCapability(),
                    /*supports_sub_key_systems=*/true, kTestCdmName,
-                   kTestCdmGuid, base::Version(kVersion1),
+                   kTestCdmType, base::Version(kVersion1),
                    base::FilePath::FromUTF8Unsafe(kTestPath),
                    kTestFileSystemId);
   }
@@ -117,10 +117,10 @@
     return false;
   }
 
-  std::vector<std::string> GetVersions(const base::Token& guid) {
+  std::vector<std::string> GetVersions(const base::Token& cdm_type) {
     std::vector<std::string> versions;
     for (const auto& cdm : cdm_registry_.GetRegisteredCdms()) {
-      if (cdm.guid == guid)
+      if (cdm.type == cdm_type)
         versions.push_back(cdm.version.GetString());
     }
     return versions;
@@ -183,7 +183,7 @@
   cdm_info.version = base::Version(kVersion2);
   Register(cdm_info);
 
-  const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
+  const std::vector<std::string> versions = GetVersions(kTestCdmType);
   EXPECT_EQ(2u, versions.size());
   EXPECT_EQ(kVersion1, versions[0]);
   EXPECT_EQ(kVersion2, versions[1]);
diff --git a/content/browser/media/key_system_support_impl_unittest.cc b/content/browser/media/key_system_support_impl_unittest.cc
index fbc429e..806dbc1 100644
--- a/content/browser/media/key_system_support_impl_unittest.cc
+++ b/content/browser/media/key_system_support_impl_unittest.cc
@@ -43,7 +43,7 @@
 using testing::_;
 
 const char kTestCdmName[] = "Test Content Decryption Module";
-const base::Token kTestCdmGuid{1234, 5678};
+const base::Token kTestCdmType{1234, 5678};
 const char kVersion[] = "1.1.1.1";
 const char kTestPath[] = "/aa/bb";
 const char kTestFileSystemId[] = "file_system_id";
@@ -129,7 +129,7 @@
 
     CdmRegistry::GetInstance()->RegisterCdm(
         CdmInfo(key_system, robustness, std::move(capability),
-                /*supports_sub_key_systems=*/false, kTestCdmName, kTestCdmGuid,
+                /*supports_sub_key_systems=*/false, kTestCdmName, kTestCdmType,
                 base::Version(kVersion),
                 base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId));
   }
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc
index da52565b..d3a30ffb 100644
--- a/content/browser/media/media_interface_proxy.cc
+++ b/content/browser/media/media_interface_proxy.cc
@@ -520,45 +520,45 @@
     return nullptr;
   }
 
-  auto& cdm_guid = cdm_info->guid;
+  auto& cdm_type = cdm_info->type;
 
-  auto found = cdm_factory_map_.find(cdm_guid);
+  auto found = cdm_factory_map_.find(cdm_type);
   if (found != cdm_factory_map_.end())
     return found->second.get();
 
-  return ConnectToCdmService(cdm_guid, *cdm_info);
+  return ConnectToCdmService(cdm_type, *cdm_info);
 }
 
 media::mojom::CdmFactory* MediaInterfaceProxy::ConnectToCdmService(
-    const base::Token& cdm_guid,
+    const base::Token& cdm_type,
     const CdmInfo& cdm_info) {
   DVLOG(1) << __func__ << ": cdm_name = " << cdm_info.name;
 
-  DCHECK(!cdm_factory_map_.count(cdm_guid));
+  DCHECK(!cdm_factory_map_.count(cdm_type));
 
   auto* browser_context = render_frame_host().GetBrowserContext();
   auto& site = render_frame_host().GetSiteInstance()->GetSiteURL();
-  auto& cdm_service = GetCdmService(cdm_guid, browser_context, site, cdm_info);
+  auto& cdm_service = GetCdmService(cdm_type, browser_context, site, cdm_info);
 
   mojo::Remote<media::mojom::CdmFactory> cdm_factory_remote;
   cdm_service.CreateCdmFactory(cdm_factory_remote.BindNewPipeAndPassReceiver(),
                                GetFrameServices(cdm_info.file_system_id));
   cdm_factory_remote.set_disconnect_handler(
       base::BindOnce(&MediaInterfaceProxy::OnCdmServiceConnectionError,
-                     base::Unretained(this), cdm_guid));
+                     base::Unretained(this), cdm_type));
 
   auto* cdm_factory = cdm_factory_remote.get();
-  cdm_factory_map_.emplace(cdm_guid, std::move(cdm_factory_remote));
+  cdm_factory_map_.emplace(cdm_type, std::move(cdm_factory_remote));
   return cdm_factory;
 }
 
 void MediaInterfaceProxy::OnCdmServiceConnectionError(
-    const base::Token& cdm_guid) {
+    const base::Token& cdm_type) {
   DVLOG(1) << __func__;
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  DCHECK(cdm_factory_map_.count(cdm_guid));
-  cdm_factory_map_.erase(cdm_guid);
+  DCHECK(cdm_factory_map_.count(cdm_type));
+  cdm_factory_map_.erase(cdm_type);
 }
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
diff --git a/content/browser/media/media_interface_proxy.h b/content/browser/media/media_interface_proxy.h
index 644613b..8b59cc30 100644
--- a/content/browser/media/media_interface_proxy.h
+++ b/content/browser/media/media_interface_proxy.h
@@ -105,18 +105,18 @@
   // error happened.
   media::mojom::CdmFactory* GetCdmFactory(const std::string& key_system);
 
-  // Connects to the CDM service associated with |cdm_guid|, adds the new
+  // Connects to the CDM service associated with |cdm_type|, adds the new
   // CdmFactoryPtr to the |cdm_factory_map_|, and returns the newly created
   // CdmFactory pointer. Returns nullptr if unexpected error happened.
   // |cdm_path| will be used to preload the CDM, if necessary.
   // |cdm_file_system_id| is used when creating the matching storage interface.
   // |cdm_name| is used as the display name of the CDM (utility) process.
-  media::mojom::CdmFactory* ConnectToCdmService(const base::Token& cdm_guid,
+  media::mojom::CdmFactory* ConnectToCdmService(const base::Token& cdm_type,
                                                 const CdmInfo& cdm_info);
 
   // Callback for connection error from the CdmFactoryPtr in the
-  // |cdm_factory_map_| associated with |cdm_guid|.
-  void OnCdmServiceConnectionError(const base::Token& cdm_guid);
+  // |cdm_factory_map_| associated with |cdm_type|.
+  void OnCdmServiceConnectionError(const base::Token& cdm_type);
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
 #if defined(OS_CHROMEOS)
@@ -160,7 +160,7 @@
   std::unique_ptr<MediaInterfaceFactoryHolder> secondary_interface_factory_;
 
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-  // CDM GUID to CDM InterfaceFactory Remotes mapping, where the
+  // CDM type to CDM InterfaceFactory Remotes mapping, where the
   // InterfaceFactory instances live in the standalone CdmService instances.
   // These map entries effectively own the corresponding CDM processes.
   // Only using the GUID to identify the CdmFactory is sufficient because the
diff --git a/content/browser/media/service_factory.cc b/content/browser/media/service_factory.cc
index de456f1..e57da58 100644
--- a/content/browser/media/service_factory.cc
+++ b/content/browser/media/service_factory.cc
@@ -168,10 +168,10 @@
   GetServiceMap<T>().EraseRemote(key);
 }
 
-// Gets an instance of the service for `guid`, `browser_context` and `site`.
+// Gets an instance of the service for `cdm_type`, `browser_context` and `site`.
 // Instances are started lazily as needed.
 template <typename T>
-T& GetService(const base::Token& guid,
+T& GetService(const base::Token& cdm_type,
               BrowserContext* browser_context,
               const GURL& site,
               const std::string& service_name,
@@ -180,14 +180,14 @@
   std::string display_name = service_name;
 
   if (base::FeatureList::IsEnabled(media::kCdmProcessSiteIsolation)) {
-    key = {guid, browser_context, site};
+    key = {cdm_type, browser_context, site};
     auto site_display_name =
         GetContentClient()->browser()->GetSiteDisplayNameForCdmProcess(
             browser_context, site);
     if (!site_display_name.empty())
       display_name += " (" + site_display_name + ")";
   } else {
-    key = {guid, nullptr, GURL()};
+    key = {cdm_type, nullptr, GURL()};
   }
   DVLOG(2) << __func__ << ": key=" << key;
 
@@ -224,11 +224,11 @@
 
 }  // namespace
 
-media::mojom::CdmService& GetCdmService(const base::Token& guid,
+media::mojom::CdmService& GetCdmService(const base::Token& cdm_type,
                                         BrowserContext* browser_context,
                                         const GURL& site,
                                         const CdmInfo& cdm_info) {
-  return GetService<media::mojom::CdmService>(guid, browser_context, site,
+  return GetService<media::mojom::CdmService>(cdm_type, browser_context, site,
                                               cdm_info.name, cdm_info.path);
 }
 
diff --git a/content/browser/media/service_factory.h b/content/browser/media/service_factory.h
index 426895d..ba81bac 100644
--- a/content/browser/media/service_factory.h
+++ b/content/browser/media/service_factory.h
@@ -19,10 +19,10 @@
 
 class BrowserContext;
 
-// Gets an instance of the CdmService for the `guid`, `browser_context` and
+// Gets an instance of the CdmService for the `cdm_type`, `browser_context` and
 // the `site`. Instances are started lazily as needed. The CDM located at
 // `cdm_path` is loaded in the sandboxed process to be used by the service.
-media::mojom::CdmService& GetCdmService(const base::Token& guid,
+media::mojom::CdmService& GetCdmService(const base::Token& cdm_type,
                                         BrowserContext* browser_context,
                                         const GURL& site,
                                         const CdmInfo& cdm_info);
diff --git a/content/browser/native_profiling.pdl b/content/browser/native_profiling.pdl
new file mode 100644
index 0000000..eb45816
--- /dev/null
+++ b/content/browser/native_profiling.pdl
@@ -0,0 +1,11 @@
+# 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.
+
+version
+  major 1
+  minor 0
+
+experimental domain NativeProfiling
+  # Request a dump of the profiling data for all processes.
+  command dumpProfilingDataOfAllProcesses
\ No newline at end of file
diff --git a/content/browser/network_service_browsertest.cc b/content/browser/network_service_browsertest.cc
index 35118a7..148101a 100644
--- a/content/browser/network_service_browsertest.cc
+++ b/content/browser/network_service_browsertest.cc
@@ -514,12 +514,15 @@
   mojo::Remote<network::mojom::NetworkServiceTest> network_service_test;
   content::GetNetworkService()->BindTestInterface(
       network_service_test.BindNewPipeAndPassReceiver());
-  network_service_test.FlushForTesting();
-
-  mojo::ScopedAllowSyncCallForTesting allow_sync_call;
 
   int64_t count = 0;
-  EXPECT_TRUE(network_service_test->GetFirstPartySetEntriesCount(&count));
+  base::RunLoop run_loop;
+  network_service_test->GetFirstPartySetEntriesCount(
+      base::BindLambdaForTesting([&](int64_t count_from_network_service) {
+        count = count_from_network_service;
+        run_loop.Quit();
+      }));
+  run_loop.Run();
 
   return count;
 }
diff --git a/content/browser/payments/payment_app_provider_util.cc b/content/browser/payments/payment_app_provider_util.cc
index 3fdc3f9..6e657f5 100644
--- a/content/browser/payments/payment_app_provider_util.cc
+++ b/content/browser/payments/payment_app_provider_util.cc
@@ -5,7 +5,7 @@
 #include "content/public/browser/payment_app_provider_util.h"
 
 #include "content/browser/service_worker/service_worker_loader_helpers.h"
-#include "content/common/service_worker/service_worker_utils.h"
+#include "content/browser/service_worker/service_worker_security_utils.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace content {
@@ -36,7 +36,8 @@
   // TODO(crbug.com/855312): Unify duplicated code between here and
   // ServiceWorkerProviderHost::IsValidRegisterMessage.
   std::vector<GURL> urls = {manifest_url, sw_js_url, sw_scope};
-  if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+  if (!service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          urls)) {
     *error_message =
         "Origins are not matching, or some origins cannot access service "
         "worker (manifest:" +
diff --git a/content/browser/profiling_utils.cc b/content/browser/profiling_utils.cc
new file mode 100644
index 0000000..5af571b
--- /dev/null
+++ b/content/browser/profiling_utils.cc
@@ -0,0 +1,136 @@
+// 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 <memory>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "base/rand_util.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+#include "content/public/browser/browser_child_process_host_iterator.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/gpu_utils.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/child_process_host.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/profiling_utils.h"
+
+namespace content {
+
+// Serves WaitableEvent that should be used by the child processes to signal
+// that they have finished dumping the profiling data.
+class WaitForProcessesToDumpProfilingInfo {
+ public:
+  WaitForProcessesToDumpProfilingInfo();
+  ~WaitForProcessesToDumpProfilingInfo();
+  WaitForProcessesToDumpProfilingInfo(
+      const WaitForProcessesToDumpProfilingInfo& other) = delete;
+  WaitForProcessesToDumpProfilingInfo& operator=(
+      const WaitForProcessesToDumpProfilingInfo&) = delete;
+
+  // Wait for all the events served by |GetNewWaitableEvent| to signal.
+  void WaitForAll();
+
+  // Return a new waitable event. Calling |WaitForAll| will wait for this event
+  // to be signaled.
+  // The returned WaitableEvent is owned by this
+  // WaitForProcessesToDumpProfilingInfo instance.
+  base::WaitableEvent* GetNewWaitableEvent();
+
+ private:
+  // Implementation of WaitForAll that will run on the thread pool.
+  void WaitForAllOnThreadPool();
+
+  std::vector<std::unique_ptr<base::WaitableEvent>> events_;
+};
+
+WaitForProcessesToDumpProfilingInfo::WaitForProcessesToDumpProfilingInfo() =
+    default;
+WaitForProcessesToDumpProfilingInfo::~WaitForProcessesToDumpProfilingInfo() =
+    default;
+
+void WaitForProcessesToDumpProfilingInfo::WaitForAll() {
+  base::RunLoop nested_run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+
+  // Some of the waitable events will be signaled on the main thread, use a
+  // nested run loop to ensure we're not preventing them from signaling.
+  base::ThreadPool::PostTaskAndReply(
+      FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+      base::BindOnce(
+          &WaitForProcessesToDumpProfilingInfo::WaitForAllOnThreadPool,
+          base::Unretained(this)),
+      nested_run_loop.QuitClosure());
+  nested_run_loop.Run();
+}
+
+void WaitForProcessesToDumpProfilingInfo::WaitForAllOnThreadPool() {
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_blocking;
+
+  std::vector<base::WaitableEvent*> events_raw;
+  events_raw.reserve(events_.size());
+  for (const auto& iter : events_)
+    events_raw.push_back(iter.get());
+
+  // Wait for all the events to be signaled.
+  while (events_raw.size()) {
+    size_t index =
+        base::WaitableEvent::WaitMany(events_raw.data(), events_raw.size());
+    events_raw.erase(events_raw.begin() + index);
+  }
+}
+
+base::WaitableEvent*
+WaitForProcessesToDumpProfilingInfo::GetNewWaitableEvent() {
+  events_.push_back(std::make_unique<base::WaitableEvent>());
+  return events_.back().get();
+}
+
+void WaitForAllChildrenToDumpProfilingData() {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSingleProcess)) {
+    return;
+  }
+  WaitForProcessesToDumpProfilingInfo wait_for_profiling_data;
+
+  // Ask all the renderer processes to dump their profiling data.
+  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
+       !i.IsAtEnd(); i.Advance()) {
+    DCHECK(!i.GetCurrentValue()->GetProcess().is_current());
+    if (!i.GetCurrentValue()->IsInitializedAndNotDead())
+      continue;
+    i.GetCurrentValue()->DumpProfilingData(base::BindOnce(
+        &base::WaitableEvent::Signal,
+        base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
+  }
+
+  // Ask all the other child processes to dump their profiling data
+  for (content::BrowserChildProcessHostIterator browser_child_iter;
+       !browser_child_iter.Done(); ++browser_child_iter) {
+    browser_child_iter.GetHost()->DumpProfilingData(base::BindOnce(
+        &base::WaitableEvent::Signal,
+        base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
+  }
+
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kInProcessGPU)) {
+    DumpGpuProfilingData(base::BindOnce(
+        &base::WaitableEvent::Signal,
+        base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
+  }
+
+  // This will block until all the child processes have saved their profiling
+  // data to disk.
+  wait_for_profiling_data.WaitForAll();
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
index 0ee3962..3d2316d 100644
--- a/content/browser/renderer_host/media/peer_connection_tracker_host.cc
+++ b/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -165,6 +165,19 @@
   }
 }
 
+void PeerConnectionTrackerHost::GetUserMediaSuccess(
+    int request_id,
+    const std::string& stream_id,
+    const std::string& audio_track_info,
+    const std::string& video_track_info) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  for (auto& observer : GetObserverList()) {
+    observer.OnGetUserMediaSuccess(frame_id_, peer_pid_, request_id, stream_id,
+                                   audio_track_info, video_track_info);
+  }
+}
+
 void PeerConnectionTrackerHost::WebRtcEventLogWrite(
     int lid,
     const std::vector<uint8_t>& output) {
diff --git a/content/browser/renderer_host/media/peer_connection_tracker_host.h b/content/browser/renderer_host/media/peer_connection_tracker_host.h
index aafd369..25a37dd 100644
--- a/content/browser/renderer_host/media/peer_connection_tracker_host.h
+++ b/content/browser/renderer_host/media/peer_connection_tracker_host.h
@@ -91,6 +91,10 @@
                     bool video,
                     const std::string& audio_constraints,
                     const std::string& video_constraints) override;
+  void GetUserMediaSuccess(int request_id,
+                           const std::string& stream_id,
+                           const std::string& audio_track_info,
+                           const std::string& video_track_info) override;
   void WebRtcEventLogWrite(int lid,
                            const std::vector<uint8_t>& output) override;
   void AddStandardStats(int lid, base::Value value) override;
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index e0463a93..82a249b 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -1291,13 +1291,14 @@
       ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
       false /* was_opener_suppressed */, false /* is_pdf */));
 
-  // TODO(https://crbug.com/1199077): Initialize the StorageKey also with the
-  // top frame origin.
   absl::optional<base::UnguessableToken> nonce =
       render_frame_host->ComputeNonce(navigation_request->anonymous());
+  url::Origin top_level_origin =
+      render_frame_host->ComputeTopFrameOrigin(origin);
   navigation_request->commit_params_->storage_key =
-      nonce ? blink::StorageKey::CreateWithNonce(origin, nonce.value())
-            : blink::StorageKey(origin);
+      blink::StorageKey::CreateWithOptionalNonce(
+          origin, net::SchemefulSite(top_level_origin),
+          base::OptionalOrNullptr(nonce));
   navigation_request->web_bundle_navigation_info_ =
       std::move(web_bundle_navigation_info);
   if (subresource_web_bundle_navigation_info) {
@@ -4286,17 +4287,16 @@
           origin, anonymous());
   DCHECK(!isolation_info_for_subresources_.IsEmpty());
 
-  // TODO(https://crbug.com/1199077): Initialize the StorageKey also with the
-  // top frame origin.
-  //
   // TODO(https://crbug.com/888079): The storage key's origin is ignored at the
   // moment. We will be able to use it once the browser can compute the origin
   // to commit.
   absl::optional<base::UnguessableToken> nonce =
       render_frame_host_->ComputeNonce(anonymous());
-  commit_params_->storage_key = nonce ? blink::StorageKey::CreateWithNonce(
-                                            GetOriginToCommit(), nonce.value())
-                                      : blink::StorageKey(GetOriginToCommit());
+  url::Origin top_level_origin =
+      render_frame_host_->ComputeTopFrameOrigin(GetOriginToCommit());
+  commit_params_->storage_key = blink::StorageKey::CreateWithOptionalNonce(
+      GetOriginToCommit(), net::SchemefulSite(top_level_origin),
+      base::OptionalOrNullptr(nonce));
 
   if (IsServedFromBackForwardCache() || IsPrerenderedPageActivation()) {
     CommitPageActivation();
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 24678aa1..254eb19 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -30,6 +30,7 @@
 #include "base/no_destructor.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/process/kill.h"
+#include "base/ranges/algorithm.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
@@ -3684,14 +3685,7 @@
   isolation_info_ = ComputeIsolationInfoInternal(
       new_frame_origin, net::IsolationInfo::RequestType::kOther, anonymous());
   SetLastCommittedOrigin(new_frame_origin);
-
-  absl::optional<base::UnguessableToken> nonce = ComputeNonce(anonymous());
-
-  // TODO(https://crbug.com/1199077): Initialize the StorageKey also with the
-  // top frame origin.
-  SetStorageKey(nonce ? blink::StorageKey::CreateWithNonce(new_frame_origin,
-                                                           nonce.value())
-                      : blink::StorageKey(new_frame_origin));
+  SetStorageKey(blink::StorageKey::FromNetIsolationInfo(isolation_info_));
 
   // Apply private network request policy according to our new origin.
   if (GetContentClient()->browser()->ShouldAllowInsecurePrivateNetworkRequests(
@@ -4299,8 +4293,6 @@
   if (web_ui())
     web_ui()->RenderFrameHostUnloading();
 
-  web_bluetooth_services_.clear();
-
   StartPendingDeletionOnSubtree();
   // Some children with no unload handler may be eligible for deletion. Cut the
   // dead branches now. This is a performance optimization.
@@ -9220,40 +9212,33 @@
       BackForwardCacheDisablingFeature::kPaymentManager);
 }
 
+WebBluetoothServiceImpl*
+RenderFrameHostImpl::GetWebBluetoothServiceForTesting() {
+  if (!document_associated_data_ || !last_web_bluetooth_service_for_testing_)
+    return nullptr;
+
+  // Checking the list of services to make sure the last WebBluetoothServiceImpl
+  // instance has not been invalidated since then.
+  auto it = base::ranges::find(document_associated_data_->services,
+                               last_web_bluetooth_service_for_testing_);
+  if (document_associated_data_->services.end() == it) {
+    last_web_bluetooth_service_for_testing_ = nullptr;
+  }
+
+  return last_web_bluetooth_service_for_testing_;
+}
+
 void RenderFrameHostImpl::CreateWebBluetoothService(
     mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver) {
   BackForwardCache::DisableForRenderFrameHost(
       this, BackForwardCacheDisable::DisabledReason(
                 BackForwardCacheDisable::DisabledReasonId::kWebBluetooth));
-  // RFHI owns |web_bluetooth_services_| and |web_bluetooth_service| owns the
-  // |receiver_| which may run the error handler. |receiver_| can't run the
-  // error handler after it's destroyed so it can't run after the RFHI is
-  // destroyed.
-  auto web_bluetooth_service =
-      std::make_unique<WebBluetoothServiceImpl>(this, std::move(receiver));
-  web_bluetooth_service->SetClientConnectionErrorHandler(
-      base::BindOnce(&RenderFrameHostImpl::DeleteWebBluetoothService,
-                     base::Unretained(this), web_bluetooth_service.get()));
-  web_bluetooth_services_.push_back(std::move(web_bluetooth_service));
-}
 
-WebBluetoothServiceImpl*
-RenderFrameHostImpl::GetWebBluetoothServiceForTesting() {
-  if (web_bluetooth_services_.empty())
-    return nullptr;
-  return web_bluetooth_services_.back().get();
-}
-
-void RenderFrameHostImpl::DeleteWebBluetoothService(
-    WebBluetoothServiceImpl* web_bluetooth_service) {
-  auto it = std::find_if(
-      web_bluetooth_services_.begin(), web_bluetooth_services_.end(),
-      [web_bluetooth_service](
-          const std::unique_ptr<WebBluetoothServiceImpl>& service) {
-        return web_bluetooth_service == service.get();
-      });
-  DCHECK(it != web_bluetooth_services_.end());
-  web_bluetooth_services_.erase(it);
+  // Although the returned pointer is being stored for test support, this is not
+  // a test-only function, and the call of WebBluetoothServiceImpl::Create below
+  // is how the WebBluetoothServiceImpl instance gets created.
+  last_web_bluetooth_service_for_testing_ =
+      WebBluetoothServiceImpl::Create(this, std::move(receiver));
 }
 
 void RenderFrameHostImpl::CreateWebUsbService(
@@ -9265,6 +9250,13 @@
 }
 
 void RenderFrameHostImpl::ResetPermissionsPolicy() {
+  if (IsNestedWithinFencedFrame()) {
+    // In Fenced Frames, all permission policy gated features must be disabled
+    // for privacy reasons.
+    permissions_policy_ =
+        blink::PermissionsPolicy::CreateForFencedFrame(last_committed_origin_);
+    return;
+  }
   RenderFrameHostImpl* parent_frame_host = GetParent();
   const blink::PermissionsPolicy* parent_policy =
       parent_frame_host ? parent_frame_host->permissions_policy() : nullptr;
@@ -10660,11 +10652,9 @@
   const blink::StorageKey& provisional_storage_key =
       navigation_request->commit_params().storage_key;
   blink::StorageKey storage_key_to_commit =
-      provisional_storage_key.nonce().has_value()
-          ? blink::StorageKey::CreateWithNonce(
-                GetLastCommittedOrigin(),
-                provisional_storage_key.nonce().value())
-          : blink::StorageKey(GetLastCommittedOrigin());
+      blink::StorageKey::CreateWithOptionalNonce(
+          GetLastCommittedOrigin(), provisional_storage_key.top_level_site(),
+          base::OptionalOrNullptr(provisional_storage_key.nonce()));
   SetStorageKey(storage_key_to_commit);
 
   coep_reporter_ = navigation_request->TakeCoepReporter();
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index cf25d72..140fa18 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -2868,14 +2868,11 @@
   // frames, it will return the current frame's view.
   RenderWidgetHostViewBase* GetViewForAccessibility();
 
-  // Returns a raw pointer to the Web Bluetooth Service owned by the frame. Used
-  // for testing purposes only (see |TestRenderFrameHost|).
+  // Returns a raw pointer to the last Web Bluetooth Service associated with the
+  // frame, or nullptr otherwise. Used for testing purposes only (see
+  // |TestRenderFrameHost|).
   WebBluetoothServiceImpl* GetWebBluetoothServiceForTesting();
 
-  // Deletes the Web Bluetooth Service owned by the frame.
-  void DeleteWebBluetoothService(
-      WebBluetoothServiceImpl* web_bluetooth_service);
-
   // Allows tests to disable the unload event timer to simulate bugs that
   // happen before it fires (to avoid flakiness).
   void DisableUnloadTimerForTesting();
@@ -3505,8 +3502,6 @@
 
   std::unique_ptr<service_manager::InterfaceProvider> remote_interfaces_;
 
-  std::list<std::unique_ptr<WebBluetoothServiceImpl>> web_bluetooth_services_;
-
   // The object managing the accessibility tree for this frame.
   std::unique_ptr<BrowserAccessibilityManager> browser_accessibility_manager_;
 
@@ -4112,6 +4107,9 @@
   // nested within a fenced frame.
   const FencedFrameStatus fenced_frame_status_;
 
+  // Used when testing to retrieve that last created Web Bluetooth service.
+  WebBluetoothServiceImpl* last_web_bluetooth_service_for_testing_ = nullptr;
+
   // NOTE: This must be the last member.
   base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_{this};
 };
diff --git a/content/browser/resources/attribution_reporting/attribution_internals.js b/content/browser/resources/attribution_reporting/attribution_internals.js
index c9eca515..431e228 100644
--- a/content/browser/resources/attribution_reporting/attribution_internals.js
+++ b/content/browser/resources/attribution_reporting/attribution_internals.js
@@ -400,6 +400,9 @@
       case WebUIAttributionReport_Status.kDroppedForNoise:
         this.status = 'Dropped for noise';
         break;
+      case WebUIAttributionReport_Status.kProhibitedByBrowserPolicy:
+        this.status = 'Prohibited by browser policy';
+        break;
     }
   }
 }
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc
index f1c6c827..417d7c7 100644
--- a/content/browser/service_worker/service_worker_container_host.cc
+++ b/content/browser/service_worker/service_worker_container_host.cc
@@ -18,9 +18,9 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_object_host.h"
 #include "content/browser/service_worker/service_worker_registration_object_host.h"
+#include "content/browser/service_worker/service_worker_security_utils.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/content_navigation_policy.h"
-#include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/origin_util.h"
@@ -185,7 +185,8 @@
   }
 
   std::vector<GURL> urls = {url_, options->scope, script_url};
-  if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+  if (!service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          urls)) {
     mojo::ReportBadMessage(ServiceWorkerConsts::kBadMessageImproperOrigins);
     // ReportBadMessage() will kill the renderer process, but Mojo complains if
     // the callback is not run. Just run it with nonsense arguments.
@@ -1581,7 +1582,8 @@
     return false;
   }
   std::vector<GURL> urls = {url_, client_url};
-  if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+  if (!service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          urls)) {
     *out_error = ServiceWorkerConsts::kBadMessageImproperOrigins;
     return false;
   }
@@ -1664,7 +1666,7 @@
 blink::StorageKey
 ServiceWorkerContainerHost::GetCorrectStorageKeyForWebSecurityState(
     const GURL& url) const {
-  if (ServiceWorkerUtils::IsWebSecurityDisabled()) {
+  if (service_worker_security_utils::IsWebSecurityDisabled()) {
     url::Origin other_origin = url::Origin::Create(url);
 
     if (key_.origin() != other_origin)
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 1cafcc9..b08719c 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -33,6 +33,7 @@
 #include "content/browser/service_worker/service_worker_quota_client.h"
 #include "content/browser/service_worker/service_worker_register_job.h"
 #include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_security_utils.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/common/content_navigation_policy.h"
@@ -706,7 +707,8 @@
     return false;
 
   urls.push_back(key.origin().GetURL());
-  if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+  if (!service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          urls)) {
     *out_error = ServiceWorkerConsts::kBadMessageImproperOrigins;
     return false;
   }
diff --git a/content/browser/service_worker/service_worker_new_script_loader_unittest.cc b/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
index 04fc4cd..9438be30 100644
--- a/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
@@ -459,36 +459,6 @@
   histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
 }
 
-// Tests that service workers fail to load over a connection with legacy TLS.
-TEST_F(ServiceWorkerNewScriptLoaderTest, Error_LegacyTLS) {
-  base::HistogramTester histogram_tester;
-
-  std::unique_ptr<network::TestURLLoaderClient> client;
-  std::unique_ptr<ServiceWorkerNewScriptLoader> loader;
-
-  // Serve a response with a certificate error.
-  const GURL kScriptURL("https://example.com/certificate-error.js");
-  MockHTTPServer::Response response(std::string("HTTP/1.1 200 OK\n\n"),
-                                    std::string("body"));
-  response.has_certificate_error = true;
-  response.cert_status = net::CERT_STATUS_LEGACY_TLS;
-  mock_server_.Set(kScriptURL, response);
-  SetUpRegistration(kScriptURL);
-  DoRequest(kScriptURL, &client, &loader);
-  client->RunUntilComplete();
-
-  // The request should be failed because of the response with the legacy TLS
-  // error.
-  EXPECT_EQ(net::ERR_SSL_OBSOLETE_VERSION,
-            client->completion_status().error_code);
-  EXPECT_FALSE(client->has_received_response());
-
-  // The response shouldn't be stored in the storage.
-  EXPECT_FALSE(VerifyStoredResponse(kScriptURL));
-  // No sample should be recorded since a write didn't occur.
-  histogram_tester.ExpectTotalCount(kHistogramWriteResponseResult, 0);
-}
-
 TEST_F(ServiceWorkerNewScriptLoaderTest, Error_BadMimeType) {
   base::HistogramTester histogram_tester;
 
diff --git a/content/browser/service_worker/service_worker_registration_object_host.cc b/content/browser/service_worker/service_worker_registration_object_host.cc
index 22f99b4f..b6a87148 100644
--- a/content/browser/service_worker/service_worker_registration_object_host.cc
+++ b/content/browser/service_worker/service_worker_registration_object_host.cc
@@ -14,7 +14,7 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_host.h"
 #include "content/browser/service_worker/service_worker_object_host.h"
-#include "content/common/service_worker/service_worker_utils.h"
+#include "content/browser/service_worker/service_worker_security_utils.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/http/http_util.h"
@@ -476,7 +476,8 @@
   }
 
   std::vector<GURL> urls = {container_host_->url(), registration_->scope()};
-  if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(urls)) {
+  if (!service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          urls)) {
     receivers_.ReportBadMessage(
         ServiceWorkerConsts::kBadMessageImproperOrigins);
     return false;
diff --git a/content/browser/service_worker/service_worker_security_utils.cc b/content/browser/service_worker/service_worker_security_utils.cc
new file mode 100644
index 0000000..fa6bbc1d
--- /dev/null
+++ b/content/browser/service_worker/service_worker_security_utils.cc
@@ -0,0 +1,44 @@
+// 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 "content/browser/service_worker/service_worker_security_utils.h"
+
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/origin_util.h"
+
+namespace content {
+namespace service_worker_security_utils {
+
+bool AllOriginsMatchAndCanAccessServiceWorkers(const std::vector<GURL>& urls) {
+  // (A) Check if all origins can access service worker. Every URL must be
+  // checked despite the same-origin check below in (B), because GetOrigin()
+  // uses the inner URL for filesystem URLs so that https://foo/ and
+  // filesystem:https://foo/ are considered equal, but filesystem URLs cannot
+  // access service worker.
+  for (const GURL& url : urls) {
+    if (!OriginCanAccessServiceWorkers(url))
+      return false;
+  }
+
+  // (B) Check if all origins are equal. Cross-origin access is permitted when
+  // --disable-web-security is set.
+  if (IsWebSecurityDisabled()) {
+    return true;
+  }
+  const GURL& first = urls.front();
+  for (const GURL& url : urls) {
+    if (first.DeprecatedGetOriginAsURL() != url.DeprecatedGetOriginAsURL())
+      return false;
+  }
+  return true;
+}
+
+bool IsWebSecurityDisabled() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableWebSecurity);
+}
+
+}  // namespace service_worker_security_utils
+}  // namespace content
diff --git a/content/browser/service_worker/service_worker_security_utils.h b/content/browser/service_worker/service_worker_security_utils.h
new file mode 100644
index 0000000..d824f94
--- /dev/null
+++ b/content/browser/service_worker/service_worker_security_utils.h
@@ -0,0 +1,28 @@
+// 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SECURITY_UTILS_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SECURITY_UTILS_H_
+
+#include <vector>
+
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace service_worker_security_utils {
+
+// Returns true if all members of |urls| have the same origin, and
+// OriginCanAccessServiceWorkers is true for this origin.
+// If --disable-web-security is enabled, the same origin check is
+// not performed.
+CONTENT_EXPORT bool AllOriginsMatchAndCanAccessServiceWorkers(
+    const std::vector<GURL>& urls);
+
+CONTENT_EXPORT bool IsWebSecurityDisabled();
+
+}  // namespace service_worker_security_utils
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_SECURITY_UTILS_H_
diff --git a/content/browser/service_worker/service_worker_security_utils_unittest.cc b/content/browser/service_worker/service_worker_security_utils_unittest.cc
new file mode 100644
index 0000000..7db1b2b
--- /dev/null
+++ b/content/browser/service_worker/service_worker_security_utils_unittest.cc
@@ -0,0 +1,61 @@
+// 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 "content/browser/service_worker/service_worker_security_utils.h"
+
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+TEST(ServiceWorkerSecurityUtilsTest,
+     AllOriginsMatchAndCanAccessServiceWorkers) {
+  std::vector<GURL> https_same_origin = {GURL("https://example.com/1"),
+                                         GURL("https://example.com/2"),
+                                         GURL("https://example.com/3")};
+  EXPECT_TRUE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          https_same_origin));
+
+  std::vector<GURL> http_same_origin = {GURL("http://example.com/1"),
+                                        GURL("http://example.com/2")};
+  EXPECT_FALSE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          http_same_origin));
+
+  std::vector<GURL> localhost_same_origin = {GURL("http://localhost/1"),
+                                             GURL("http://localhost/2")};
+  EXPECT_TRUE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          localhost_same_origin));
+
+  std::vector<GURL> filesystem_same_origin = {
+      GURL("https://example.com/1"), GURL("https://example.com/2"),
+      GURL("filesystem:https://example.com/3")};
+  EXPECT_FALSE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          filesystem_same_origin));
+
+  std::vector<GURL> https_cross_origin = {GURL("https://example.com/1"),
+                                          GURL("https://example.org/2"),
+                                          GURL("https://example.com/3")};
+  EXPECT_FALSE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          https_cross_origin));
+
+  // Cross-origin access is permitted with --disable-web-security.
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  command_line->AppendSwitch(switches::kDisableWebSecurity);
+  EXPECT_TRUE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          https_cross_origin));
+
+  // Disallowed schemes are not permitted even with --disable-web-security.
+  EXPECT_FALSE(
+      service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
+          filesystem_same_origin));
+}
+
+}  // namespace content
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 0c196d00..95ed36f 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -38,8 +38,8 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_host.h"
 #include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
+#include "content/browser/service_worker/service_worker_security_utils.h"
 #include "content/common/content_navigation_policy.h"
-#include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/page_navigator.h"
@@ -2349,7 +2349,7 @@
   // Check that the worker is allowed on this origin. It's possible a
   // worker was previously allowed and installed, but later the embedder's
   // policy or binary changed to disallow this origin.
-  if (!ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
+  if (!service_worker_security_utils::AllOriginsMatchAndCanAccessServiceWorkers(
           {script_url_})) {
     return false;
   }
diff --git a/content/browser/tracing/memory_instrumentation_browsertest.cc b/content/browser/tracing/memory_instrumentation_browsertest.cc
index 5f1b006..3bd89ff 100644
--- a/content/browser/tracing/memory_instrumentation_browsertest.cc
+++ b/content/browser/tracing/memory_instrumentation_browsertest.cc
@@ -4,7 +4,10 @@
 
 #include <stdint.h>
 
+#include <algorithm>
+
 #include "base/bind.h"
+#include "base/process/process_handle.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "content/public/browser/render_frame_host.h"
@@ -40,40 +43,31 @@
   }
 };
 
-uint64_t GetPrivateFootprintKb(ProcessType type,
-                               const GlobalMemoryDump& global_dump,
-                               base::ProcessId pid = base::kNullProcessId) {
-  const GlobalMemoryDump::ProcessDump* target_dump = nullptr;
-  for (const auto& dump : global_dump.process_dumps()) {
-    if (dump.process_type() != type)
-      continue;
-
-    if (pid != base::kNullProcessId && pid != dump.pid())
-      continue;
-
-    EXPECT_FALSE(target_dump);
-    target_dump = &dump;
-  }
-  EXPECT_TRUE(target_dump);
-  return target_dump->os_dump().private_footprint_kb;
-}
-
-std::unique_ptr<GlobalMemoryDump> DoGlobalDump() {
-  std::unique_ptr<GlobalMemoryDump> result;
+uint64_t GetPrivateFootprintKb() {
+  uint64_t private_footprint_kb = 0;
   base::RunLoop run_loop;
   memory_instrumentation::MemoryInstrumentation::GetInstance()
-      ->RequestGlobalDump(
-          {}, base::BindOnce(
-                  [](base::OnceClosure quit_closure,
-                     std::unique_ptr<GlobalMemoryDump>* out_result,
-                     bool success, std::unique_ptr<GlobalMemoryDump> result) {
-                    EXPECT_TRUE(success);
-                    *out_result = std::move(result);
-                    std::move(quit_closure).Run();
-                  },
-                  run_loop.QuitClosure(), &result));
+      ->RequestPrivateMemoryFootprint(
+          base::GetCurrentProcId(),
+          base::BindOnce(
+              [](base::OnceClosure quit_closure, uint64_t* private_footprint_kb,
+                 bool success, std::unique_ptr<GlobalMemoryDump> result) {
+                // The global dump should only contain the current process
+                // (browser).
+                EXPECT_TRUE(success);
+                ASSERT_EQ(std::distance(result->process_dumps().begin(),
+                                        result->process_dumps().end()),
+                          1);
+                const auto& process_dump = *result->process_dumps().begin();
+                ASSERT_EQ(ProcessType::BROWSER, process_dump.process_type());
+
+                *private_footprint_kb =
+                    process_dump.os_dump().private_footprint_kb;
+                std::move(quit_closure).Run();
+              },
+              run_loop.QuitClosure(), &private_footprint_kb));
   run_loop.Run();
-  return result;
+  return private_footprint_kb;
 }
 
 // *SAN fake some sys calls we need meaning we never get dumps for the
@@ -114,14 +108,14 @@
   const int64_t kAllocSize = 65 * 1024 * 1024;
   const int64_t kAllocSizeKb = kAllocSize / 1024;
 
-  std::unique_ptr<GlobalMemoryDump> before_ptr = DoGlobalDump();
+  int64_t before_kb = GetPrivateFootprintKb();
 
   std::unique_ptr<char[]> buffer = std::make_unique<char[]>(kAllocSize);
   memset(buffer.get(), 1, kAllocSize);
   volatile char* x = static_cast<volatile char*>(buffer.get());
   EXPECT_EQ(x[0] + x[kAllocSize - 1], 2);
 
-  std::unique_ptr<GlobalMemoryDump> during_ptr = DoGlobalDump();
+  int64_t during_kb = GetPrivateFootprintKb();
 
   buffer.reset();
 
@@ -130,11 +124,7 @@
     mallopt(M_PURGE, 0);
 #endif
 
-  std::unique_ptr<GlobalMemoryDump> after_ptr = DoGlobalDump();
-
-  int64_t before_kb = GetPrivateFootprintKb(ProcessType::BROWSER, *before_ptr);
-  int64_t during_kb = GetPrivateFootprintKb(ProcessType::BROWSER, *during_ptr);
-  int64_t after_kb = GetPrivateFootprintKb(ProcessType::BROWSER, *after_ptr);
+  int64_t after_kb = GetPrivateFootprintKb();
 
   EXPECT_THAT(after_kb - before_kb,
               AllOf(Ge(-kAllocSizeKb / 10), Le(kAllocSizeKb / 10)));
diff --git a/content/browser/webrtc/resources/webrtc_internals.js b/content/browser/webrtc/resources/webrtc_internals.js
index 2b3951e8..157ca48 100644
--- a/content/browser/webrtc/resources/webrtc_internals.js
+++ b/content/browser/webrtc/resources/webrtc_internals.js
@@ -122,6 +122,7 @@
   addWebUIListener('add-standard-stats', addStandardStats);
   addWebUIListener('add-legacy-stats', addLegacyStats);
   addWebUIListener('add-get-user-media', addGetUserMedia);
+  addWebUIListener('update-get-user-media', updateGetUserMedia);
   addWebUIListener(
       'remove-get-user-media-for-renderer', removeGetUserMediaForRenderer);
   addWebUIListener(
@@ -548,7 +549,6 @@
   }
 }
 
-
 /**
  * Adds a getUserMedia request.
  *
@@ -564,25 +564,66 @@
 
   const requestDiv = document.createElement('div');
   requestDiv.className = 'user-media-request-div-class';
+  requestDiv.id = ['gum', data.rid, data.pid, data.request_id].join('-');
   requestDiv.rid = data.rid;
   $(USER_MEDIA_TAB_ID).appendChild(requestDiv);
 
   appendChildWithText(requestDiv, 'div', 'Caller origin: ' + data.origin);
   appendChildWithText(requestDiv, 'div', 'Caller process id: ' + data.pid);
-  appendChildWithText(requestDiv, 'div', 'Time: ' + (new Date(data.timestamp)));
+  const el = appendChildWithText(requestDiv, 'span', 'getUserMedia call');
+  el.style.fontWeight = 'bold';
+  appendChildWithText(el, 'div', 'Time: ' +
+    (new Date(data.timestamp).toTimeString()))
+    .style.fontWeight = 'normal';
   if (data.audio !== undefined) {
-    appendChildWithText(requestDiv, 'span', 'Audio Constraints')
-        .style.fontWeight = 'bold';
-    appendChildWithText(requestDiv, 'div', data.audio || "true");
+    appendChildWithText(el, 'div', 'Audio constraints: ' +
+      (data.audio || 'true'))
+      .style.fontWeight = 'normal';
   }
-
   if (data.video !== undefined) {
-    appendChildWithText(requestDiv, 'span', 'Video Constraints')
-        .style.fontWeight = 'bold';
-    appendChildWithText(requestDiv, 'div', data.video || "true");
+    appendChildWithText(el, 'div', 'Video constraints: ' +
+      (data.video || 'true'))
+      .style.fontWeight = 'normal';
   }
 }
 
+/**
+ * Update a getUserMedia request.
+ *
+ * @param {!Object} data The object containing rid {number}, pid {number},
+ *     request_id {number}, stream_id {string},
+ *     audio_track_info {string} and video_track_info {string}
+ */
+function updateGetUserMedia(data) {
+  userMediaRequests.push(data);
+
+  if (!$(USER_MEDIA_TAB_ID)) {
+    tabView.addTab(USER_MEDIA_TAB_ID, 'GetUserMedia Requests');
+  }
+
+  const requestDiv = document.getElementById(
+    ['gum', data.rid, data.pid, data.request_id].join('-'));
+  if (!requestDiv) {
+    console.error('Could not update getUserMedia request', data);
+    return;
+  }
+
+  const el = appendChildWithText(requestDiv, 'span', 'getUserMedia result');
+  el.style.fontWeight = 'bold';
+  appendChildWithText(el, 'div', 'Time: ' +
+    (new Date(data.timestamp).toTimeString()))
+    .style.fontWeight = 'normal';
+  appendChildWithText(el, 'div', 'Stream id: ' + data.stream_id)
+    .style.fontWeight = 'normal';
+  if (data.audio_track_info) {
+    appendChildWithText(el, 'div', 'Audio track: ' + data.audio_track_info)
+        .style.fontWeight = 'normal';
+  }
+  if (data.video_track_info) {
+    appendChildWithText(el, 'div', 'Video track: ' + data.video_track_info)
+        .style.fontWeight = 'normal';
+  }
+}
 
 /**
  * Removes the getUserMedia requests from the specified |rid|.
diff --git a/content/browser/webrtc/webrtc_internals.cc b/content/browser/webrtc/webrtc_internals.cc
index 2551e64d..9beee80 100644
--- a/content/browser/webrtc/webrtc_internals.cc
+++ b/content/browser/webrtc/webrtc_internals.cc
@@ -320,6 +320,43 @@
       host->AddObserver(this);
   }
 }
+void WebRTCInternals::OnGetUserMediaSuccess(
+    GlobalRenderFrameHostId frame_id,
+    base::ProcessId pid,
+    int request_id,
+    const std::string& stream_id,
+    const std::string& audio_track_info,
+    const std::string& video_track_info) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  if (get_user_media_requests_.GetList().size() >= kMaxGetUserMediaEntries) {
+    LOG(WARNING) << "Maximum number of tracked getUserMedia() requests reached "
+                    "in webrtc-internals.";
+    return;
+  }
+
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetIntKey("rid", frame_id.child_id);
+  dict.SetIntKey("pid", static_cast<int>(pid));
+  dict.SetIntKey("request_id", request_id);
+  dict.SetDoubleKey("timestamp", base::Time::Now().ToJsTime());
+  dict.SetStringKey("stream_id", stream_id);
+  if (!audio_track_info.empty())
+    dict.SetStringKey("audio_track_info", audio_track_info);
+  if (!video_track_info.empty())
+    dict.SetStringKey("video_track_info", video_track_info);
+
+  if (!observers_.empty())
+    SendUpdate("update-get-user-media", dict.Clone());
+
+  get_user_media_requests_.Append(std::move(dict));
+
+  if (render_process_id_set_.insert(frame_id.child_id).second) {
+    RenderProcessHost* host = RenderProcessHost::FromID(frame_id.child_id);
+    if (host)
+      host->AddObserver(this);
+  }
+}
 
 void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -360,7 +397,12 @@
     observer->OnUpdate("update-all-peer-connections", &peer_connection_data_);
 
   for (const auto& request : get_user_media_requests_.GetList()) {
-    observer->OnUpdate("add-get-user-media", &request);
+    // If there is a stream_id key this is an update.
+    if (request.FindStringKey("stream_id")) {
+      observer->OnUpdate("update-get-user-media", &request);
+    } else {
+      observer->OnUpdate("add-get-user-media", &request);
+    }
   }
 }
 
diff --git a/content/browser/webrtc/webrtc_internals.h b/content/browser/webrtc/webrtc_internals.h
index 130b3e5..ca58ced 100644
--- a/content/browser/webrtc/webrtc_internals.h
+++ b/content/browser/webrtc/webrtc_internals.h
@@ -84,6 +84,12 @@
                       bool video,
                       const std::string& audio_constraints,
                       const std::string& video_constraints) override;
+  void OnGetUserMediaSuccess(GlobalRenderFrameHostId frame_id,
+                             base::ProcessId pid,
+                             int request_id,
+                             const std::string& stream_id,
+                             const std::string& audio_track_info,
+                             const std::string& video_track_info) override;
 
   // Methods for adding or removing WebRTCInternalsUIObserver.
   void AddObserver(WebRTCInternalsUIObserver* observer);
@@ -202,13 +208,18 @@
   // are strings representing the event.
   base::ListValue peer_connection_data_;
 
-  // A list of getUserMedia requests. Each item is a DictionaryValue that
-  // contains these fields:
+  // A list of getUserMedia requests or updates.
+  // Each item is a DictionaryValue that contains some of these fields
+  // depending on the type:
   // "rid" -- the renderer id.
-  // "pid" -- proceddId of the renderer.
+  // "pid" -- OS process id of the renderer that creates the PeerConnection.
   // "origin" -- the security origin of the request.
   // "audio" -- the serialized audio constraints if audio is requested.
   // "video" -- the serialized video constraints if video is requested.
+  // "timestamp" -- time of the request
+  // "stream_id" -- the resulting stream id.
+  // "audio_track_info" -- the serialized audio track (track id and label).
+  // "video_track_info" -- the serialized video track (track id and label).
   base::ListValue get_user_media_requests_;
 
   // For managing select file dialog.
diff --git a/content/browser/webrtc/webrtc_internals_unittest.cc b/content/browser/webrtc/webrtc_internals_unittest.cc
index bb42c72..61f47c9 100644
--- a/content/browser/webrtc/webrtc_internals_unittest.cc
+++ b/content/browser/webrtc/webrtc_internals_unittest.cc
@@ -37,6 +37,10 @@
 const char kAudioConstraint[] = "aaa";
 const char kVideoConstraint[] = "vvv";
 
+const char kStreamId[] = "streamid";
+const char kAudioTrackInfo[] = "id:audio label:fancy device";
+const char kVideoTrackInfo[] = "id:audio label:fancy device";
+
 class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver {
  public:
   MockWebRtcInternalsProxy() = default;
@@ -171,6 +175,25 @@
     VerifyString(dict, "video", video);
   }
 
+  void VerifyGetUserMediaSuccessData(base::Value* actual_data,
+                                     GlobalRenderFrameHostId frame_id,
+                                     int pid,
+                                     int request_id,
+                                     const std::string& stream_id,
+                                     const std::string& audio_track_info,
+                                     const std::string& video_track_info) {
+    ASSERT_TRUE(actual_data->is_dict());
+    const base::DictionaryValue& dict =
+        base::Value::AsDictionaryValue(*actual_data);
+
+    VerifyInt(dict, "rid", frame_id.child_id);
+    VerifyInt(dict, "pid", pid);
+    VerifyInt(dict, "request_id", request_id);
+    VerifyString(dict, "stream_id", stream_id);
+    VerifyString(dict, "audio_track_info", audio_track_info);
+    VerifyString(dict, "video_track_info", video_track_info);
+  }
+
   BrowserTaskEnvironment task_environment_;
 };
 
@@ -371,6 +394,29 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(WebRtcInternalsTest, UpdateGetUserMedia) {
+  base::RunLoop loop;
+  MockWebRtcInternalsProxy observer(&loop);
+  WebRTCInternalsForTest webrtc_internals;
+
+  // Add one observer before "getUserMediaSuccess".
+  webrtc_internals.AddObserver(&observer);
+
+  webrtc_internals.OnGetUserMediaSuccess(kFrameId, kPid, kRequestId, kStreamId,
+                                         kAudioTrackInfo, kVideoTrackInfo);
+
+  loop.Run();
+
+  ASSERT_EQ("update-get-user-media", observer.event_name());
+  VerifyGetUserMediaSuccessData(observer.event_data(), kFrameId, kPid,
+                                kRequestId, kStreamId, kAudioTrackInfo,
+                                kVideoTrackInfo);
+
+  webrtc_internals.RemoveObserver(&observer);
+
+  base::RunLoop().RunUntilIdle();
+}
+
 TEST_F(WebRtcInternalsTest, SendAllUpdateWithGetUserMedia) {
   WebRTCInternalsForTest webrtc_internals;
   webrtc_internals.OnGetUserMedia(kFrameId, kPid, kUrl, kRequestId, true, true,
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 7927350..cc6e56f 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -294,6 +294,8 @@
     {wf::EnableSkipTouchEventFilter, blink::features::kSkipTouchEventFilter},
     {wf::EnableSubresourceWebBundles, features::kSubresourceWebBundles},
     {wf::EnableTextFragmentAnchor, blink::features::kTextFragmentAnchor},
+    {wf::EnableCSSSelectorFragmentAnchor,
+     blink::features::kCssSelectorFragmentAnchor},
     {wf::EnableBackfaceVisibilityInterop,
      blink::features::kBackfaceVisibilityInterop},
     {wf::EnableUserActivationSameOriginVisibility,
@@ -406,6 +408,10 @@
            blink::features::kAutoExpandDetailsElement},
           {"UserAgentClientHintFullVersionList",
            blink::features::kUserAgentClientHintFullVersionList},
+          {"ClientHintsMetaHTTPEquivAcceptCH",
+           blink::features::kClientHintsMetaHTTPEquivAcceptCH},
+          {"ClientHintsMetaNameAcceptCH",
+           blink::features::kClientHintsMetaNameAcceptCH},
       };
   for (const auto& mapping : runtimeFeatureNameToChromiumFeatureMapping) {
     SetRuntimeFeatureFromChromiumFeature(
diff --git a/content/common/media/cdm_info.cc b/content/common/media/cdm_info.cc
index f41ae67..8831601 100644
--- a/content/common/media/cdm_info.cc
+++ b/content/common/media/cdm_info.cc
@@ -13,7 +13,7 @@
                  absl::optional<media::CdmCapability> capability,
                  bool supports_sub_key_systems,
                  const std::string& name,
-                 const base::Token& guid,
+                 const base::Token& type,
                  const base::Version& version,
                  const base::FilePath& path,
                  const std::string& file_system_id)
@@ -22,7 +22,7 @@
       capability(std::move(capability)),
       supports_sub_key_systems(supports_sub_key_systems),
       name(name),
-      guid(guid),
+      type(type),
       version(version),
       path(path),
       file_system_id(file_system_id) {
diff --git a/content/common/profiling_utils.cc b/content/common/profiling_utils.cc
index fb1ec4b..cd2916f 100644
--- a/content/common/profiling_utils.cc
+++ b/content/common/profiling_utils.cc
@@ -9,8 +9,7 @@
 #include <string>
 
 #include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/clang_profiling_buildflags.h"
+#include "base/command_line.h"
 #include "base/environment.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
@@ -19,13 +18,9 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/rand_util.h"
-#include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task/task_traits.h"
-#include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 
@@ -95,47 +90,5 @@
 
   return file;
 }
-WaitForProcessesToDumpProfilingInfo::WaitForProcessesToDumpProfilingInfo() =
-    default;
-WaitForProcessesToDumpProfilingInfo::~WaitForProcessesToDumpProfilingInfo() =
-    default;
-
-void WaitForProcessesToDumpProfilingInfo::WaitForAll() {
-  base::RunLoop nested_run_loop(base::RunLoop::Type::kNestableTasksAllowed);
-
-  // Some of the waitable events will be signaled on the main thread, use a
-  // nested run loop to ensure we're not preventing them from signaling.
-  base::ThreadPool::PostTask(
-      FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-      base::BindOnce(
-          &WaitForProcessesToDumpProfilingInfo::WaitForAllOnThreadPool,
-          base::Unretained(this), nested_run_loop.QuitClosure()));
-  nested_run_loop.Run();
-}
-
-void WaitForProcessesToDumpProfilingInfo::WaitForAllOnThreadPool(
-    base::OnceClosure quit_closure) {
-  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_blocking;
-
-  std::vector<base::WaitableEvent*> events_raw;
-  events_raw.reserve(events_.size());
-  for (const auto& iter : events_)
-    events_raw.push_back(iter.get());
-
-  // Wait for all the events to be signaled.
-  while (events_raw.size()) {
-    size_t index =
-        base::WaitableEvent::WaitMany(events_raw.data(), events_raw.size());
-    events_raw.erase(events_raw.begin() + index);
-  }
-
-  std::move(quit_closure).Run();
-}
-
-base::WaitableEvent*
-WaitForProcessesToDumpProfilingInfo::GetNewWaitableEvent() {
-  events_.push_back(std::make_unique<base::WaitableEvent>());
-  return events_.back().get();
-}
 
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc
index 280e471..8c90002 100644
--- a/content/common/service_worker/service_worker_utils.cc
+++ b/content/common/service_worker/service_worker_utils.cc
@@ -5,14 +5,9 @@
 #include "content/common/service_worker/service_worker_utils.h"
 
 #include "base/check.h"
-#include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/notreached.h"
-#include "base/numerics/safe_math.h"
 #include "base/strings/string_util.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/origin_util.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_byte_range.h"
 #include "services/network/public/cpp/features.h"
@@ -73,32 +68,6 @@
 }
 
 // static
-bool ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-    const std::vector<GURL>& urls) {
-  // (A) Check if all origins can access service worker. Every URL must be
-  // checked despite the same-origin check below in (B), because GetOrigin()
-  // uses the inner URL for filesystem URLs so that https://foo/ and
-  // filesystem:https://foo/ are considered equal, but filesystem URLs cannot
-  // access service worker.
-  for (const GURL& url : urls) {
-    if (!OriginCanAccessServiceWorkers(url))
-      return false;
-  }
-
-  // (B) Check if all origins are equal. Cross-origin access is permitted when
-  // --disable-web-security is set.
-  if (IsWebSecurityDisabled()) {
-    return true;
-  }
-  const GURL& first = urls.front();
-  for (const GURL& url : urls) {
-    if (first.DeprecatedGetOriginAsURL() != url.DeprecatedGetOriginAsURL())
-      return false;
-  }
-  return true;
-}
-
-// static
 blink::mojom::FetchCacheMode ServiceWorkerUtils::GetCacheModeFromLoadFlags(
     int load_flags) {
   if (load_flags & net::LOAD_DISABLE_CACHE)
@@ -145,10 +114,4 @@
   return ".Unknown";
 }
 
-// static
-bool ServiceWorkerUtils::IsWebSecurityDisabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kDisableWebSecurity);
-}
-
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_utils.h b/content/common/service_worker/service_worker_utils.h
index 4c217bd0..437a8e0 100644
--- a/content/common/service_worker/service_worker_utils.h
+++ b/content/common/service_worker/service_worker_utils.h
@@ -7,9 +7,7 @@
 
 #include <sstream>
 #include <string>
-#include <vector>
 
-#include "base/command_line.h"
 #include "content/common/content_export.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
@@ -28,13 +26,6 @@
                                           const GURL& script_url,
                                           std::string* error_message);
 
-  // Returns true if all members of |urls| have the same origin, and
-  // OriginCanAccessServiceWorkers is true for this origin.
-  // If --disable-web-security is enabled, the same origin check is
-  // not performed.
-  CONTENT_EXPORT static bool AllOriginsMatchAndCanAccessServiceWorkers(
-      const std::vector<GURL>& urls);
-
   template <typename T>
   static std::string MojoEnumToString(T mojo_enum) {
     std::ostringstream oss;
@@ -50,8 +41,6 @@
   CONTENT_EXPORT static const char* FetchResponseSourceToSuffix(
       network::mojom::FetchResponseSource source);
 
-  CONTENT_EXPORT static bool IsWebSecurityDisabled();
-
  private:
   static bool IsPathRestrictionSatisfiedInternal(
       const GURL& scope,
diff --git a/content/common/service_worker/service_worker_utils_unittest.cc b/content/common/service_worker/service_worker_utils_unittest.cc
index 5f72cbe..b48a4ec 100644
--- a/content/common/service_worker/service_worker_utils_unittest.cc
+++ b/content/common/service_worker/service_worker_utils_unittest.cc
@@ -4,8 +4,6 @@
 
 #include "content/common/service_worker/service_worker_utils.h"
 
-#include "base/command_line.h"
-#include "content/public/common/content_switches.h"
 #include "net/base/load_flags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -13,46 +11,6 @@
 
 namespace content {
 
-TEST(ServiceWorkerUtilsTest, AllOriginsMatchAndCanAccessServiceWorkers) {
-  std::vector<GURL> https_same_origin = {GURL("https://example.com/1"),
-                                         GURL("https://example.com/2"),
-                                         GURL("https://example.com/3")};
-  EXPECT_TRUE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      https_same_origin));
-
-  std::vector<GURL> http_same_origin = {GURL("http://example.com/1"),
-                                        GURL("http://example.com/2")};
-  EXPECT_FALSE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      http_same_origin));
-
-  std::vector<GURL> localhost_same_origin = {GURL("http://localhost/1"),
-                                             GURL("http://localhost/2")};
-  EXPECT_TRUE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      localhost_same_origin));
-
-  std::vector<GURL> filesystem_same_origin = {
-      GURL("https://example.com/1"), GURL("https://example.com/2"),
-      GURL("filesystem:https://example.com/3")};
-  EXPECT_FALSE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      filesystem_same_origin));
-
-  std::vector<GURL> https_cross_origin = {GURL("https://example.com/1"),
-                                          GURL("https://example.org/2"),
-                                          GURL("https://example.com/3")};
-  EXPECT_FALSE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      https_cross_origin));
-
-  // Cross-origin access is permitted with --disable-web-security.
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  command_line->AppendSwitch(switches::kDisableWebSecurity);
-  EXPECT_TRUE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      https_cross_origin));
-
-  // Disallowed schemes are not permitted even with --disable-web-security.
-  EXPECT_FALSE(ServiceWorkerUtils::AllOriginsMatchAndCanAccessServiceWorkers(
-      filesystem_same_origin));
-}
-
 TEST(ServiceWorkerFetchRequestTest, CacheModeTest) {
   EXPECT_EQ(FetchCacheMode::kDefault,
             ServiceWorkerUtils::GetCacheModeFromLoadFlags(0));
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
index be97c4d..2b82a63 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -174,7 +174,7 @@
     private boolean mUserHasTouchExplored;
     private boolean mPendingScrollToMakeNodeVisible;
     private boolean mNotifyFrameInfoInitializedCalled;
-    private boolean mAccessibilityEnabledForTesting;
+    private boolean mAccessibilityEnabledOverride;
     private int mSelectionGranularity;
     private int mAccessibilityFocusId;
     private int mSelectionNodeId;
@@ -396,7 +396,7 @@
     @VisibleForTesting
     @Override
     public void setAccessibilityEnabledForTesting() {
-        mAccessibilityEnabledForTesting = true;
+        mAccessibilityEnabledOverride = true;
     }
 
     @VisibleForTesting
@@ -583,6 +583,17 @@
     }
 
     @CalledByNative
+    public String generateAccessibilityNodeInfoString(int virtualViewId) {
+        // If accessibility isn't enabled, all the AccessibilityNodeInfo objects will be null, so
+        // temporarily set the |mAccessibilityEnabledOverride| flag to true, then disable it.
+        mAccessibilityEnabledOverride = true;
+        String returnString =
+                AccessibilityNodeInfoUtils.toString(createAccessibilityNodeInfo(virtualViewId));
+        mAccessibilityEnabledOverride = false;
+        return returnString;
+    }
+
+    @CalledByNative
     public void clearNodeInfoCacheForGivenId(int virtualViewId) {
         // Recycle and remove the element in our cache for this |virtualViewId|.
         if (mNodeInfoCache.get(virtualViewId) != null) {
@@ -1404,7 +1415,7 @@
     @Override
     public boolean isAccessibilityEnabled() {
         return isNativeInitialized()
-                && (mAccessibilityEnabledForTesting || mAccessibilityManager.isEnabled());
+                && (mAccessibilityEnabledOverride || mAccessibilityManager.isEnabled());
     }
 
     private AccessibilityNodeInfo createNodeForHost(int rootId) {
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index be69ecf..6ef4f1c8 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -601,6 +601,10 @@
       "//device/vr/public/mojom:isolated_xr_service",
     ]
   }
+
+  if (use_clang_profiling_inside_sandbox) {
+    sources += [ "profiling_utils.h" ]
+  }
 }
 
 if (is_android) {
diff --git a/content/public/browser/ax_inspect_factory_android.cc b/content/public/browser/ax_inspect_factory_android.cc
index 9b76eec..4522aea 100644
--- a/content/public/browser/ax_inspect_factory_android.cc
+++ b/content/public/browser/ax_inspect_factory_android.cc
@@ -7,6 +7,7 @@
 #include "base/notreached.h"
 #include "content/browser/accessibility/accessibility_event_recorder.h"
 #include "content/browser/accessibility/accessibility_tree_formatter_android.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_android_external.h"
 #include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
 
 namespace content {
@@ -14,7 +15,11 @@
 // static
 std::unique_ptr<ui::AXTreeFormatter>
 AXInspectFactory::CreatePlatformFormatter() {
-  return AXInspectFactory::CreateFormatter(ui::AXApiType::kAndroid);
+  // The default platform tree formatter for Android uses the "external" tree,
+  // i.e. pulling from the AccessibilityNodeInfo objects in the Java-side code.
+  // If the internal tree is desired, then CreateFormatter() should be called
+  // with the appropriate tree type.
+  return AXInspectFactory::CreateFormatter(ui::AXApiType::kAndroidExternal);
 }
 
 // static
@@ -32,6 +37,8 @@
   switch (type) {
     case ui::AXApiType::kAndroid:
       return std::make_unique<AccessibilityTreeFormatterAndroid>();
+    case ui::AXApiType::kAndroidExternal:
+      return std::make_unique<AccessibilityTreeFormatterAndroidExternal>();
     case ui::AXApiType::kBlink:
       return std::make_unique<AccessibilityTreeFormatterBlink>();
     default:
diff --git a/content/public/browser/document_service.h b/content/public/browser/document_service.h
index f9a2d83..c4c4e08 100644
--- a/content/public/browser/document_service.h
+++ b/content/public/browser/document_service.h
@@ -75,6 +75,8 @@
     return render_frame_host()->GetLastCommittedOrigin();
   }
 
+  mojo::Receiver<Interface>* receiver() { return &receiver_; }
+
   // Returns the RenderFrameHost tracked by this object. Guaranteed to never be
   // null.
   using DocumentServiceBase::render_frame_host;
diff --git a/content/public/browser/peer_connection_tracker_host_observer.h b/content/public/browser/peer_connection_tracker_host_observer.h
index 7559c7a..8c7e791a 100644
--- a/content/public/browser/peer_connection_tracker_host_observer.h
+++ b/content/public/browser/peer_connection_tracker_host_observer.h
@@ -113,6 +113,21 @@
                               const std::string& audio_constraints,
                               const std::string& video_constraints) {}
 
+  // This method is called when getUserMedia resolves with a stream.
+  // - |render_frame_host_id| identifies the RenderFrameHost.
+  // - |pid| is the OS process ID.
+  // - |request_id| is the internal getUserMedia request id.
+  // - |stream_id| is the id of the stream containing the tracks.
+  // - |audio_track_info| describes the streams audio track (if any).
+  // - |video_track_info| describes the streams video track (if any).
+  virtual void OnGetUserMediaSuccess(
+      GlobalRenderFrameHostId render_frame_host_id,
+      base::ProcessId pid,
+      int request_id,
+      const std::string& stream_id,
+      const std::string& audio_track_info,
+      const std::string& video_track_info) {}
+
  protected:
   PeerConnectionTrackerHostObserver();
 };
diff --git a/content/public/browser/profiling_utils.h b/content/public/browser/profiling_utils.h
new file mode 100644
index 0000000..06a8f297
--- /dev/null
+++ b/content/public/browser/profiling_utils.h
@@ -0,0 +1,18 @@
+// 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 CONTENT_PUBLIC_BROWSER_PROFILING_UTILS_H_
+#define CONTENT_PUBLIC_BROWSER_PROFILING_UTILS_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Ask all the child processes to dump their profiling data to disk and block
+// until this is done.
+CONTENT_EXPORT void WaitForAllChildrenToDumpProfilingData();
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_PROFILING_UTILS_H_
diff --git a/content/public/common/cdm_info.h b/content/public/common/cdm_info.h
index 95f9bc00..2760fa5 100644
--- a/content/public/common/cdm_info.h
+++ b/content/public/common/cdm_info.h
@@ -32,10 +32,11 @@
           absl::optional<media::CdmCapability> capability,
           bool supports_sub_key_systems,
           const std::string& name,
-          const base::Token& guid,
+          const base::Token& type,
           const base::Version& version,
           const base::FilePath& path,
           const std::string& file_system_id);
+  // TODO(xhwang): Always require the `type`.
   CdmInfo(const std::string& key_system,
           Robustness robustness,
           absl::optional<media::CdmCapability> capability);
@@ -66,8 +67,10 @@
   // Display name of the CDM (e.g. Widevine Content Decryption Module).
   std::string name;
 
-  // A token to uniquely identify this type of CDM.
-  base::Token guid;
+  // A token to uniquely identify the type of the CDM. Used for per-CDM-type
+  // isolation, e.g. for running different CDMs in different child processes,
+  // and per-CDM-type storage.
+  base::Token type;
 
   // Version of the CDM. May be empty if the version is not known.
   base::Version version;
diff --git a/content/public/common/content_switch_dependent_feature_overrides.cc b/content/public/common/content_switch_dependent_feature_overrides.cc
index 04a47c2..c76dba9 100644
--- a/content/public/common/content_switch_dependent_feature_overrides.cc
+++ b/content/public/common/content_switch_dependent_feature_overrides.cc
@@ -90,6 +90,12 @@
       {switches::kEnableExperimentalWebPlatformFeatures,
        std::cref(blink::features::kUserAgentClientHintFullVersionList),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {switches::kEnableExperimentalWebPlatformFeatures,
+       std::cref(blink::features::kClientHintsMetaHTTPEquivAcceptCH),
+       base::FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {switches::kEnableExperimentalWebPlatformFeatures,
+       std::cref(blink::features::kClientHintsMetaNameAcceptCH),
+       base::FeatureList::OVERRIDE_ENABLE_FEATURE},
 
       // Overrides for --enable-experimental-cookie-features.
       {switches::kEnableExperimentalCookieFeatures,
diff --git a/content/public/common/profiling_utils.h b/content/public/common/profiling_utils.h
index 113c6c5..4db5429 100644
--- a/content/public/common/profiling_utils.h
+++ b/content/public/common/profiling_utils.h
@@ -5,11 +5,7 @@
 #ifndef CONTENT_PUBLIC_COMMON_PROFILING_UTILS_H_
 #define CONTENT_PUBLIC_COMMON_PROFILING_UTILS_H_
 
-#include <vector>
-
-#include "base/callback_forward.h"
 #include "base/files/file.h"
-#include "base/synchronization/waitable_event.h"
 #include "content/common/content_export.h"
 
 namespace content {
@@ -18,34 +14,6 @@
 // data.
 CONTENT_EXPORT base::File OpenProfilingFile();
 
-// Serves WaitableEvent that should be used by the child processes to signal
-// that they have finished dumping the profiling data.
-class CONTENT_EXPORT WaitForProcessesToDumpProfilingInfo {
- public:
-  WaitForProcessesToDumpProfilingInfo();
-  ~WaitForProcessesToDumpProfilingInfo();
-  WaitForProcessesToDumpProfilingInfo(
-      const WaitForProcessesToDumpProfilingInfo& other) = delete;
-  WaitForProcessesToDumpProfilingInfo& operator=(
-      const WaitForProcessesToDumpProfilingInfo&) = delete;
-
-  // Wait for all the events served by |GetNewWaitableEvent| to signal.
-  void WaitForAll();
-
-  // Return a new waitable event. Calling |WaitForAll| will wait for this event
-  // to be signaled.
-  // The returned WaitableEvent is owned by this
-  // WaitForProcessesToDumpProfilingInfo instance.
-  base::WaitableEvent* GetNewWaitableEvent();
-
- private:
-  // Implementation of WaitForAll that will run on the thread pool. This will
-  // run |quit_closure| once it's done waiting.
-  void WaitForAllOnThreadPool(base::OnceClosure quit_closure);
-
-  std::vector<std::unique_ptr<base::WaitableEvent>> events_;
-};
-
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_COMMON_PROFILING_UTILS_H_
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index aa30679..82a89fe 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1558,7 +1558,6 @@
       "//ppapi/tests/test_page.css",
       "//ppapi/tests/test_url_loader_data/",
       "//third_party/pywebsocket3/src/mod_pywebsocket/",
-      "//third_party/tlslite/",
     ]
   }
 
diff --git a/content/web_test/renderer/gc_controller.cc b/content/web_test/renderer/gc_controller.cc
index 4082354..811a85d 100644
--- a/content/web_test/renderer/gc_controller.cc
+++ b/content/web_test/renderer/gc_controller.cc
@@ -89,7 +89,8 @@
   v8::Isolate* const isolate = blink::MainThreadIsolate();
 
   for (int i = 0; i < kNumberOfGCsForFullCollection; i++) {
-    isolate->GetEmbedderHeapTracer()->GarbageCollectionForTesting(
+    isolate->RequestGarbageCollectionForTesting(
+        v8::Isolate::kFullGarbageCollection,
         v8::EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers);
   }
 
diff --git a/docs/chrome_untrusted.md b/docs/chrome_untrusted.md
index 9dafab1e..04658f19 100644
--- a/docs/chrome_untrusted.md
+++ b/docs/chrome_untrusted.md
@@ -57,9 +57,23 @@
 
 Any team that requires extra capabilities granted to `chrome-untrusted://` should consult with the security team to ensure they are non-dangerous. In this context, we consider non-dangerous any API that we would expose to the renderer process, e.g. UMA.
 
-We currently use `postMessage()` to expose certain APIs to `chrome-untrusted://`. For example, the Media App uses `postMessage()` to pass a read-only file handle to `chrome-untrusted://media-app` from `chrome-untrusted://`. Teams are encouraged to get a review from someone in [SECURITY_OWNERS](https://source.chromium.org/chromium/chromium/src/+/main:ipc/SECURITY_OWNERS) when exposing capabilities over postMessage.
+We recommend using Mojo to expose APIs to `chrome-untrusted://`. Mojo for `chrome-untrusted://` works similarly to how it works for `chrome://` with a few key differences:
 
-We are hoping to move to Mojo to improve auditability of these APIs and to make the security review required.
+* Unlike chrome:// pages, chrome-untrusted:// pages don't get access to all renderer exposed Mojo interfaces by default. Use `PopulateChromeWebUIFrameInterfaceBrokers` to expose WebUI specific interfaces to your WebUI. See [this CL](https://crrev.com/c/3138688/5/chrome/browser/chrome_browser_interface_binders.cc) for example.
+* The exposed interface has a different threat model: a compromised `chrome-untrusted://` page could try to exploit the interface (e.g. sending malformed messages, closing the Mojo pipe).
+
+When exposing extra capabilities to chrome-untrusted://, keep in mind:
+
+* Don't grant any capabilities that we wouldn't grant to a regular renderer. For example, don't expose unrestricted access to Bluetooth devices, but expose a method that opens a browser-controlled dialog where the user chooses a device.
+* What you received (from the WebUI page) is untrustworthy. You must sanitize and verify its content before processing.
+* What you send (to the WebUI page) could be exfiltrated to the Web. Don't send sensitive information (e.g. user credentials). Only send what you actually need.
+* The difference in Mojo interface lifetimes could lead to use-after-free bugs (e.g. a page reloads itself when it shouldn't). We recommend you create and reinitialize the interface on each page load (using [WebUIPrimaryPageChanged](https://source.chromium.org/chromium/chromium/src/+/main:content/public/browser/web_ui_controller.h;l=54?q=WebUIPrimaryPageChanged&ss=chromium)), and have the JavaScript bind the interface on page load.
+
+We also recommend using Mojo to communicate between parent and child frames whenever possible. See [this CL](https://crrev.com/c/3222406) for example. 
+
+You should only use `postMessage()` when transferring objects unsupported by Mojo. For example, Media App uses `postMessage()` to pass a read-only [`FileSystemHandle`](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API) file handle to `chrome-untrusted://media-app` from its parent `chrome://media-app`.
+
+We encourage teams to engage with [SECURITY_OWNERS](https://source.chromium.org/chromium/chromium/src/+/main:ipc/SECURITY_OWNERS) early and get the reviews required.
 
 ## Can chrome-untrusted:// be the main document or does it need to be embedded in a `chrome://` page?
 Yes, `chrome-untrusted://` can be the main document, although the most common case is for a `chrome://` page to embed a `chrome-untrusted://` subframe.
@@ -118,12 +132,14 @@
 
 2. Register the WebUIConfig
 
-Add the `WebUIConfig` to the list of WebUIConfigs in `[ChromeUntrustedWebUIControllerFactory](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc)`.
+Add the `WebUIConfig` to the list of WebUIConfigs in [`ChromeUntrustedWebUIControllerFactory`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc).
 
 ```cpp
 register_config(std::make_unique<chromeos::UntrustedExampleUIConfig>());
 ```
 
+3. If needed, implement and register the necessary Mojo interfaces. See [this CL](https://crrev.com/c/3138688/5/chrome/browser/chrome_browser_interface_binders.cc) for example.
+
 ### Embed chrome-untrusted:// in chrome:// WebUIs
 
 Developers can embed `chrome-untrusted://` iframes in `chrome://` pages. [Example CL](https://chromium-review.googlesource.com/c/chromium/src/+/2037186).
@@ -143,4 +159,4 @@
 trusted_data_source->OverrideContentSecurityPolicy(
     “frame-src ” + kUntrustedExampleURL);
 ```
-5. Add communication mechanism to `chrome-untrusted://` frames. For example, `iframe.postMessage()` and `window.onmessage`.
+5. Add communication mechanism to `chrome-untrusted://` frames. For example, [using Mojo](https://crrev.com/c/3222406), or `postMessage` the JavaScript object is not supported by Mojo.
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn
index b15b5cca..367ad32 100644
--- a/extensions/BUILD.gn
+++ b/extensions/BUILD.gn
@@ -277,7 +277,6 @@
     "//extensions/test/data/",
     "//net/tools/testserver/",
     "//third_party/pywebsocket3/src/mod_pywebsocket/",
-    "//third_party/tlslite/",
     "$root_out_dir/extensions_shell_and_test.pak",
   ]
 
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index daf1c4e0..a3d1b78ae 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -763,10 +763,7 @@
   // RenderFrameHost.
   if (!render_frame_host_)
     return;
-  // Only the main frame handles dev tools messages.
-  WebContents::FromRenderFrameHost(render_frame_host_)
-      ->GetMainFrame()
-      ->AddMessageToConsole(level, message);
+  render_frame_host_->AddMessageToConsole(level, message);
 }
 
 void ExtensionFunction::SetTransferredBlobUUIDs(
diff --git a/extensions/browser/suggest_permission_util.cc b/extensions/browser/suggest_permission_util.cc
index f7769ad..b92edbf0 100644
--- a/extensions/browser/suggest_permission_util.cc
+++ b/extensions/browser/suggest_permission_util.cc
@@ -37,11 +37,8 @@
       extension->is_platform_app() ?
           kPermissionsHelpURLForApps : kPermissionsHelpURLForExtensions);
 
-  // Only the main frame handles dev tools messages.
-  content::WebContents::FromRenderFrameHost(render_frame_host)
-      ->GetMainFrame()
-      ->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning,
-                            message);
+  render_frame_host->AddMessageToConsole(
+      blink::mojom::ConsoleMessageLevel::kWarning, message);
 }
 
 }  // namespace
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index fb0093ed..deb4224 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -767,7 +767,6 @@
     "//net/tools/testserver/",
     "//third_party/blink/web_tests/http/tests/inspector-protocol/",
     "//third_party/pywebsocket3/",
-    "//third_party/tlslite/",
   ]
 
   if (is_fuchsia) {
diff --git "a/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.textpb" "b/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.textpb"
index 94f3cb4..94d4601 100644
--- "a/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.textpb"
+++ "b/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.textpb"
@@ -1,9 +1,8 @@
 {
-  "$build/goma": {
-    "enable_ats": true,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "jobs": 250,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git "a/infra/config/generated/builders/ci/Android WebView P FYI \050rel\051/properties.textpb" "b/infra/config/generated/builders/ci/Android WebView P FYI \050rel\051/properties.textpb"
index c6534f7..b6e2921 100644
--- "a/infra/config/generated/builders/ci/Android WebView P FYI \050rel\051/properties.textpb"
+++ "b/infra/config/generated/builders/ci/Android WebView P FYI \050rel\051/properties.textpb"
@@ -1,9 +1,8 @@
 {
-  "$build/goma": {
-    "enable_ats": true,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "jobs": 250,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/Mojo Android/properties.textpb b/infra/config/generated/builders/ci/Mojo Android/properties.textpb
index 7f652d0..a2d72f99 100644
--- a/infra/config/generated/builders/ci/Mojo Android/properties.textpb
+++ b/infra/config/generated/builders/ci/Mojo Android/properties.textpb
@@ -1,9 +1,8 @@
 {
-  "$build/goma": {
-    "enable_ats": true,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "jobs": 250,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/Site Isolation Android/properties.textpb b/infra/config/generated/builders/ci/Site Isolation Android/properties.textpb
index fc3bce3..b232002 100644
--- a/infra/config/generated/builders/ci/Site Isolation Android/properties.textpb
+++ b/infra/config/generated/builders/ci/Site Isolation Android/properties.textpb
@@ -1,9 +1,8 @@
 {
-  "$build/goma": {
-    "enable_ats": true,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "jobs": 250,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index c4a3aede..b1175dab 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -228,7 +228,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -315,7 +315,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -402,7 +402,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -489,7 +489,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -576,7 +576,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -663,7 +663,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -829,7 +829,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -916,7 +916,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1006,7 +1006,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1096,7 +1096,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1186,7 +1186,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1276,7 +1276,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1366,7 +1366,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1456,7 +1456,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1546,7 +1546,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1636,7 +1636,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1726,7 +1726,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1816,7 +1816,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1906,7 +1906,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -1996,7 +1996,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2086,7 +2086,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2173,7 +2173,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2263,7 +2263,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2353,7 +2353,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2443,7 +2443,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2533,7 +2533,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2623,7 +2623,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2713,7 +2713,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2803,7 +2803,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2893,7 +2893,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -2983,7 +2983,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3073,7 +3073,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3163,7 +3163,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3253,7 +3253,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3343,7 +3343,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3430,7 +3430,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3603,7 +3603,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3693,7 +3693,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3780,7 +3780,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3867,7 +3867,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -3954,7 +3954,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4041,7 +4041,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4128,7 +4128,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4215,7 +4215,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4300,7 +4300,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4385,7 +4385,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4472,7 +4472,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4559,7 +4559,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4646,7 +4646,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4733,7 +4733,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4820,7 +4820,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4907,7 +4907,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -4994,7 +4994,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5081,7 +5081,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5168,7 +5168,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5255,7 +5255,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5342,7 +5342,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5429,7 +5429,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5516,7 +5516,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5603,7 +5603,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5690,7 +5690,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5777,7 +5777,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5864,7 +5864,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -5951,7 +5951,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6038,7 +6038,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6527,7 +6527,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6617,7 +6617,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6707,7 +6707,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6797,7 +6797,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6887,7 +6887,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -6975,7 +6975,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7063,7 +7063,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7151,7 +7151,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7239,7 +7239,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7329,7 +7329,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7419,7 +7419,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7509,7 +7509,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7599,7 +7599,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7689,7 +7689,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7779,7 +7779,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7869,7 +7869,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -7959,7 +7959,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8047,7 +8047,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8135,7 +8135,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8225,7 +8225,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8315,7 +8315,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8405,7 +8405,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8495,7 +8495,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -8585,7 +8585,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -9738,7 +9738,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -9828,7 +9828,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -9918,7 +9918,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10008,7 +10008,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10098,7 +10098,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10188,7 +10188,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10278,7 +10278,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10365,7 +10365,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10455,7 +10455,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10542,7 +10542,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10632,7 +10632,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10722,7 +10722,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10812,7 +10812,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10902,7 +10902,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -10992,7 +10992,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11082,7 +11082,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11172,7 +11172,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11262,7 +11262,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11352,7 +11352,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11442,7 +11442,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11532,7 +11532,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11622,7 +11622,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11712,7 +11712,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11802,7 +11802,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11892,7 +11892,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -11982,7 +11982,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12072,7 +12072,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12162,7 +12162,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12252,7 +12252,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12342,7 +12342,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12432,7 +12432,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12522,7 +12522,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12612,7 +12612,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12702,7 +12702,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12792,7 +12792,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12879,7 +12879,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -12966,7 +12966,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13053,7 +13053,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13139,7 +13139,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13225,7 +13225,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13313,7 +13313,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13402,7 +13402,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13490,7 +13490,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13578,7 +13578,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13663,7 +13663,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13749,7 +13749,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13834,7 +13834,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -13924,7 +13924,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14014,7 +14014,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14104,7 +14104,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14194,7 +14194,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14284,7 +14284,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14374,7 +14374,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14464,7 +14464,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14554,7 +14554,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14644,7 +14644,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14734,7 +14734,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14824,7 +14824,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -14914,7 +14914,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15004,7 +15004,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15094,7 +15094,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15184,7 +15184,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15274,7 +15274,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15364,7 +15364,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15600,7 +15600,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15690,7 +15690,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15780,7 +15780,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15870,7 +15870,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -15960,7 +15960,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16050,7 +16050,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16140,7 +16140,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16230,7 +16230,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16320,7 +16320,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16407,7 +16407,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16494,7 +16494,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16581,7 +16581,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16667,7 +16667,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16757,7 +16757,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16847,7 +16847,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -16937,7 +16937,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17024,7 +17024,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17111,7 +17111,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17198,7 +17198,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17288,7 +17288,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17378,7 +17378,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17468,7 +17468,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17558,7 +17558,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17648,7 +17648,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17738,7 +17738,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17828,7 +17828,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -17918,7 +17918,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18008,7 +18008,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18098,7 +18098,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18188,7 +18188,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18278,7 +18278,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18368,7 +18368,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18458,7 +18458,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18548,7 +18548,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18637,7 +18637,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18801,7 +18801,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18891,7 +18891,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -18981,7 +18981,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19071,7 +19071,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19160,7 +19160,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19249,7 +19249,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19338,7 +19338,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19502,7 +19502,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19591,7 +19591,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19681,7 +19681,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19771,7 +19771,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19861,7 +19861,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -19951,7 +19951,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20041,7 +20041,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20130,7 +20130,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20220,7 +20220,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20310,7 +20310,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20477,7 +20477,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20570,7 +20570,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20657,7 +20657,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20744,7 +20744,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20831,7 +20831,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -20921,7 +20921,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21011,7 +21011,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21101,7 +21101,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21190,7 +21190,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21276,7 +21276,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21366,7 +21366,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21452,7 +21452,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21538,7 +21538,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21627,7 +21627,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21716,7 +21716,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21805,7 +21805,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21895,7 +21895,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -21982,7 +21982,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22069,7 +22069,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22159,7 +22159,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22249,7 +22249,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22339,7 +22339,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22429,7 +22429,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22519,7 +22519,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22609,7 +22609,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22699,7 +22699,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22789,7 +22789,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22879,7 +22879,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -22969,7 +22969,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23059,7 +23059,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23149,7 +23149,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23238,7 +23238,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23327,7 +23327,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23413,7 +23413,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23503,7 +23503,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23593,7 +23593,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23683,7 +23683,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23773,7 +23773,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23863,7 +23863,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -23953,7 +23953,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24043,7 +24043,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24133,7 +24133,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24302,7 +24302,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24389,7 +24389,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24476,7 +24476,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24566,7 +24566,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -24653,7 +24653,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25109,7 +25109,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25199,7 +25199,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25289,7 +25289,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25379,7 +25379,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25470,7 +25470,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25639,7 +25639,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25726,7 +25726,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25816,7 +25816,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -25987,7 +25987,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26074,7 +26074,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26164,7 +26164,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26254,7 +26254,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26344,7 +26344,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26434,7 +26434,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26524,7 +26524,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26614,7 +26614,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26704,7 +26704,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26794,7 +26794,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -26960,7 +26960,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27050,7 +27050,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27140,7 +27140,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27230,7 +27230,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27320,7 +27320,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27410,7 +27410,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27500,7 +27500,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27590,7 +27590,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27680,7 +27680,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27770,7 +27770,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27859,7 +27859,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -27949,7 +27949,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28039,7 +28039,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28129,7 +28129,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28216,7 +28216,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28303,7 +28303,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28393,7 +28393,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28479,7 +28479,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28746,7 +28746,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28833,7 +28833,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -28923,7 +28923,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29013,7 +29013,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29103,7 +29103,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29190,7 +29190,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29277,7 +29277,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29364,7 +29364,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29454,7 +29454,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29544,7 +29544,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29631,7 +29631,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29718,7 +29718,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29808,7 +29808,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29898,7 +29898,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -29988,7 +29988,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30078,7 +30078,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30168,7 +30168,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30255,7 +30255,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30342,7 +30342,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30430,7 +30430,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30520,7 +30520,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30610,7 +30610,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30700,7 +30700,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30867,7 +30867,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -30954,7 +30954,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31041,7 +31041,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31128,7 +31128,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31215,7 +31215,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31302,7 +31302,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31389,7 +31389,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31478,7 +31478,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31568,7 +31568,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31658,7 +31658,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31897,7 +31897,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -31986,7 +31986,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32079,7 +32079,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32168,7 +32168,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32262,7 +32262,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32352,7 +32352,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32441,7 +32441,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32534,7 +32534,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32623,7 +32623,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32716,7 +32716,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32805,7 +32805,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32894,7 +32894,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -32983,7 +32983,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33072,7 +33072,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33161,7 +33161,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33250,7 +33250,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33340,7 +33340,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33430,7 +33430,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33517,7 +33517,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33604,7 +33604,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33691,7 +33691,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -33781,7 +33781,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34306,7 +34306,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34396,7 +34396,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34486,7 +34486,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34575,7 +34575,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34662,7 +34662,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34758,7 +34758,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34845,7 +34845,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -34935,7 +34935,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35025,7 +35025,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35112,7 +35112,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35199,7 +35199,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35286,7 +35286,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35373,7 +35373,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35460,7 +35460,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35547,7 +35547,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35637,7 +35637,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35727,7 +35727,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35814,7 +35814,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35904,7 +35904,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -35991,7 +35991,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36081,7 +36081,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36168,7 +36168,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36255,7 +36255,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36342,7 +36342,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36432,7 +36432,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36519,7 +36519,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36609,7 +36609,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36696,7 +36696,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36783,7 +36783,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36873,7 +36873,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -36960,7 +36960,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37047,7 +37047,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37134,7 +37134,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37224,7 +37224,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37311,7 +37311,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37398,7 +37398,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37485,7 +37485,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37575,7 +37575,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37662,7 +37662,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37751,7 +37751,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37838,7 +37838,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -37924,7 +37924,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38014,7 +38014,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38262,7 +38262,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38352,7 +38352,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38442,7 +38442,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38529,7 +38529,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38619,7 +38619,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38707,7 +38707,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38795,7 +38795,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38883,7 +38883,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -38973,7 +38973,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39278,7 +39278,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39367,7 +39367,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39456,7 +39456,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39545,7 +39545,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39634,7 +39634,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39723,7 +39723,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39808,7 +39808,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39893,7 +39893,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -39982,7 +39982,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40069,7 +40069,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40156,7 +40156,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40243,7 +40243,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40329,7 +40329,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40415,7 +40415,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40503,7 +40503,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40590,7 +40590,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40675,7 +40675,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40760,7 +40760,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40848,7 +40848,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -40933,7 +40933,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41018,7 +41018,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41103,7 +41103,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41190,7 +41190,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41277,7 +41277,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41364,7 +41364,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41451,7 +41451,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41538,7 +41538,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41625,7 +41625,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41712,7 +41712,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41799,7 +41799,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41886,7 +41886,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -41973,7 +41973,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42063,7 +42063,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42150,7 +42150,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42237,7 +42237,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42711,7 +42711,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42800,7 +42800,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42889,7 +42889,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -42978,7 +42978,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43068,7 +43068,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43155,7 +43155,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43242,7 +43242,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43329,7 +43329,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43416,7 +43416,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43663,7 +43663,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43749,7 +43749,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43836,7 +43836,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -43926,7 +43926,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -44332,7 +44332,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -44422,7 +44422,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -44509,7 +44509,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -44596,7 +44596,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -44683,7 +44683,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45054,7 +45054,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45141,7 +45141,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45228,7 +45228,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45315,7 +45315,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45404,7 +45404,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45493,7 +45493,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45582,7 +45582,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45668,7 +45668,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45757,7 +45757,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45844,7 +45844,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -45931,7 +45931,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -46018,7 +46018,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -46105,7 +46105,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -46334,7 +46334,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -46421,7 +46421,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47281,7 +47281,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47331,7 +47331,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47381,7 +47381,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47431,7 +47431,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47481,7 +47481,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47531,7 +47531,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47581,7 +47581,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47631,7 +47631,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47681,7 +47681,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47731,7 +47731,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47781,7 +47781,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47831,7 +47831,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47881,7 +47881,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47931,7 +47931,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -47981,7 +47981,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48031,7 +48031,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48081,7 +48081,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48131,7 +48131,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48181,7 +48181,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48236,7 +48236,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48287,7 +48287,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48338,7 +48338,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48388,7 +48388,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48438,7 +48438,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48487,7 +48487,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48537,7 +48537,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48587,7 +48587,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48637,7 +48637,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48687,7 +48687,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48737,7 +48737,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48787,7 +48787,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48837,7 +48837,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48887,7 +48887,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48937,7 +48937,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -48988,7 +48988,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49039,7 +49039,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49090,7 +49090,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49141,7 +49141,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49192,7 +49192,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49243,7 +49243,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49293,7 +49293,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49343,7 +49343,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49396,7 +49396,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49449,7 +49449,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49500,7 +49500,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49551,7 +49551,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49602,7 +49602,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49653,7 +49653,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49703,7 +49703,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49753,7 +49753,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49827,7 +49827,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -49914,7 +49914,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -50239,7 +50239,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -50330,7 +50330,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -50421,7 +50421,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -50512,7 +50512,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -50777,7 +50777,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -50868,7 +50868,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51061,7 +51061,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51152,7 +51152,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51243,7 +51243,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51334,7 +51334,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51425,7 +51425,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51516,7 +51516,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51607,7 +51607,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51698,7 +51698,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51789,7 +51789,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51880,7 +51880,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -51971,7 +51971,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52062,7 +52062,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52153,7 +52153,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52418,7 +52418,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52517,7 +52517,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52616,7 +52616,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52905,7 +52905,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -52997,7 +52997,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53088,7 +53088,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53179,7 +53179,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53270,7 +53270,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53361,7 +53361,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53456,7 +53456,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53551,7 +53551,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53642,7 +53642,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -53918,7 +53918,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54009,7 +54009,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54101,7 +54101,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54192,7 +54192,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54283,7 +54283,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54374,7 +54374,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54465,7 +54465,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54556,7 +54556,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54647,7 +54647,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54738,7 +54738,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54829,7 +54829,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -54920,7 +54920,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55011,7 +55011,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55102,7 +55102,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55193,7 +55193,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55284,7 +55284,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55375,7 +55375,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55466,7 +55466,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55558,7 +55558,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55649,7 +55649,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55740,7 +55740,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55832,7 +55832,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -55923,7 +55923,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56014,7 +56014,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56105,7 +56105,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56195,7 +56195,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56286,7 +56286,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56377,7 +56377,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56468,7 +56468,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56559,7 +56559,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56861,7 +56861,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -56952,7 +56952,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57042,7 +57042,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57133,7 +57133,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57224,7 +57224,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57315,7 +57315,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57406,7 +57406,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57679,7 +57679,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57770,7 +57770,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57867,7 +57867,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -57958,7 +57958,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58049,7 +58049,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58224,7 +58224,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58312,7 +58312,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58400,7 +58400,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58488,7 +58488,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58577,7 +58577,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58666,7 +58666,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58755,7 +58755,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58844,7 +58844,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -58935,7 +58935,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59113,7 +59113,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59299,7 +59299,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59477,7 +59477,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59568,7 +59568,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59659,7 +59659,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59750,7 +59750,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59841,7 +59841,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -59932,7 +59932,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60022,7 +60022,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60112,7 +60112,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60202,7 +60202,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60292,7 +60292,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60379,7 +60379,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60466,7 +60466,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60553,7 +60553,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60640,7 +60640,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60727,7 +60727,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60814,7 +60814,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60901,7 +60901,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -60988,7 +60988,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61075,7 +61075,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61162,7 +61162,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61249,7 +61249,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61336,7 +61336,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61423,7 +61423,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61510,7 +61510,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61597,7 +61597,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61684,7 +61684,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61771,7 +61771,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61858,7 +61858,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -61945,7 +61945,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62032,7 +62032,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62119,7 +62119,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62206,7 +62206,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62291,7 +62291,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62376,7 +62376,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62461,7 +62461,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62546,7 +62546,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62631,7 +62631,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62716,7 +62716,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62801,7 +62801,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62886,7 +62886,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -62971,7 +62971,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63056,7 +63056,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63141,7 +63141,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63226,7 +63226,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63311,7 +63311,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63398,7 +63398,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63485,7 +63485,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63572,7 +63572,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63659,7 +63659,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63746,7 +63746,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63833,7 +63833,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -63920,7 +63920,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64007,7 +64007,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64094,7 +64094,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64181,7 +64181,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64268,7 +64268,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64355,7 +64355,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64442,7 +64442,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64529,7 +64529,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64616,7 +64616,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64703,7 +64703,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64788,7 +64788,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64873,7 +64873,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -64960,7 +64960,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65139,7 +65139,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65232,7 +65232,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65333,7 +65333,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65429,7 +65429,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65533,7 +65533,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65626,7 +65626,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65719,7 +65719,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65812,7 +65812,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -65912,7 +65912,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66005,7 +66005,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66098,7 +66098,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66191,7 +66191,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66284,7 +66284,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66374,7 +66374,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66464,7 +66464,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66555,7 +66555,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66646,7 +66646,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66740,7 +66740,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -66918,7 +66918,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67096,7 +67096,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67187,7 +67187,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67278,7 +67278,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67370,7 +67370,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67461,7 +67461,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67552,7 +67552,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67643,7 +67643,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67734,7 +67734,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67825,7 +67825,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -67916,7 +67916,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68014,7 +68014,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68105,7 +68105,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68196,7 +68196,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68286,7 +68286,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68377,7 +68377,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68468,7 +68468,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -68563,7 +68563,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69034,7 +69034,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69125,7 +69125,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69216,7 +69216,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69307,7 +69307,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69392,7 +69392,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69483,7 +69483,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69574,7 +69574,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69665,7 +69665,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69756,7 +69756,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69848,7 +69848,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -69940,7 +69940,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70031,7 +70031,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70122,7 +70122,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70299,7 +70299,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70390,7 +70390,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70481,7 +70481,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70572,7 +70572,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70863,7 +70863,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -70957,7 +70957,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71048,7 +71048,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71142,7 +71142,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71236,7 +71236,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71324,7 +71324,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71580,7 +71580,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71672,7 +71672,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71763,7 +71763,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71853,7 +71853,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -71944,7 +71944,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72035,7 +72035,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72126,7 +72126,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72217,7 +72217,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72309,7 +72309,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72400,7 +72400,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72491,7 +72491,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72582,7 +72582,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72858,7 +72858,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -72949,7 +72949,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73041,7 +73041,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73133,7 +73133,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73311,7 +73311,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73402,7 +73402,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73497,7 +73497,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73588,7 +73588,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73683,7 +73683,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -73775,7 +73775,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74050,7 +74050,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74141,7 +74141,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74232,7 +74232,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74323,7 +74323,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74414,7 +74414,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74505,7 +74505,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74595,7 +74595,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74767,7 +74767,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -74940,7 +74940,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75029,7 +75029,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75117,7 +75117,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75206,7 +75206,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75299,7 +75299,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75580,7 +75580,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75665,7 +75665,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75753,7 +75753,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75841,7 +75841,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -75930,7 +75930,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76019,7 +76019,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76108,7 +76108,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76197,7 +76197,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76468,7 +76468,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76557,7 +76557,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76646,7 +76646,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76735,7 +76735,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76824,7 +76824,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -76913,7 +76913,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77002,7 +77002,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77091,7 +77091,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77180,7 +77180,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77270,7 +77270,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77360,7 +77360,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77449,7 +77449,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77538,7 +77538,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77626,7 +77626,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -77877,7 +77877,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -78326,7 +78326,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -78678,7 +78678,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -78770,7 +78770,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -78868,7 +78868,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -79048,7 +79048,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -79225,7 +79225,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -79313,7 +79313,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -79737,7 +79737,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -79825,7 +79825,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -79916,7 +79916,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80007,7 +80007,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80098,7 +80098,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80189,7 +80189,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80286,7 +80286,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80377,7 +80377,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80665,7 +80665,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80759,7 +80759,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80850,7 +80850,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -80941,7 +80941,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81033,7 +81033,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81124,7 +81124,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81216,7 +81216,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81307,7 +81307,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81398,7 +81398,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81489,7 +81489,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81580,7 +81580,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81671,7 +81671,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81842,7 +81842,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 1
+        value: 5
       }
       experiments {
         key: "luci.use_realms"
@@ -81936,7 +81936,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -81979,7 +81979,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82028,7 +82028,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82071,7 +82071,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82120,7 +82120,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82163,7 +82163,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82212,7 +82212,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82255,7 +82255,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82298,7 +82298,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82341,7 +82341,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82405,7 +82405,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82453,7 +82453,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82501,7 +82501,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82543,7 +82543,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82585,7 +82585,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82633,7 +82633,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82681,7 +82681,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82723,7 +82723,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82771,7 +82771,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82819,7 +82819,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82861,7 +82861,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82909,7 +82909,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82957,7 +82957,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -82999,7 +82999,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -83041,7 +83041,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
@@ -83083,7 +83083,7 @@
       }
       experiments {
         key: "luci.recipes.use_python3"
-        value: 5
+        value: 20
       }
       experiments {
         key: "luci.use_realms"
diff --git a/infra/config/generated/luci/project.cfg b/infra/config/generated/luci/project.cfg
index 5b39869..9f7b01980 100644
--- a/infra/config/generated/luci/project.cfg
+++ b/infra/config/generated/luci/project.cfg
@@ -7,7 +7,7 @@
 name: "chromium"
 access: "group:all"
 lucicfg {
-  version: "1.30.1"
+  version: "1.30.4"
   package_dir: "../.."
   config_dir: "generated/luci"
   entry_point: "main.star"
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star
index 2ae5c46f..8dafdb708 100644
--- a/infra/config/lib/ci.star
+++ b/infra/config/lib/ci.star
@@ -205,12 +205,16 @@
         **kwargs
     )
 
-def android_fyi_builder(*, name, **kwargs):
+def android_fyi_builder(
+        *,
+        name,
+        goma_backend = builders.goma.backend.RBE_PROD,
+        **kwargs):
     kwargs.setdefault("os", os.LINUX_BIONIC_REMOVE)
     return ci_builder(
         name = name,
         builder_group = "chromium.android.fyi",
-        goma_backend = builders.goma.backend.RBE_PROD,
+        goma_backend = goma_backend,
         **kwargs
     )
 
diff --git a/infra/config/recipes.star b/infra/config/recipes.star
index 598a38f..989b2a2 100644
--- a/infra/config/recipes.star
+++ b/infra/config/recipes.star
@@ -129,7 +129,7 @@
     name = "recipe:chromium",
     bootstrappable = True,
     experiments = {
-        "luci.recipes.use_python3": 5,
+        "luci.recipes.use_python3": 20,
     },
 )
 
@@ -181,7 +181,7 @@
     name = "recipe:chromium_trybot",
     bootstrappable = True,
     experiments = {
-        "luci.recipes.use_python3": 1,
+        "luci.recipes.use_python3": 5,
     },
 )
 
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index caef3cd..c327facd 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -1126,6 +1126,9 @@
         category = "webview",
         short_name = "p-rel",
     ),
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.DEFAULT,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 # TODO(crbug.com/1022533#c40): Remove this builder once there are no associated
@@ -3464,6 +3467,9 @@
         category = "site_isolation",
     ),
     notifies = ["Site Isolation Android"],
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.DEFAULT,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 ci.fyi_builder(
@@ -4715,6 +4721,9 @@
     ),
     cq_mirrors_console_view = "mirrors",
     main_console_view = main_console_if_on_branch(),
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.DEFAULT,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 ci.gpu_linux_builder(
@@ -6358,6 +6367,9 @@
     console_view_entry = consoles.console_view_entry(
         short_name = "and",
     ),
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.DEFAULT,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 ci.mojo_builder(
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 101cc54..97b5c65 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -511,10 +511,6 @@
      FEATURE_VALUE_TYPE(
          optimization_guide::features::
              kRemoteOptimizationGuideFetchingAnonymousDataConsent)},
-    {"legacy-tls-interstitial",
-     flag_descriptions::kIOSLegacyTLSInterstitialsName,
-     flag_descriptions::kIOSLegacyTLSInterstitialsDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(web::features::kIOSLegacyTLSInterstitial)},
 #if BUILDFLAG(IOS_SCREEN_TIME_ENABLED)
     {"screen-time-integration-ios",
      flag_descriptions::kScreenTimeIntegrationName,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 110859d..a88dcdb 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -306,12 +306,6 @@
     "an individual promotion causes that promotion but no other promotions to "
     "occur.";
 
-const char kIOSLegacyTLSInterstitialsName[] = "Show legacy TLS interstitials";
-const char kIOSLegacyTLSInterstitialsDescription[] =
-    "When enabled, an interstitial will be shown on main-frame navigations "
-    "that use legacy TLS connections, and subresources using legacy TLS "
-    "connections will be blocked.";
-
 const char kIOSPersistCrashRestoreName[] = "Persist Crash Restore Infobar";
 const char kIOSPersistCrashRestoreDescription[] =
     "When enabled, the Crash Restore Infobar will persist through navigations "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 8575dc3..3a1b3795 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -270,11 +270,6 @@
 extern const char kInProductHelpDemoModeName[];
 extern const char kInProductHelpDemoModeDescription[];
 
-// Title and description for the flag to enable interstitials on legacy TLS
-// connections.
-extern const char kIOSLegacyTLSInterstitialsName[];
-extern const char kIOSLegacyTLSInterstitialsDescription[];
-
 // Title and description for the flag to persist the Crash Restore Infobar
 // across navigations.
 extern const char kIOSPersistCrashRestoreName[];
diff --git a/ios/chrome/browser/link_to_text/link_to_text_response.mm b/ios/chrome/browser/link_to_text/link_to_text_response.mm
index 6c4a762..41e5ac3 100644
--- a/ios/chrome/browser/link_to_text/link_to_text_response.mm
+++ b/ios/chrome/browser/link_to_text/link_to_text_response.mm
@@ -6,8 +6,8 @@
 
 #import "base/strings/sys_string_conversions.h"
 #import "base/values.h"
+#import "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #import "components/shared_highlighting/core/common/text_fragment.h"
-#import "components/shared_highlighting/core/common/text_fragments_utils.h"
 #import "components/ukm/ios/ukm_url_recorder.h"
 #import "ios/chrome/browser/link_to_text/link_to_text_payload.h"
 #import "ios/chrome/browser/link_to_text/link_to_text_utils.h"
diff --git a/ios/chrome/browser/passwords/password_controller.h b/ios/chrome/browser/passwords/password_controller.h
index 3f1ee2e0..f348788 100644
--- a/ios/chrome/browser/passwords/password_controller.h
+++ b/ios/chrome/browser/passwords/password_controller.h
@@ -31,6 +31,8 @@
 
 // Delegate for registering view controller and displaying its view. Used to
 // add views to BVC.
+// TODO(crbug.com/1272487): Refactor this API to not be coupled to the BVC and
+// to use the UI command patterns.
 @protocol PasswordControllerDelegate
 
 // Adds |viewController| as child controller in order to display auto sign-in
@@ -44,6 +46,8 @@
 @end
 
 // Per-tab password controller. Handles password autofill and saving.
+// TODO(crbug.com/1272487): Refactor this into an appropriately-scoped object,
+// such as a browser agent.
 @interface PasswordController
     : NSObject <CRWWebStateObserver, IOSChromePasswordManagerClientBridge>
 
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index f15a818b..38d3060 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -106,7 +106,6 @@
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list/web_usage_enabler",
     "//ios/components/security_interstitials",
-    "//ios/components/security_interstitials/legacy_tls",
     "//ios/components/security_interstitials/lookalikes",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/text_zoom:text_zoom_api",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index 668e410f..1b30759 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -80,7 +80,6 @@
 #import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h"
 #import "ios/chrome/browser/web/tab_id_tab_helper.h"
 #import "ios/components/security_interstitials/ios_blocking_page_tab_helper.h"
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_container.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_tab_allow_list.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.h"
@@ -188,10 +187,6 @@
   LookalikeUrlTabAllowList::CreateForWebState(web_state);
   LookalikeUrlContainer::CreateForWebState(web_state);
 
-  if (base::FeatureList::IsEnabled(web::features::kIOSLegacyTLSInterstitial)) {
-    LegacyTLSTabAllowList::CreateForWebState(web_state);
-  }
-
   // TODO(crbug.com/794115): pre-rendered WebState have lots of unnecessary
   // tab helpers for historical reasons. For the moment, AttachTabHelpers
   // allows to inhibit the creation of some of them. Once PreloadController
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm
index 4d5bce5c1..91d6bf1 100644
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm
@@ -72,9 +72,6 @@
 @property(nonatomic, assign) ChromeAccountManagerService* accountManagerService;
 // YES if this coordinator is currently used in First Run.
 @property(nonatomic, readonly) BOOL firstRun;
-// The consent string ids that were pushed that are related to the text for
-// sync.
-@property(nonatomic, assign, readonly) NSMutableArray* consentStringIDs;
 
 @end
 
@@ -112,10 +109,9 @@
     return;
   }
 
-  ChromeBrowserState* browserState = self.browser->GetBrowserState();
-
   AuthenticationService* authenticationService =
-      AuthenticationServiceFactory::GetForBrowserState(browserState);
+      AuthenticationServiceFactory::GetForBrowserState(
+          self.browser->GetBrowserState());
 
   if (authenticationService->GetPrimaryIdentity(
           signin::ConsentLevel::kSignin)) {
@@ -132,10 +128,11 @@
   self.viewController = [[SigninSyncViewController alloc] init];
   self.viewController.delegate = self;
   self.viewController.enterpriseSignInRestrictions =
-      GetEnterpriseSignInRestrictions(browserState);
+      GetEnterpriseSignInRestrictions(self.browser->GetBrowserState());
 
   self.accountManagerService =
-      ChromeAccountManagerServiceFactory::GetForBrowserState(browserState);
+      ChromeAccountManagerServiceFactory::GetForBrowserState(
+          self.browser->GetBrowserState());
 
   self.mediator = [[SigninSyncMediator alloc]
       initWithAccountManagerService:self.accountManagerService
@@ -194,17 +191,8 @@
       self.mediator.selectedIdentity;
 }
 
-- (void)showSyncSettings {
-  // TODO(crbug.com/1268669): Implement this.
-}
-
-- (void)addConsentStringID:(const int)stringID {
-  [self.consentStringIDs addObject:[NSNumber numberWithInt:stringID]];
-}
-
 - (void)didTapPrimaryActionButton {
   if (self.mediator.selectedIdentity) {
-    // TODO(crbug.com/1268671): This should start sync as well.
     [self startSignIn];
   } else {
     [self triggerAddAccount];
@@ -340,7 +328,6 @@
   }
 }
 
-// TODO(crbug.com/1268671): This should start sync as well.
 // Starts the sign in process.
 - (void)startSignIn {
   DCHECK(self.mediator.selectedIdentity);
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h
index d5efbc6aa..03085b3 100644
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h
+++ b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h
@@ -20,9 +20,6 @@
 @property(nonatomic, assign)
     EnterpriseSignInRestrictions enterpriseSignInRestrictions;
 
-// YES if the identity control button has to be in the top of the screen.
-@property(nonatomic, assign) BOOL identityControlInTop;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm
index 825b47a1..a18d691 100644
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm
@@ -24,10 +24,8 @@
 namespace {
 
 // Width of the identity control if nothing is contraining it.
-constexpr CGFloat kIdentityControlMaxWidth = 327;
-constexpr CGFloat kIdentityTopMargin = 16;
-constexpr CGFloat kMarginBetweenContents = 12;
-constexpr CGFloat kTopSpecificContentVerticalMargin = 24;
+const CGFloat kIdentityControlMaxWidth = 327;
+const CGFloat kIdentityTopMargin = 16;
 
 // URL for the learn more text.
 // Need to set a value so the delegate gets called.
@@ -36,8 +34,6 @@
 NSString* const kLearnMoreTextViewAccessibilityIdentifier =
     @"kLearnMoreTextViewAccessibilityIdentifier";
 
-constexpr int kEnableSyncStringID = IDS_IOS_FIRST_RUN_SIGNIN_CONTINUE_AS;
-
 }  // namespace
 
 @interface SigninSyncViewController () <UITextViewDelegate>
@@ -74,49 +70,31 @@
   self.readMoreString =
       l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SCREEN_READ_MORE);
 
-  int titleTextID = IDS_IOS_FIRST_RUN_SIGNIN_TITLE;
-  [self.delegate addConsentStringID:titleTextID];
-  self.titleText = l10n_util::GetNSString(titleTextID);
-
-  int subtitleTextID;
+  self.titleText = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_TITLE);
   if (self.enterpriseSignInRestrictions == kNoEnterpriseRestriction) {
-    subtitleTextID = IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE;
+    self.subtitleText =
+        l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE);
   } else {
-    subtitleTextID = IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE_MANAGED;
+    self.subtitleText =
+        l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE_MANAGED);
   }
-  [self.delegate addConsentStringID:subtitleTextID];
-  self.subtitleText = l10n_util::GetNSString(subtitleTextID);
-
   if (!self.primaryActionString) {
     // |primaryActionString| could already be set using the consumer methods.
     self.primaryActionString =
         l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SIGN_IN_ACTION);
   }
-  // Set the consent ID associated with the primary action string to
-  // |kEnableSyncStringID| regardless of its current value because this is the
-  // only string that will be used in the button when enabling sync.
-  [self.delegate addConsentStringID:kEnableSyncStringID];
 
-  if (self.identityControlInTop) {
-    [self.topSpecificContentView addSubview:self.identityControl];
-  } else {
-    [self.specificContentView addSubview:self.identityControl];
-  }
+  [self.specificContentView addSubview:self.identityControl];
 
-  UILabel* syncInfoLabel = [self syncInfoLabel];
-  UIButton* advanceSyncSettingsButton = [self advanceSyncSettingsButton];
-
-  // Add content specific to sync.
-  [self.specificContentView addSubview:syncInfoLabel];
-  [self.specificContentView addSubview:advanceSyncSettingsButton];
-
-  // Add the Learn More text label if there are enterprise sign-in or sync
-  // restrictions.
+  // Add Learn More text label according to EnterpriseSignInRestrictions.
   if (self.enterpriseSignInRestrictions != kNoEnterpriseRestriction) {
     self.learnMoreTextView.delegate = self;
     [self.specificContentView addSubview:self.learnMoreTextView];
 
     [NSLayoutConstraint activateConstraints:@[
+      [self.learnMoreTextView.topAnchor
+          constraintGreaterThanOrEqualToAnchor:self.identityControl
+                                                   .bottomAnchor],
       [self.learnMoreTextView.bottomAnchor
           constraintEqualToAnchor:self.specificContentView.bottomAnchor],
       [self.learnMoreTextView.centerXAnchor
@@ -131,72 +109,22 @@
   self.secondaryActionString =
       l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_DONT_SIGN_IN);
 
-  // Set constraints specific to the identity control button that don't change.
   NSLayoutConstraint* widthConstraint = [self.identityControl.widthAnchor
       constraintEqualToConstant:kIdentityControlMaxWidth];
   widthConstraint.priority = UILayoutPriorityDefaultHigh;
+
   [NSLayoutConstraint activateConstraints:@[
-    [self.identityControl.centerXAnchor
-        constraintEqualToAnchor:self.identityControl.superview.centerXAnchor],
-    [self.identityControl.widthAnchor
-        constraintLessThanOrEqualToAnchor:self.identityControl.superview
-                                              .widthAnchor],
-    widthConstraint,
-  ]];
-
-  // Set constraints that are dependent on the position of the identity
-  // controller button and sign-in restrictions.
-
-  if (self.identityControlInTop) {
-    [self.identityControl.bottomAnchor
-        constraintEqualToAnchor:self.identityControl.superview.bottomAnchor
-                       constant:-kTopSpecificContentVerticalMargin]
-        .active = YES;
     [self.identityControl.topAnchor
-        constraintEqualToAnchor:self.identityControl.superview.topAnchor
-                       constant:kTopSpecificContentVerticalMargin]
-        .active = YES;
-    if (self.enterpriseSignInRestrictions == kNoEnterpriseRestriction) {
-      [advanceSyncSettingsButton.bottomAnchor
-          constraintLessThanOrEqualToAnchor:advanceSyncSettingsButton.superview
-                                                .bottomAnchor]
-          .active = YES;
-    } else {
-      [advanceSyncSettingsButton.bottomAnchor
-          constraintLessThanOrEqualToAnchor:self.learnMoreTextView.topAnchor]
-          .active = YES;
-    }
-  } else {
-    [advanceSyncSettingsButton.bottomAnchor
-        constraintLessThanOrEqualToAnchor:self.identityControl.topAnchor]
-        .active = YES;
-    if (self.enterpriseSignInRestrictions == kNoEnterpriseRestriction) {
-      [self.identityControl.bottomAnchor
-          constraintEqualToAnchor:self.identityControl.superview.bottomAnchor]
-          .active = YES;
-    } else {
-      [self.learnMoreTextView.topAnchor
-          constraintEqualToAnchor:self.identityControl.bottomAnchor
-                         constant:kIdentityTopMargin]
-          .active = YES;
-    }
-  }
-
-  // Set constraints specific to the content related to sync.
-  [NSLayoutConstraint activateConstraints:@[
-    [syncInfoLabel.topAnchor
-        constraintEqualToAnchor:self.specificContentView.topAnchor],
-    [syncInfoLabel.centerXAnchor
+        constraintEqualToAnchor:self.specificContentView.topAnchor
+                       constant:kIdentityTopMargin],
+    [self.identityControl.centerXAnchor
         constraintEqualToAnchor:self.specificContentView.centerXAnchor],
-    [syncInfoLabel.widthAnchor
+    [self.identityControl.widthAnchor
         constraintLessThanOrEqualToAnchor:self.specificContentView.widthAnchor],
-    [advanceSyncSettingsButton.topAnchor
-        constraintEqualToAnchor:syncInfoLabel.bottomAnchor
-                       constant:kMarginBetweenContents],
-    [advanceSyncSettingsButton.centerXAnchor
-        constraintEqualToAnchor:self.specificContentView.centerXAnchor],
-    [advanceSyncSettingsButton.widthAnchor
-        constraintLessThanOrEqualToAnchor:self.specificContentView.widthAnchor],
+    widthConstraint,
+    [self.identityControl.bottomAnchor
+        constraintLessThanOrEqualToAnchor:self.specificContentView
+                                              .bottomAnchor],
   ]];
 
   // Call super after setting up the strings and others, as required per super
@@ -284,43 +212,6 @@
   return _learnMoreTextView;
 }
 
-// Creates and returns the label that gives detailed information about sync.
-- (UILabel*)syncInfoLabel {
-  UILabel* label = [[UILabel alloc] init];
-  label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
-  label.numberOfLines = 0;
-  label.textAlignment = NSTextAlignmentCenter;
-  label.translatesAutoresizingMaskIntoConstraints = NO;
-  label.adjustsFontForContentSizeCategory = YES;
-  int textID = IDS_IOS_FIRST_RUN_SYNC_SCREEN_CONTENT;
-  [self.delegate addConsentStringID:textID];
-  label.text = l10n_util::GetNSString(textID);
-  label.textColor = [UIColor colorNamed:kGrey600Color];
-  label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
-  return label;
-}
-
-// Creates and returns the button to show advanced settings.
-- (UIButton*)advanceSyncSettingsButton {
-  UIButton* button = [[UIButton alloc] init];
-  button.translatesAutoresizingMaskIntoConstraints = NO;
-  button.titleLabel.numberOfLines = 0;
-  button.titleLabel.adjustsFontForContentSizeCategory = YES;
-  [button.titleLabel
-      setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]];
-  int stringID = IDS_IOS_FIRST_RUN_SYNC_SCREEN_ADVANCE_SETTINGS;
-  [self.delegate addConsentStringID:stringID];
-  [button setTitle:l10n_util::GetNSString(stringID)
-          forState:UIControlStateNormal];
-  [button setTitleColor:[UIColor colorNamed:kBlueColor]
-               forState:UIControlStateNormal];
-
-  [button addTarget:self
-                action:@selector(showAdvanceSyncSettings)
-      forControlEvents:UIControlEventTouchUpInside];
-  return button;
-}
-
 #pragma mark - SignInSyncConsumer
 
 - (void)setSelectedIdentityUserName:(NSString*)userName
@@ -362,8 +253,9 @@
   self.identityControl.hidden = !identityAvailable;
   if (identityAvailable) {
     self.primaryActionString = l10n_util::GetNSStringF(
-        kEnableSyncStringID,
+        IDS_IOS_FIRST_RUN_SIGNIN_CONTINUE_AS,
         base::SysNSStringToUTF16(self.personalizedButtonPrompt));
+    ;
   } else {
     self.primaryActionString =
         l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SIGN_IN_ACTION);
@@ -379,11 +271,6 @@
   [existingString appendString:restrictionString];
 }
 
-// Called when the sync advanced settings button is tapped.
-- (void)showAdvanceSyncSettings {
-  [self.delegate showSyncSettings];
-}
-
 #pragma mark - UITextViewDelegate
 
 - (BOOL)textView:(UITextView*)textView
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h
index 42f2bc6..dfc943f 100644
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h
+++ b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h
@@ -13,12 +13,6 @@
 // Called when the user taps to see the account picker.
 - (void)showAccountPickerFromPoint:(CGPoint)point;
 
-// Called when the user taps to see sync settings.
-- (void)showSyncSettings;
-
-// Adds consent string ID.
-- (void)addConsentStringID:(const int)stringID;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
index 7609fc43..7e0fa4f2 100644
--- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -311,6 +311,8 @@
   }
   _active = active;
 
+  // TODO(crbug.com/1272516): Update the WebUsageEnablerBrowserAgent as part of
+  // setting active/inactive.
   self.viewController.active = active;
 }
 
@@ -392,6 +394,7 @@
 
 // Shuts down the BrowserViewController.
 - (void)destroyViewController {
+  // TODO(crbug.com/1272516): Set the WebUsageEnablerBrowserAgent to disabled.
   [self.viewController shutdown];
   _viewController = nil;
 }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller+delegates.h b/ios/chrome/browser/ui/browser_view/browser_view_controller+delegates.h
index c1cff44..e01a093f 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller+delegates.h
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller+delegates.h
@@ -24,8 +24,10 @@
 
 @property(nonatomic, strong, readonly) SideSwipeController* sideSwipeController;
 
+// TODO(crbug.com/1272494): Move this to BrowserCoordinator.
 @property(nonatomic, strong, readonly) SadTabCoordinator* sadTabCoordinator;
 
+// TODO(crbug.com/1272495): Move this to BrowserCoordinator.
 @property(nonatomic, strong, readonly)
     DownloadManagerCoordinator* downloadManagerCoordinator;
 
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 8fdb73b..8c3c5d4 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -337,9 +337,11 @@
   BookmarkInteractionController* _bookmarkInteractionController;
 
   // Coordinator for displaying alerts for the net export tab helper.
+  // TODO(crbug.com/1272483): Move this to its own coordinator.
   AlertCoordinator* _alertCoordinatorForNetExport;
 
   // Coordinator for displaying Sad Tab.
+  // TODO(crbug.com/1272494): Move SadTabCoordinator to BrowserCoordinator.
   SadTabCoordinator* _sadTabCoordinator;
 
   ToolbarCoordinatorAdaptor* _toolbarCoordinatorAdaptor;
@@ -357,9 +359,12 @@
   std::unique_ptr<FullscreenUIUpdater> _fullscreenUIUpdater;
 
   // Coordinator for the Download Manager UI.
+  // TODO(crbug.com/1272495): Move DownloadManagerCoordinator to
+  // BrowserCoordinator.
   DownloadManagerCoordinator* _downloadManagerCoordinator;
 
   // A map associating webStates with their NTP coordinators.
+  // TODO(crbug.com/1173610): Factor NTPCoordinator ownership out of the BVC
   std::map<web::WebState*, NewTabPageCoordinator*> _ntpCoordinatorsForWebStates;
 
   // Fake status bar view used to blend the toolbar into the status bar.
@@ -383,6 +388,7 @@
   std::unique_ptr<ScopedFullscreenDisabler> _fullscreenDisabler;
 
   // A controller that can provide an entrypoint into Lens features.
+  // TODO(crbug.com/1272549): Move this into BrowserCoordinator.
   id<ChromeLensController> _lensController;
 }
 
@@ -427,6 +433,7 @@
 @property(nonatomic, assign) BOOL bottomPosition;
 // Coordinator for displaying a modal overlay with activity indicator to prevent
 // the user from interacting with the browser view.
+// TODO(crbug.com/1272550): Move this coordinator to BrowserCoordinator.
 @property(nonatomic, strong)
     ActivityOverlayCoordinator* activityOverlayCoordinator;
 // A block to be run when the |tabWasAdded:| method completes the animation
@@ -456,6 +463,7 @@
 // Coordinator for the popup menus.
 @property(nonatomic, strong) PopupMenuCoordinator* popupMenuCoordinator;
 
+// TODO(crbug.com/1272534): Move BubblePresenter to BrowserCoordinator.
 @property(nonatomic, strong) BubblePresenter* bubblePresenter;
 
 // Command handler for text zoom commands
@@ -554,6 +562,7 @@
   self = [super initWithNibName:nil bundle:base::mac::FrameworkBundle()];
   if (self) {
     DCHECK(factory);
+    // TODO(crbug.com/1272524): DCHECK that |browser| is non-null.
 
     _commandDispatcher = dispatcher;
     _browserContainerViewController = browserContainerViewController;
@@ -568,6 +577,8 @@
         [[ToolbarCoordinatorAdaptor alloc] initWithDispatcher:self.dispatcher];
     self.toolbarInterface = _toolbarCoordinatorAdaptor;
 
+    // TODO(crbug.com/1272495): Move DownloadManagerCoordinator to
+    // BrowserCoordinator.
     _downloadManagerCoordinator = [[DownloadManagerCoordinator alloc]
         initWithBaseViewController:_browserContainerViewController
                            browser:browser];
@@ -653,10 +664,13 @@
   [self updateOverlayContainerOrder];
 }
 
+// TODO(crbug.com/1272494): Move SadTabCoordinator to BrowserCoordinator.
 - (SadTabCoordinator*)sadTabCoordinator {
   return _sadTabCoordinator;
 }
 
+// TODO(crbug.com/1272495): Move DownloadManagerCoordinator to
+// BrowserCoordinator.
 - (DownloadManagerCoordinator*)downloadManagerCoordinator {
   return _downloadManagerCoordinator;
 }
@@ -775,12 +789,15 @@
   }
 }
 
+// TODO(crbug.com/1272516): Change webUsageEnabled to be a regular BOOL ivar.
 - (BOOL)isWebUsageEnabled {
   return self.browserState && !_isShutdown &&
          WebUsageEnablerBrowserAgent::FromBrowser(self.browser)
              ->IsWebUsageEnabled();
 }
 
+// TODO(crbug.com/1272516): Change webUsageEnabled to be a regular BOOL ivar.
+// BrowserCoordinator should update the WebUsageEnablerBrowserAgent.
 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled {
   if (!self.browserState || _isShutdown)
     return;
@@ -1029,7 +1046,9 @@
     [self showActivityOverlay:!active];
   }
 
+  // TODO(crbug.com/1272524): Move these updates to BrowserCoordinator.
   if (self.browserState) {
+    // TODO(crbug.com/1272520): Refactor ActiveStateManager for multiwindow.
     ActiveStateManager* active_state_manager =
         ActiveStateManager::FromBrowserState(self.browserState);
     active_state_manager->SetActive(active);
@@ -1157,6 +1176,7 @@
 
   [self setActive:NO];
 
+  // TODO(crbug.com/1272524): Move these updates to BrowserCoordinator.
   if (self.browserState) {
     TextToSpeechPlaybackController* controller =
         TextToSpeechPlaybackControllerFactory::GetInstance()
@@ -1732,6 +1752,9 @@
 // Updates non-view-related functionality with the given browser and tab
 // model.
 // Does not matter whether or not the view has been loaded.
+// TODO(crbug.com/1272524): Move this all into the init. Update the rest of the
+// code to assume that if the BVC isn't shutdown, it has a valid Browser. Update
+// the comments above to reflect reality.
 - (void)updateWithBrowser:(Browser*)browser {
   DCHECK(browser);
   DCHECK(!self.browser);
@@ -1750,6 +1773,8 @@
       ->AddObserver(_URLLoadingObserverBridge.get());
 
   // Set the TTS playback controller's WebStateList.
+  // TODO(crbug.com/1272528): Move this somewhere else -- BrowserCoordinator at
+  // least.
   TextToSpeechPlaybackControllerFactory::GetInstance()
       ->GetForBrowserState(self.browserState)
       ->SetWebStateList(self.browser->GetWebStateList());
@@ -1806,6 +1831,8 @@
   DCHECK(!_locationBarModelDelegate);
 
   // Initialize the prerender service before creating the toolbar controller.
+  // TODO(crbug.com/1272532): Move this to BrowserCoordinator, after creating
+  // the BVC.
   PrerenderService* prerenderService =
       PrerenderServiceFactory::GetForBrowserState(self.browserState);
   if (prerenderService) {
@@ -2061,12 +2088,13 @@
 
   [self.sideSwipeController addHorizontalGesturesToView:self.view];
 
-    // DownloadManagerCoordinator is already created.
+  // DownloadManagerCoordinator is already created.
   DCHECK(_downloadManagerCoordinator);
   _downloadManagerCoordinator.bottomMarginHeightAnchor =
       [NamedGuide guideWithName:kSecondaryToolbarGuide view:self.contentArea]
           .heightAnchor;
 
+  // TODO(crbug.com/1272534): Move BubblePresenter to BrowserCoordinator.
   self.bubblePresenter =
       [[BubblePresenter alloc] initWithBrowserState:self.browserState
                                            delegate:self
@@ -2097,6 +2125,7 @@
   self.omniboxHandler =
       HandlerForProtocol(self.browser->GetCommandDispatcher(), OmniboxCommands);
 
+  // TODO(crbug.com/1272494): Move SadTabCoordinator to BrowserCoordinator.
   _sadTabCoordinator = [[SadTabCoordinator alloc]
       initWithBaseViewController:self.browserContainerViewController
                          browser:self.browser];
@@ -2105,6 +2134,7 @@
   // If there are any existing SadTabHelpers in
   // |self.browser->GetWebStateList()|, update the helpers delegate with the new
   // |_sadTabCoordinator|.
+  // TODO(crbug.com/1272496) : Move this update into TabLifecycleMediator.
   DCHECK(_sadTabCoordinator);
   WebStateList* webStateList = self.browser->GetWebStateList();
   for (int i = 0; i < webStateList->count(); i++) {
@@ -2619,6 +2649,7 @@
 }
 
 #pragma mark - Private Methods: Reading List
+// TODO(crbug.com/1272540): Remove these methods from the BVC.
 
 // Adds the given urls to the reading list.
 - (void)addURLsToReadingList:(NSArray<URLWithTitle*>*)URLs {
@@ -2972,6 +3003,9 @@
 }
 
 #pragma mark - SnapshotGeneratorDelegate methods
+// TODO(crbug.com/1272491): Refactor snapshot generation into (probably) a
+// mediator with a narrowly-defined API to get UI-layer information from the
+// BVC.
 
 - (BOOL)snapshotGenerator:(SnapshotGenerator*)snapshotGenerator
     canTakeSnapshotForWebState:(web::WebState*)webState {
@@ -3091,6 +3125,8 @@
 
 #pragma mark - PasswordControllerDelegate methods
 
+// TODO(crbug.com/1272487): Refactor the PasswordControllerDelegate API into an
+// independent coordinator.
 - (BOOL)displaySignInNotification:(UIViewController*)viewController
                         fromTabId:(NSString*)tabId {
   // Check if the call comes from currently visible tab.
@@ -3263,6 +3299,8 @@
 
 #pragma mark - OverscrollActionsControllerDelegate methods.
 
+// TODO(crbug.com/1272486) : Separate action handling for overscroll from UI
+// management.
 - (void)overscrollActionsController:(OverscrollActionsController*)controller
                    didTriggerAction:(OverscrollAction)action {
   switch (action) {
@@ -3715,10 +3753,14 @@
   }
 }
 
+// TODO(crbug.com/1272540): Remove this command and factor it into a model
+// update helper function as part of the reading list API.
 - (void)addToReadingList:(ReadingListAddCommand*)command {
   [self addURLsToReadingList:command.URLs];
 }
 
+// TODO(crbug.com/1272534): Move this commend implementation to
+// BrowserCoordinator, which should be owning bubblePresenter.
 - (void)showReadingListIPH {
   [self.bubblePresenter presentReadingListBottomToolbarTipBubble];
 }
@@ -3730,6 +3772,7 @@
   [_voiceSearchController prepareToAppear];
 }
 
+// TODO(crbug.com/1272511): Move |showTranslate| out of the BVC.
 - (void)showTranslate {
   feature_engagement::Tracker* engagement_tracker =
       feature_engagement::TrackerFactory::GetForBrowserState(self.browserState);
@@ -3769,6 +3812,8 @@
   [self.sendTabToSelfCoordinator start];
 }
 
+// TODO(crbug.com/1272497): Move requestDesktopSite and requestMobileSite to the
+// WebNavigationBrowserAgent.
 - (void)requestDesktopSite {
   [self reloadWithUserAgentType:web::UserAgentType::DESKTOP];
 }
@@ -3777,6 +3822,9 @@
   [self reloadWithUserAgentType:web::UserAgentType::MOBILE];
 }
 
+// TODO(crbug.com/1272498): Refactor this command away, and add a mediator to
+// observe the active web state closing and push updates into the BVC for UI
+// work.
 - (void)closeCurrentTab {
   WebStateList* webStateList = self.browser->GetWebStateList();
   if (!webStateList)
@@ -3824,6 +3872,8 @@
   }
 }
 
+// TODO(crbug.com/1272550): Move this command implementation to
+// BrowserCoordinator.
 - (void)showActivityOverlay:(BOOL)show {
   if (!show) {
     [self.activityOverlayCoordinator stop];
@@ -3836,6 +3886,8 @@
   }
 }
 
+// TODO(crbug.com/1272549): Move this command implementation into
+// BrowserCoordinator, and potentially into a child coordinator from there.
 - (void)searchImageWithLens:(SearchImageWithLensCommand*)command {
   LensConfiguration* configuration = [[LensConfiguration alloc] init];
   configuration.isIncognito = self.isOffTheRecord;
@@ -3867,6 +3919,7 @@
 
 // Reloads the original url of the last non-redirect item (including non-history
 // items) with |userAgentType|.
+// TODO(crbug.com/1272497): Move this to the WebNavigationBrowserAgent.
 - (void)reloadWithUserAgentType:(web::UserAgentType)userAgentType {
   if (self.userAgentType == userAgentType)
     return;
@@ -3877,6 +3930,8 @@
 
 #pragma mark - ChromeLensControllerDelegate
 
+// TODO(crbug.com/1272549): Move this delegate implmentation into
+// BrowserCoordinator, or into the dedicated lens coordinator.
 - (void)lensControllerDidTapDismissButton {
   // TODO(crbug.com/1234532): Integrate Lens with the browser's navigation
   // stack.
@@ -3903,12 +3958,16 @@
                 oldWebState:(web::WebState*)oldWebState
                     atIndex:(int)atIndex
                      reason:(ActiveWebStateChangeReason)reason {
+  // TODO(crbug.com/1272513): Move this update to NTPCoordinator.
   if (IsSingleNtpEnabled()) {
     self.ntpCoordinator.webState = newWebState;
   }
   if (oldWebState) {
+    // TODO(crbug.com/1272514): Move webstate lifecycle updates to a browser
+    // agent.
     oldWebState->WasHidden();
     oldWebState->SetKeepRenderProcessAlive(false);
+
     [[self ntpCoordinatorForWebState:oldWebState] ntpDidChangeVisibility:NO];
     [self dismissPopups];
   }
@@ -3917,7 +3976,10 @@
   if (!newWebState)
     return;
 
+  // TODO(crbug.com/1272514): Move webstate lifecycle updates to a browser
+  // agent.
   self.currentWebState->GetWebViewProxy().scrollViewProxy.clipsToBounds = NO;
+
   [[self ntpCoordinatorForWebState:newWebState] ntpDidChangeVisibility:YES];
 
   [self webStateSelected:newWebState notifyToolbar:YES];
@@ -3927,6 +3989,8 @@
 - (void)webStateList:(WebStateList*)webStateList
     didDetachWebState:(web::WebState*)webState
               atIndex:(int)atIndex {
+  // TODO(crbug.com/1272514): Move webstate lifecycle updates to a browser
+  // agent.
   webState->WasHidden();
   webState->SetKeepRenderProcessAlive(false);
 
@@ -3940,6 +4004,7 @@
     self.browserContainerViewController.contentView = nil;
   }
 
+  // TODO(crbug.com/1272546): Move UpgradeCenter updates into a browser agent.
   [[UpgradeCenter sharedInstance]
       tabWillClose:TabIdTabHelper::FromWebState(webState)->tab_id()];
 }
@@ -3978,11 +4043,14 @@
   // happen after a new WebState has added and finished initial navigation. If
   // this happens earlier, the initial navigation may end up clearing the
   // infobar(s) that are just added.
+  // TODO(crbug.com/1272546): Move UpgradeCenter updates into a browser agent.
   infobars::InfoBarManager* infoBarManager =
       InfoBarManagerImpl::FromWebState(webState);
   NSString* tabID = TabIdTabHelper::FromWebState(webState)->tab_id();
   [[UpgradeCenter sharedInstance] addInfoBarToManager:infoBarManager
                                              forTabId:tabID];
+
+  // TODO(crbug.com/1272545): Factor this logic into a browser agent.
   if (!ReSignInInfoBarDelegate::Create(self.browserState, webState,
                                        self /* id<SigninPresenter> */)) {
     DisplaySyncErrors(self.browserState, webState,
@@ -4297,6 +4365,9 @@
 
 #pragma mark - NetExportTabHelperDelegate
 
+// TODO(crbug.com/1272483): Factor NextExportTabHelperDelegate out of the BVC,
+// along with the alert coordinator. This feature can be moved to its own
+// coordinator.
 - (void)netExportTabHelper:(NetExportTabHelper*)tabHelper
     showMailComposerWithContext:(ShowMailComposerContext*)context {
   if (![MFMailComposeViewController canSendMail]) {
@@ -4364,6 +4435,9 @@
 
 #pragma mark - CaptivePortalDetectorTabHelperDelegate
 
+// TODO(crbug.com/1272473) : Factor CaptivePortalDetectorTabHelperDelegate of
+// the BVC. This logic can be handled inside the tab helper.
+
 - (void)captivePortalDetectorTabHelper:
             (CaptivePortalDetectorTabHelper*)tabHelper
                  connectWithLandingURL:(const GURL&)landingURL {
@@ -4438,6 +4512,8 @@
 }
 
 #pragma mark - ManageAccountsDelegate
+// TODO(crbug.com/1272476): Factor ManageAccountsDelegate out of the BVC. It can
+// be a browser agent instead.
 
 - (void)onRestoreGaiaCookies {
   signin_metrics::LogAccountReconcilorStateOnGaiaResponse(
diff --git a/ios/chrome/browser/ui/browser_view/common_tab_helper_delegate.h b/ios/chrome/browser/ui/browser_view/common_tab_helper_delegate.h
index fcaa45b..e64dad53 100644
--- a/ios/chrome/browser/ui/browser_view/common_tab_helper_delegate.h
+++ b/ios/chrome/browser/ui/browser_view/common_tab_helper_delegate.h
@@ -19,14 +19,21 @@
 // This protocol is scaffolding for refactoring these delegate responsibilities
 // out of the BVC. The goal is to reduce the number of these delegate protocols
 // that the BVC conforms to to zero.
-@protocol CommonTabHelperDelegate <BubblePresenterDelegate,
-                                   CaptivePortalDetectorTabHelperDelegate,
-                                   ManageAccountsDelegate,
-                                   NetExportTabHelperDelegate,
-                                   NewTabPageTabHelperDelegate,
-                                   OverscrollActionsControllerDelegate,
-                                   PasswordControllerDelegate,
-                                   SnapshotGeneratorDelegate>
+@protocol CommonTabHelperDelegate <
+    BubblePresenterDelegate,
+    // TODO(crbug.com/1272473): Factor this out of the BVC.
+    CaptivePortalDetectorTabHelperDelegate,
+    // TODO(crbug.com/1272476): Factor this out of the BVC.
+    ManageAccountsDelegate,
+    // TODO(crbug.com/1272483): Factor this out of the BVC.
+    NetExportTabHelperDelegate,
+    // TODO(crbug.com/1173610): Factor this out of the BVC.
+    NewTabPageTabHelperDelegate,
+    OverscrollActionsControllerDelegate,
+    // TODO(crbug.com/1272487): Factor this out of the BVC.
+    PasswordControllerDelegate,
+    // TODO(crbug.com/1272491): Factor this out of the BVC.
+    SnapshotGeneratorDelegate>
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_BROWSER_VIEW_COMMON_TAB_HELPER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h
index c2888092..766106ea 100644
--- a/ios/chrome/browser/ui/commands/browser_commands.h
+++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -36,6 +36,8 @@
                            DefaultPromoCommands>
 
 // Closes the current tab.
+// TODO(crbug.com/1272498): Refactor this command away; call sites should close
+// via the WebStateList.
 - (void)closeCurrentTab;
 
 // Bookmarks the current page.
@@ -43,6 +45,7 @@
 - (void)bookmarkCurrentPage;
 
 // Adds a page to the reading list using data in |command|.
+// TODO(crbug.com/1272540): Remove this command.
 - (void)addToReadingList:(ReadingListAddCommand*)command;
 
 // Shows an IPH pointing to where the Reading List entry point is, if
@@ -67,6 +70,8 @@
 // Shows the dialog for sending the current tab between a user's devices.
 - (void)showSendTabToSelfUI;
 
+// TODO(crbug.com/1272497): Move requestDesktopSite and requestMobileSite to the
+// WebNavigationBrowserAgent, eliminating them as commands.
 // Requests the "desktop" version of the current page in the active tab.
 - (void)requestDesktopSite;
 
diff --git a/ios/chrome/browser/ui/first_run/first_run_egtest.mm b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
index 58446dd..38eb976 100644
--- a/ios/chrome/browser/ui/first_run/first_run_egtest.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
@@ -261,8 +261,9 @@
   [self scrollToElementAndAssertVisibility:GetAcceptButton()];
 }
 
+// TODO(crbug.com/1272857): Adapt this test to the sign-in & sync UI.
 // Checks that the Sign In screen is displayed correctly.
-- (void)testSignInScreenUI {
+- (void)DISABLED_testSignInScreenUI {
   [self verifyWelcomeScreenIsDisplayed];
 
   // Go to the sign-in screen.
@@ -359,8 +360,9 @@
                                      kSigninSyncScreenAccessibilityIdentifier)];
 }
 
+// TODO(crbug.com/1272857): Adapt this test to the sign-in & sync UI.
 // Checks that the default browser screen is displayed correctly.
-- (void)testDefaultBrowserScreenUI {
+- (void)DISABLED_testDefaultBrowserScreenUI {
   if ([self isDefaultBrowserTestDisabled]) {
     return;
   }
@@ -503,10 +505,11 @@
   [self verifyFREIsDismissed];
 }
 
+// TODO(crbug.com/1272857): Adapt this test to the sign-in & sync UI.
 // Checks that when opening the app no accounts are here and the primary button
 // allows to create a new account and that it is updated if a new account is
 // added.
-- (void)testSignInNoAccount {
+- (void)DISABLED_testSignInNoAccount {
   [self scrollToElementAndAssertVisibility:GetAcceptButton()];
   [[EarlGrey selectElementWithMatcher:GetAcceptButton()]
       performAction:grey_tap()];
@@ -543,10 +546,11 @@
       assertWithMatcher:grey_nil()];
 }
 
+// TODO(crbug.com/1272857): Adapt this test to the sign-in & sync UI.
 // Checks that it is possible to add an account even if there is already account
 // and that it is possible to switch accounts when multiple accounts are
 // present.
-- (void)testSignInSelectAccount {
+- (void)DISABLED_testSignInSelectAccount {
   FakeChromeIdentity* fakeIdentity1 = [SigninEarlGrey fakeIdentity1];
   FakeChromeIdentity* fakeIdentity2 = [SigninEarlGrey fakeIdentity2];
   [SigninEarlGrey addFakeIdentity:fakeIdentity1];
@@ -581,8 +585,9 @@
       assertWithMatcher:grey_sufficientlyVisible()];
 }
 
+// TODO(crbug.com/1272857): Adapt this test to the sign-in & sync UI.
 // Checks that pressing "No thanks" on SignIn screen doesn't sign in the user.
-- (void)testNoSignIn {
+- (void)DISABLED_testNoSignIn {
   FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1];
   [SigninEarlGrey addFakeIdentity:fakeIdentity];
 
diff --git a/ios/chrome/browser/ui/link_to_text/link_to_text_egtest.mm b/ios/chrome/browser/ui/link_to_text/link_to_text_egtest.mm
index 6510a73..c63b69e 100644
--- a/ios/chrome/browser/ui/link_to_text/link_to_text_egtest.mm
+++ b/ios/chrome/browser/ui/link_to_text/link_to_text_egtest.mm
@@ -8,8 +8,8 @@
 #import "base/strings/string_util.h"
 #import "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
+#import "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #import "components/shared_highlighting/core/common/text_fragment.h"
-#import "components/shared_highlighting/core/common/text_fragments_utils.h"
 #import "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_actions_app_interface.h"
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h
index 6f157d4..f4d714f7 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h
@@ -40,6 +40,8 @@
 // Called when an action has been triggered.
 // The action index holds the current triggered action which are numbered left
 // to right.
+// TODO(crbug.com/1272486) : Separate action handling for overscroll from UI
+// management.
 - (void)overscrollActionsController:(OverscrollActionsController*)controller
                    didTriggerAction:(OverscrollAction)action;
 // Should return true when the delegate wants to enable the overscroll actions.
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 4c2dc09..43e3da810 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -264,7 +264,6 @@
     "//ios/chrome/browser/web/session_state",
     "//ios/chrome/browser/web/web_performance_metrics",
     "//ios/components/security_interstitials",
-    "//ios/components/security_interstitials/legacy_tls",
     "//ios/components/security_interstitials/lookalikes",
     "//ios/components/webui:url_constants",
     "//ios/net",
@@ -338,7 +337,6 @@
     "//ios/chrome/browser/web",
     "//ios/chrome/test/fakes",
     "//ios/components/security_interstitials",
-    "//ios/components/security_interstitials/legacy_tls",
     "//ios/components/security_interstitials/lookalikes",
     "//ios/net",
     "//ios/web/common:features",
@@ -429,7 +427,6 @@
     "forms_egtest.mm",
     "http_auth_egtest.mm",
     "js_print_egtest.mm",
-    "legacy_tls_egtest.mm",
     "lookalike_url_egtest.mm",
     "navigation_egtest.mm",
     "progress_indicator_egtest.mm",
diff --git a/ios/chrome/browser/web/chrome_web_client.h b/ios/chrome/browser/web/chrome_web_client.h
index 6762b5c9..71bc6f1 100644
--- a/ios/chrome/browser/web/chrome_web_client.h
+++ b/ios/chrome/browser/web/chrome_web_client.h
@@ -42,8 +42,6 @@
       web::BrowserState* browser_state) const override;
   NSString* GetDocumentStartScriptForMainFrame(
       web::BrowserState* browser_state) const override;
-  bool IsLegacyTLSAllowedForHost(web::WebState* web_state,
-                                 const std::string& hostname) override;
   void PrepareErrorPage(web::WebState* web_state,
                         const GURL& url,
                         NSError* error,
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index 08e67bf..f5ad86d 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -54,9 +54,6 @@
 #import "ios/chrome/browser/web/session_state/web_session_state_tab_helper.h"
 #import "ios/chrome/browser/web/web_performance_metrics/web_performance_metrics_java_script_feature.h"
 #import "ios/components/security_interstitials/ios_blocking_page_tab_helper.h"
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.h"
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.h"
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_blocking_page.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_container.h"
 #import "ios/components/security_interstitials/lookalikes/lookalike_url_controller_client.h"
@@ -153,34 +150,6 @@
   return base::SysUTF8ToNSString(error_page_content);
 }
 
-// Returns the legacy TLS error page HTML.
-NSString* GetLegacyTLSErrorPageHTML(web::WebState* web_state,
-                                    int64_t navigation_id) {
-  std::string error_page_content;
-  security_interstitials::IOSBlockingPageTabHelper* blocking_page_tab_helper =
-      security_interstitials::IOSBlockingPageTabHelper::FromWebState(web_state);
-
-  // WebStates that are not in the WebStateList (e.g., WebStates used for
-  // reading list sync) do not have an IOSBlockingPageTabHelper. Since such
-  // WebStates are not used for displaying web contents to a user, it is not
-  // necessary to produce an actual error page, and instead an empty string is
-  // used.
-  if (blocking_page_tab_helper) {
-    // Construct the blocking page and associate it with the WebState.
-    std::unique_ptr<security_interstitials::IOSSecurityInterstitialPage> page =
-        std::make_unique<LegacyTLSBlockingPage>(
-            web_state, web_state->GetVisibleURL() /*request_url*/,
-            std::make_unique<LegacyTLSControllerClient>(
-                web_state, web_state->GetVisibleURL(),
-                GetApplicationContext()->GetApplicationLocale()));
-    error_page_content = page->GetHtmlContents();
-    blocking_page_tab_helper->AssociateBlockingPage(navigation_id,
-                                                    std::move(page));
-  }
-
-  return base::SysUTF8ToNSString(error_page_content);
-}
-
 // Returns a version string that matches the current version number except that
 // the major version is 100.
 const std::string& GetM100VersionNumber() {
@@ -352,14 +321,6 @@
   return [scripts componentsJoinedByString:@";"];
 }
 
-bool ChromeWebClient::IsLegacyTLSAllowedForHost(web::WebState* web_state,
-                                                const std::string& hostname) {
-  auto* allowlist = LegacyTLSTabAllowList::FromWebState(web_state);
-  if (!allowlist)
-    return false;
-  return allowlist->IsDomainAllowed(hostname);
-}
-
 void ChromeWebClient::PrepareErrorPage(
     web::WebState* web_state,
     const GURL& url,
@@ -402,10 +363,6 @@
     DCHECK_EQ(kLookalikeUrlErrorCode, final_underlying_error.code);
     std::move(error_html_callback)
         .Run(GetLookalikeUrlErrorPageHtml(web_state, navigation_id));
-  } else if ([final_underlying_error.domain isEqual:net::kNSErrorDomain] &&
-             final_underlying_error.code == net::ERR_SSL_OBSOLETE_VERSION) {
-    std::move(error_html_callback)
-        .Run(GetLegacyTLSErrorPageHTML(web_state, navigation_id));
   } else if (info.has_value()) {
     base::OnceCallback<void(NSString*)> blocking_page_callback =
         base::BindOnce(^(NSString* blocking_page_html) {
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm
index d3f2f7f..2191175 100644
--- a/ios/chrome/browser/web/chrome_web_client_unittest.mm
+++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -484,72 +484,6 @@
       << base::SysNSStringToUTF8(page);
 }
 
-// Tests PrepareErrorPage for a legacy TLS error, which results in a
-// committed legacy TLS interstitial.
-TEST_F(ChromeWebClientTest, PrepareErrorPageForLegacyTLSError) {
-  web::FakeWebState web_state;
-  web_state.SetBrowserState(browser_state());
-  security_interstitials::IOSBlockingPageTabHelper::CreateForWebState(
-      &web_state);
-  auto navigation_manager = std::make_unique<web::FakeNavigationManager>();
-  web_state.SetNavigationManager(std::move(navigation_manager));
-
-  NSError* error = [NSError errorWithDomain:net::kNSErrorDomain
-                                       code:net::ERR_SSL_OBSOLETE_VERSION
-                                   userInfo:nil];
-  __block bool callback_called = false;
-  __block NSString* page = nil;
-  base::OnceCallback<void(NSString*)> callback =
-      base::BindOnce(^(NSString* error_html) {
-        callback_called = true;
-        page = error_html;
-      });
-
-  ChromeWebClient web_client;
-  web_client.PrepareErrorPage(&web_state, GURL(kTestUrl), error,
-                              /*is_post=*/false,
-                              /*is_off_the_record=*/false,
-                              /*info=*/absl::optional<net::SSLInfo>(),
-                              /*navigation_id=*/0, std::move(callback));
-
-  EXPECT_TRUE(callback_called);
-  NSString* error_string =
-      l10n_util::GetNSString(IDS_LEGACY_TLS_PRIMARY_PARAGRAPH);
-  EXPECT_TRUE([page containsString:error_string])
-      << base::SysNSStringToUTF8(page);
-}
-
-// Tests PrepareErrorPage for a legacy TLS error in a WebState that doesn't
-// have an IOSBlockingPageTabHelper, ensuring that there is no crash.
-TEST_F(ChromeWebClientTest,
-       PrepareErrorPageForLegacyTLSErrorNotInWebStateList) {
-  web::FakeWebState web_state;
-  web_state.SetBrowserState(browser_state());
-  auto navigation_manager = std::make_unique<web::FakeNavigationManager>();
-  web_state.SetNavigationManager(std::move(navigation_manager));
-
-  NSError* error = [NSError errorWithDomain:net::kNSErrorDomain
-                                       code:net::ERR_SSL_OBSOLETE_VERSION
-                                   userInfo:nil];
-  __block bool callback_called = false;
-  __block NSString* page = nil;
-  base::OnceCallback<void(NSString*)> callback =
-      base::BindOnce(^(NSString* error_html) {
-        callback_called = true;
-        page = error_html;
-      });
-
-  ChromeWebClient web_client;
-  web_client.PrepareErrorPage(&web_state, GURL(kTestUrl), error,
-                              /*is_post=*/false,
-                              /*is_off_the_record=*/false,
-                              /*info=*/absl::optional<net::SSLInfo>(),
-                              /*navigation_id=*/0, std::move(callback));
-
-  EXPECT_TRUE(callback_called);
-  EXPECT_EQ(page.length, 0u);
-}
-
 // Tests the default user agent for different views.
 TEST_F(ChromeWebClientTest, DefaultUserAgent) {
   base::test::ScopedFeatureList scoped_feature_list;
diff --git a/ios/chrome/browser/web/legacy_tls_egtest.mm b/ios/chrome/browser/web/legacy_tls_egtest.mm
deleted file mode 100644
index 50d06b3..0000000
--- a/ios/chrome/browser/web/legacy_tls_egtest.mm
+++ /dev/null
@@ -1,165 +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.
-
-#include "base/ios/ios_util.h"
-#include "components/strings/grit/components_strings.h"
-#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/testing/earl_grey/earl_grey_test.h"
-#include "ios/testing/embedded_test_server_handlers.h"
-#include "ios/web/common/features.h"
-#include "net/ssl/ssl_config.h"
-#include "net/ssl/ssl_server_config.h"
-#include "net/test/embedded_test_server/default_handlers.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface LegacyTLSTestCase : ChromeTestCase {
-  // A test server that connects via TLS 1.0.
-  std::unique_ptr<net::test_server::EmbeddedTestServer> _legacyTLSServer;
-  // A URL for the legacy TLS test server, which should trigger legacy TLS
-  // interstitials.
-  GURL _legacyTLSURL;
-  // A URL for the normal test server.
-  GURL _safeURL;
-  // Text that is found on the legacy TLS interstitial.
-  std::string _interstitialContent;
-  // Text that is found on |_legacyTLSURL| if the user clicks through.
-  std::string _unsafeContent;
-  // Text that is found on |_safeURL|.
-  std::string _safeContent;
-}
-
-@end
-
-@implementation LegacyTLSTestCase
-
-- (AppLaunchConfiguration)appConfigurationForTestCase {
-  AppLaunchConfiguration config;
-  config.features_enabled.push_back(web::features::kIOSLegacyTLSInterstitial);
-  config.relaunch_policy = NoForceRelaunchAndResetState;
-  return config;
-}
-
-- (void)setUp {
-  [super setUp];
-
-  // Setup server that will negotiate TLS 1.0.
-  _legacyTLSServer = std::make_unique<net::test_server::EmbeddedTestServer>(
-      net::test_server::EmbeddedTestServer::TYPE_HTTPS);
-  net::SSLServerConfig ssl_config;
-  ssl_config.version_min = net::SSL_PROTOCOL_VERSION_TLS1;
-  ssl_config.version_max = net::SSL_PROTOCOL_VERSION_TLS1;
-  _legacyTLSServer->SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
-  RegisterDefaultHandlers(_legacyTLSServer.get());
-  GREYAssertTrue(_legacyTLSServer->Start(),
-                 @"Legacy TLS test server failed to start.");
-
-  _legacyTLSURL = _legacyTLSServer->GetURL("/");
-  _interstitialContent =
-      l10n_util::GetStringUTF8(IDS_LEGACY_TLS_PRIMARY_PARAGRAPH);
-  // The legacy TLS server will cause self-signed cert warnings after we click
-  // through the legacy TLS interstitial, so pull the heading string for that
-  // to match on.
-  _unsafeContent = l10n_util::GetStringUTF8(IDS_SSL_V2_HEADING);
-
-  RegisterDefaultHandlers(self.testServer);
-  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
-  _safeURL = self.testServer->GetURL("/defaultresponse");
-  _safeContent = "Default response";
-}
-
-// The remaining tests in this file are only relevant for iOS 14 or later.
-
-// Test that loading a page from a server over TLS 1.0 causes the legacy TLS
-// interstitial to show.
-- (void)testLegacyTLSShowsInterstitial {
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_interstitialContent];
-}
-
-// Test that going back to safety returns the user to the previous page.
-- (void)testLegacyTLSInterstitialBackToSafety {
-  // Load a benign page first.
-  [ChromeEarlGrey loadURL:_safeURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
-
-  // Trigger the legacy TLS interstitial.
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_interstitialContent];
-
-  // Tap on the "Back to safety" button and verify that we navigate back to the
-  // previous page.
-  [ChromeEarlGrey tapWebStateElementWithID:@"primary-button"];
-  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
-}
-
-// Test that clicking through the interstitial works.
-- (void)testLegacyTLSInterstitialProceed {
-  // Load a benign page first.
-  [ChromeEarlGrey loadURL:_safeURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
-
-  // Trigger the legacy TLS interstitial.
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_interstitialContent];
-
-  // Tap on the "Proceed" link and verify that we go to the unsafe page (in this
-  // case, a cert error interstitial for the test server's self-signed cert).
-  [ChromeEarlGrey tapWebStateElementWithID:@"details-button"];
-  [ChromeEarlGrey tapWebStateElementWithID:@"proceed-link"];
-  [ChromeEarlGrey waitForWebStateContainingText:_unsafeContent];
-}
-
-// Test that clicking through the interstitial is remembered on a reload, and
-// we don't show the interstitial again.
-- (void)testLegacyTLSInterstitialAllowlist {
-  // Trigger the legacy TLS interstitial.
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_interstitialContent];
-
-  // Tap on the "Proceed" link and verify that we go to the unsafe page.
-  [ChromeEarlGrey tapWebStateElementWithID:@"details-button"];
-  [ChromeEarlGrey tapWebStateElementWithID:@"proceed-link"];
-  [ChromeEarlGrey waitForWebStateContainingText:_unsafeContent];
-
-  // Navigate away to another page.
-  [ChromeEarlGrey loadURL:_safeURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
-
-  // Navigate to the legacy TLS page again. Legacy TLS interstitial should not
-  // be shown.
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_unsafeContent];
-}
-
-// Test that the allowlist is cleared after session restart and that we show the
-// legacy TLS interstitial again.
-- (void)testLegacyTLSInterstitialAllowlistClearedOnRestart {
-  // Trigger the legacy TLS interstitial.
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_interstitialContent];
-
-  // Tap on the "Proceed" link and verify that we go to the unsafe page.
-  [ChromeEarlGrey tapWebStateElementWithID:@"details-button"];
-  [ChromeEarlGrey tapWebStateElementWithID:@"proceed-link"];
-  [ChromeEarlGrey waitForWebStateContainingText:_unsafeContent];
-
-  // Navigate away to another page.
-  [ChromeEarlGrey loadURL:_safeURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
-
-  // Do a session restoration.
-  [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo];
-  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
-
-  // Navigate to the legacy TLS page again. The interstitial should trigger.
-  [ChromeEarlGrey loadURL:_legacyTLSURL];
-  [ChromeEarlGrey waitForWebStateContainingText:_interstitialContent];
-}
-
-@end
diff --git a/ios/chrome/common/ui/promo_style/promo_style_view_controller.h b/ios/chrome/common/ui/promo_style/promo_style_view_controller.h
index 85c8871..7d42b785 100644
--- a/ios/chrome/common/ui/promo_style/promo_style_view_controller.h
+++ b/ios/chrome/common/ui/promo_style/promo_style_view_controller.h
@@ -34,12 +34,6 @@
 // should add their UI elements to it.
 @property(nonatomic, strong) UIView* specificContentView;
 
-// The container view for the specific content at the top of the screen that
-// sits between the title and the subtile. The view is lazily instantiated and
-// added to the view tree when read for the first time. Derived view
-// controllers can add their UI elements to it.
-@property(nonatomic, strong, readonly) UIView* topSpecificContentView;
-
 // The text for the primary action. Must be set before the view is loaded.
 @property(nonatomic, copy) NSString* primaryActionString;
 
diff --git a/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm b/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
index f3bf5d3..0229992 100644
--- a/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
+++ b/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
@@ -56,11 +56,6 @@
 // layout reflects the latest updates.
 @property(nonatomic, assign) BOOL canUpdateViewsOnScroll;
 
-// Redefinition to allow write. The property should only be read when
-// -hasTopSpecificContentView returns YES to not create the view when reading
-// it. The view should only be lazily instanciated when read externally.
-@property(nonatomic, strong, readwrite) UIView* topSpecificContentView;
-
 @end
 
 @implementation PromoStyleViewController
@@ -89,9 +84,6 @@
   self.scrollContentView.translatesAutoresizingMaskIntoConstraints = NO;
   [self.scrollContentView addSubview:self.imageView];
   [self.scrollContentView addSubview:self.titleLabel];
-  if ([self hasTopSpecificContentView]) {
-    [self.scrollContentView addSubview:self.topSpecificContentView];
-  }
   [self.scrollContentView addSubview:self.subtitleLabel];
   [self.view addLayoutGuide:subtitleMarginLayoutGuide];
   [self.scrollContentView addSubview:self.specificContentView];
@@ -134,25 +126,6 @@
           ? 0
           : kActionsBottomMargin;
 
-  NSLayoutConstraint* subtitleLabelTopConstraint = [self.subtitleLabel.topAnchor
-      constraintEqualToAnchor:self.titleLabel.bottomAnchor
-                     constant:kDefaultMargin];
-  if ([self hasTopSpecificContentView]) {
-    // When set, put the |topSpecificContentView| view between the title and
-    // subtitle labels.
-    [NSLayoutConstraint activateConstraints:@[
-      [self.topSpecificContentView.topAnchor
-          constraintEqualToAnchor:self.titleLabel.bottomAnchor],
-      [self.topSpecificContentView.centerXAnchor
-          constraintEqualToAnchor:self.scrollContentView.centerXAnchor],
-      [self.topSpecificContentView.widthAnchor
-          constraintLessThanOrEqualToAnchor:self.scrollContentView.widthAnchor],
-    ]];
-    subtitleLabelTopConstraint = [self.subtitleLabel.topAnchor
-        constraintEqualToAnchor:self.topSpecificContentView.bottomAnchor];
-  }
-  subtitleLabelTopConstraint.active = YES;
-
   [NSLayoutConstraint activateConstraints:@[
     // Content width layout guide constraints. Constrain the width to both at
     // least 65% of the view width, and to the full view width with margins.
@@ -222,6 +195,9 @@
     [self.titleLabel.widthAnchor
         constraintLessThanOrEqualToAnchor:self.scrollContentView.widthAnchor
                                  constant:-2 * kTitleHorizontalMargin],
+    [self.subtitleLabel.topAnchor
+        constraintEqualToAnchor:self.titleLabel.bottomAnchor
+                       constant:kDefaultMargin],
     [self.subtitleLabel.centerXAnchor
         constraintEqualToAnchor:self.scrollContentView.centerXAnchor],
     [self.subtitleLabel.widthAnchor
@@ -493,14 +469,6 @@
   return _specificContentView;
 }
 
-- (UIView*)topSpecificContentView {
-  if (!_topSpecificContentView) {
-    _topSpecificContentView = [[UIView alloc] init];
-    _topSpecificContentView.translatesAutoresizingMaskIntoConstraints = NO;
-  }
-  return _topSpecificContentView;
-}
-
 - (UIButton*)primaryActionButton {
   if (!_primaryActionButton) {
     _primaryActionButton = [[HighlightedButton alloc] initWithFrame:CGRectZero];
@@ -759,11 +727,6 @@
          traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular;
 }
 
-// Returns YES if |_topSpecificContentView| is instantiated.
-- (BOOL)hasTopSpecificContentView {
-  return _topSpecificContentView != nil;
-}
-
 #pragma mark - UIScrollViewDelegate
 
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
diff --git a/ios/components/security_interstitials/legacy_tls/BUILD.gn b/ios/components/security_interstitials/legacy_tls/BUILD.gn
deleted file mode 100644
index b6c6233..0000000
--- a/ios/components/security_interstitials/legacy_tls/BUILD.gn
+++ /dev/null
@@ -1,24 +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.
-
-source_set("legacy_tls") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "legacy_tls_blocking_page.h",
-    "legacy_tls_blocking_page.mm",
-    "legacy_tls_controller_client.h",
-    "legacy_tls_controller_client.mm",
-    "legacy_tls_tab_allow_list.h",
-    "legacy_tls_tab_allow_list.mm",
-  ]
-  deps = [
-    "//base",
-    "//components/security_interstitials/core",
-    "//components/strings:components_strings_grit",
-    "//ios/components/security_interstitials",
-    "//ios/web/public",
-    "//net",
-    "//ui/base",
-  ]
-}
diff --git a/ios/components/security_interstitials/legacy_tls/DEPS b/ios/components/security_interstitials/legacy_tls/DEPS
deleted file mode 100644
index e972e39..0000000
--- a/ios/components/security_interstitials/legacy_tls/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+ios/net",
-  "+net/base",
-]
diff --git a/ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.h b/ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.h
deleted file mode 100644
index d8395b6..0000000
--- a/ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.h
+++ /dev/null
@@ -1,45 +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 IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_BLOCKING_PAGE_H_
-#define IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_BLOCKING_PAGE_H_
-
-#include "ios/components/security_interstitials/ios_security_interstitial_page.h"
-#include "ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.h"
-
-class GURL;
-
-// This class is responsible for showing/hiding the interstitial page that is
-// shown for legacy TLS connections.
-class LegacyTLSBlockingPage
-    : public security_interstitials::IOSSecurityInterstitialPage {
- public:
-  LegacyTLSBlockingPage(const LegacyTLSBlockingPage&) = delete;
-  LegacyTLSBlockingPage& operator=(const LegacyTLSBlockingPage&) = delete;
-
-  ~LegacyTLSBlockingPage() override;
-
-  // Creates a legacy TLS blocking page.
-  LegacyTLSBlockingPage(web::WebState* web_state,
-                        const GURL& request_url,
-                        std::unique_ptr<LegacyTLSControllerClient> client);
-
- protected:
-  // SecurityInterstitialPage implementation:
-  bool ShouldCreateNewNavigation() const override;
-  void PopulateInterstitialStrings(base::Value* load_time_data) const override;
-
- private:
-  void HandleCommand(
-      security_interstitials::SecurityInterstitialCommand command,
-      const GURL& origin_url,
-      bool user_is_interacting,
-      web::WebFrame* sender_frame) override;
-
-  web::WebState* web_state_ = nullptr;
-  const GURL request_url_;
-  std::unique_ptr<LegacyTLSControllerClient> controller_;
-};
-
-#endif  // IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_BLOCKING_PAGE_H_
diff --git a/ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.mm b/ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.mm
deleted file mode 100644
index 823984c1..0000000
--- a/ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.mm
+++ /dev/null
@@ -1,78 +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.
-
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_blocking_page.h"
-
-#include <utility>
-
-#include "base/strings/string_number_conversions.h"
-#include "base/values.h"
-#include "components/security_interstitials/core/common_string_util.h"
-#include "components/security_interstitials/core/metrics_helper.h"
-#include "ios/components/security_interstitials/ios_blocking_page_controller_client.h"
-#include "ios/components/security_interstitials/ios_blocking_page_metrics_helper.h"
-#include "net/base/net_errors.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-LegacyTLSBlockingPage::LegacyTLSBlockingPage(
-    web::WebState* web_state,
-    const GURL& request_url,
-    std::unique_ptr<LegacyTLSControllerClient> client)
-    : security_interstitials::IOSSecurityInterstitialPage(web_state,
-                                                          request_url,
-                                                          client.get()),
-      web_state_(web_state),
-      request_url_(request_url),
-      controller_(std::move(client)) {
-  DCHECK(web_state_);
-
-  // Creating an interstitial without showing it (e.g. from
-  // chrome://interstitials) leaks memory, so don't create it here.
-}
-
-LegacyTLSBlockingPage::~LegacyTLSBlockingPage() = default;
-
-bool LegacyTLSBlockingPage::ShouldCreateNewNavigation() const {
-  return true;
-}
-
-void LegacyTLSBlockingPage::PopulateInterstitialStrings(
-    base::Value* load_time_data) const {
-  CHECK(load_time_data);
-
-  // Shared with SSL errors.
-  security_interstitials::common_string_util::PopulateSSLLayoutStrings(
-      net::ERR_SSL_OBSOLETE_VERSION, load_time_data);
-
-  load_time_data->SetBoolKey("overridable", true);
-  load_time_data->SetBoolKey("hide_primary_button", false);
-  load_time_data->SetBoolKey("bad_clock", false);
-  load_time_data->SetStringKey("type", "LEGACY_TLS");
-
-  const std::u16string hostname(
-      security_interstitials::common_string_util::GetFormattedHostName(
-          request_url_));
-  security_interstitials::common_string_util::PopulateLegacyTLSStrings(
-      load_time_data, hostname);
-}
-
-void LegacyTLSBlockingPage::HandleCommand(
-    security_interstitials::SecurityInterstitialCommand command,
-    const GURL& origin_url,
-    bool user_is_interacting,
-    web::WebFrame* sender_frame) {
-  if (command == security_interstitials::CMD_DONT_PROCEED) {
-    controller_->metrics_helper()->RecordUserDecision(
-        security_interstitials::MetricsHelper::DONT_PROCEED);
-    controller_->GoBack();
-  } else if (command == security_interstitials::CMD_PROCEED) {
-    controller_->metrics_helper()->RecordUserDecision(
-        security_interstitials::MetricsHelper::PROCEED);
-    controller_->Proceed();
-  }
-}
diff --git a/ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.h b/ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.h
deleted file mode 100644
index bb9955e0..0000000
--- a/ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.h
+++ /dev/null
@@ -1,34 +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 IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_CONTROLLER_CLIENT_H_
-#define IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_CONTROLLER_CLIENT_H_
-
-#include "ios/components/security_interstitials/ios_blocking_page_controller_client.h"
-#include "url/gurl.h"
-
-class GURL;
-
-namespace web {
-class WebState;
-}  // namespace web
-
-// Controller client used for legacy TLS blocking pages.
-class LegacyTLSControllerClient
-    : public security_interstitials::IOSBlockingPageControllerClient {
- public:
-  LegacyTLSControllerClient(web::WebState* web_state,
-                            const GURL& request_url,
-                            const std::string& app_locale);
-  ~LegacyTLSControllerClient() override;
-
-  // security_interstitials::ControllerClient:
-  void Proceed() override;
-
- private:
-  // The URL of the page causing the insterstitial.
-  const GURL request_url_;
-};
-
-#endif  // IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_CONTROLLER_CLIENT_H_
diff --git a/ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.mm b/ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.mm
deleted file mode 100644
index bd69afd..0000000
--- a/ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.mm
+++ /dev/null
@@ -1,43 +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.
-
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_controller_client.h"
-
-#include "components/security_interstitials/core/metrics_helper.h"
-#include "ios/components/security_interstitials/ios_blocking_page_metrics_helper.h"
-#include "ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h"
-#import "ios/web/public/web_state.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-// Creates a metrics helper for |url|.
-std::unique_ptr<security_interstitials::IOSBlockingPageMetricsHelper>
-CreateMetricsHelper(web::WebState* web_state, const GURL& url) {
-  security_interstitials::MetricsHelper::ReportDetails reporting_info;
-  reporting_info.metric_prefix = "legacy_tls";
-  return std::make_unique<security_interstitials::IOSBlockingPageMetricsHelper>(
-      web_state, url, reporting_info);
-}
-}  // namespace
-
-LegacyTLSControllerClient::LegacyTLSControllerClient(
-    web::WebState* web_state,
-    const GURL& request_url,
-    const std::string& app_locale)
-    : IOSBlockingPageControllerClient(
-          web_state,
-          CreateMetricsHelper(web_state, request_url),
-          app_locale),
-      request_url_(request_url) {}
-
-LegacyTLSControllerClient::~LegacyTLSControllerClient() {}
-
-void LegacyTLSControllerClient::Proceed() {
-  LegacyTLSTabAllowList::FromWebState(web_state())
-      ->AllowDomain(request_url_.host());
-  Reload();
-}
diff --git a/ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h b/ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h
deleted file mode 100644
index 88c47978..0000000
--- a/ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h
+++ /dev/null
@@ -1,38 +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 IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_TAB_ALLOW_LIST_H_
-#define IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_TAB_ALLOW_LIST_H_
-
-#include <set>
-#include <string>
-
-#import "ios/web/public/web_state_user_data.h"
-
-// LegacyTLSTabAllowList tracks the allowlist decisions for legacy TLS hosts.
-// Decisions are scoped to the domain.
-class LegacyTLSTabAllowList
-    : public web::WebStateUserData<LegacyTLSTabAllowList> {
- public:
-  // LegacyTLSTabAllowList is move-only.
-  LegacyTLSTabAllowList(LegacyTLSTabAllowList&& other);
-  LegacyTLSTabAllowList& operator=(LegacyTLSTabAllowList&& other);
-  ~LegacyTLSTabAllowList() override;
-
-  // Returns whether |domain| has been allowlisted.
-  bool IsDomainAllowed(const std::string& domain) const;
-
-  // Allows future navigations to |domain|.
-  void AllowDomain(const std::string& domain);
-
- private:
-  explicit LegacyTLSTabAllowList(web::WebState* web_state);
-  friend class web::WebStateUserData<LegacyTLSTabAllowList>;
-  WEB_STATE_USER_DATA_KEY_DECL();
-
-  // Set of allowlisted domains.
-  std::set<std::string> allowed_domains_;
-};
-
-#endif  // IOS_COMPONENTS_SECURITY_INTERSTITIALS_LEGACY_TLS_LEGACY_TLS_TAB_ALLOW_LIST_H_
diff --git a/ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.mm b/ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.mm
deleted file mode 100644
index 55b78fe8..0000000
--- a/ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.mm
+++ /dev/null
@@ -1,31 +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.
-
-#import "ios/components/security_interstitials/legacy_tls/legacy_tls_tab_allow_list.h"
-
-#import "ios/web/public/web_state.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-WEB_STATE_USER_DATA_KEY_IMPL(LegacyTLSTabAllowList)
-
-LegacyTLSTabAllowList::LegacyTLSTabAllowList(web::WebState* web_state) {}
-
-LegacyTLSTabAllowList::LegacyTLSTabAllowList(LegacyTLSTabAllowList&& other) =
-    default;
-
-LegacyTLSTabAllowList& LegacyTLSTabAllowList::operator=(
-    LegacyTLSTabAllowList&& other) = default;
-
-LegacyTLSTabAllowList::~LegacyTLSTabAllowList() = default;
-
-bool LegacyTLSTabAllowList::IsDomainAllowed(const std::string& domain) const {
-  return allowed_domains_.find(domain) != allowed_domains_.end();
-}
-
-void LegacyTLSTabAllowList::AllowDomain(const std::string& domain) {
-  allowed_domains_.insert(domain);
-}
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index a7575e8..be10747 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-427c387d0ac06df49291ba6940297407ab95a99b
\ No newline at end of file
+e3d3f14657fe1a26bf1295de0bda71515a76769c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 19cb7fb..e3a71f7 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-57b0ae9c0d7f939a78ee3624e9eef8f423b957ef
\ No newline at end of file
+d1cc36e1b90b1cde38f36f2edf93881abe2c2a74
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index c6e27660..bc61863 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-fdac7bdb87c95cb5593f627b8ab3dc2c3ed12248
\ No newline at end of file
+5959a252bcc78f5f90f84b45b6b4af784c48550b
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 81c41de..f06853ba 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-9a40ef885221158dc78fbed59aa1cf313f5f7dbf
\ No newline at end of file
+efb825fdaef896bdbb7d79475759b37cb897a34d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 0dfab268..6e7d88b 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-894b44b2434abdc06bc537e7780561d070d5ceb8
\ No newline at end of file
+ddd712d5f097395ee782da46aadc037c72e06d13
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 48631acb..9432535f 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-2568a09ddce5eeaf7ea09ba8f3808f73f0270efa
\ No newline at end of file
+fcbc8b1f8f53cc8164044bf9aeaf559d23c91b74
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 99ff9ac..e7994dee 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ef08127a8425f3d23b16cec28b33e7783ff1009d
\ No newline at end of file
+b0695c48a11d507317aa86edb71af74576e2206c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index a6924084..c3d869f9 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-cce7713ac8f52cc30b4306e7e6e35c029496f4bc
\ No newline at end of file
+a9a51c2f69d4d2864cce25a546a293796a1022c0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 72ca18ed..74065eae3 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-e0307feb92ad91f5aa02e190525740d11887c007
\ No newline at end of file
+54abd9d6252aa2c29ee70417db193067da5269af
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 609e605..3bbd2aa0 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-f546874447dd76d4d265965392e2faab1dae3b38
\ No newline at end of file
+ee0e941ef6b8f119ff2fa7fe0979427127ac4fd3
\ No newline at end of file
diff --git a/ios/web/common/features.h b/ios/web/common/features.h
index f7cc64a..3d7cd73c 100644
--- a/ios/web/common/features.h
+++ b/ios/web/common/features.h
@@ -44,9 +44,6 @@
 // of properties using hard coded logic.
 extern const base::Feature kPreserveScrollViewProperties;
 
-// When enabled, display an interstitial on legacy TLS connections.
-extern const base::Feature kIOSLegacyTLSInterstitial;
-
 // Records snapshot size of image (IOS.Snapshots.ImageSize histogram) and PDF
 // (IOS.Snapshots.PDFSize histogram) if enabled. Enabling this flag will
 // generate PDF when Page Snapshot is taken just to record PDF size.
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm
index 8da5edb..b879bc773 100644
--- a/ios/web/common/features.mm
+++ b/ios/web/common/features.mm
@@ -37,9 +37,6 @@
 const base::Feature kPreserveScrollViewProperties{
     "PreserveScrollViewProperties", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kIOSLegacyTLSInterstitial{"IOSLegacyTLSInterstitial",
-                                              base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kRecordSnapshotSize{"RecordSnapshotSize",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 4ea194f..4cbd82c 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -1025,25 +1025,15 @@
   DCHECK(challenge);
   DCHECK(decisionHandler);
 
-  // If the legacy TLS interstitial is not enabled, don't cause errors. The
-  // interstitial is also dependent on committed interstitials being enabled.
-  if (!base::FeatureList::IsEnabled(web::features::kIOSLegacyTLSInterstitial)) {
-    decisionHandler(YES);
-    return;
-  }
-
-  if (web::GetWebClient()->IsLegacyTLSAllowedForHost(
-          self.webStateImpl,
-          base::SysNSStringToUTF8(challenge.protectionSpace.host))) {
-    decisionHandler(YES);
-    return;
-  }
-
+  // TLS 1.0/1.1 is no longer supported in Chrome. When a connection occurs that
+  // uses deprecated TLS versions, reject it. For navigations (which are user
+  // visible), cancel the navigation and set the error code to
+  // ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
   if (self.pendingNavigationInfo) {
     self.pendingNavigationInfo.cancelled = YES;
     self.pendingNavigationInfo.cancellationError =
         [NSError errorWithDomain:net::kNSErrorDomain
-                            code:net::ERR_SSL_OBSOLETE_VERSION
+                            code:net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH
                         userInfo:nil];
   }
   decisionHandler(NO);
diff --git a/ios/web/public/web_client.h b/ios/web/public/web_client.h
index cc41c328..f4d6c795 100644
--- a/ios/web/public/web_client.h
+++ b/ios/web/public/web_client.h
@@ -143,12 +143,6 @@
       WebState* web_state,
       mojo::GenericPendingReceiver receiver) {}
 
-  // Allows the embedder to specify legacy TLS enforcement on a per-host basis,
-  // for example to allow users to bypass interstitial warnings on affected
-  // hosts.
-  virtual bool IsLegacyTLSAllowedForHost(WebState* web_state,
-                                         const std::string& hostname);
-
   // Calls the given |callback| with the contents of an error page to display
   // when a navigation error occurs. |error| is always a valid pointer. The
   // string passed to |callback| will be nil if no error page should be
diff --git a/ios/web/text_fragments/text_fragments_manager_impl.mm b/ios/web/text_fragments/text_fragments_manager_impl.mm
index 21d9462..2a8e934 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl.mm
+++ b/ios/web/text_fragments/text_fragments_manager_impl.mm
@@ -8,9 +8,9 @@
 
 #import "base/strings/string_util.h"
 #import "base/strings/utf_string_conversions.h"
+#import "components/shared_highlighting/core/common/fragment_directives_constants.h"
+#import "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #import "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
-#import "components/shared_highlighting/core/common/text_fragments_constants.h"
-#import "components/shared_highlighting/core/common/text_fragments_utils.h"
 #import "ios/web/common/features.h"
 #import "ios/web/public/js_messaging/web_frame.h"
 #import "ios/web/public/js_messaging/web_frame_util.h"
@@ -68,9 +68,9 @@
 
 void TextFragmentsManagerImpl::RemoveHighlights() {
   // Remove the fragments that are visible on the page and update the URL.
-  GetJSFeature()->RemoveHighlights(web_state_,
-                                   shared_highlighting::RemoveTextFragments(
-                                       web_state_->GetLastCommittedURL()));
+  GetJSFeature()->RemoveHighlights(
+      web_state_, shared_highlighting::RemoveFragmentSelectorDirectives(
+                      web_state_->GetLastCommittedURL()));
 }
 
 void TextFragmentsManagerImpl::RegisterDelegate(
diff --git a/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm b/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
index 8c4bb2f..7785ff39 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
+++ b/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
@@ -9,8 +9,8 @@
 #import "base/strings/utf_string_conversions.h"
 #import "base/test/metrics/histogram_tester.h"
 #import "base/test/scoped_feature_list.h"
+#import "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #import "components/shared_highlighting/core/common/shared_highlighting_metrics.h"
-#import "components/shared_highlighting/core/common/text_fragments_constants.h"
 #import "components/ukm/test_ukm_recorder.h"
 #import "ios/web/common/features.h"
 #import "ios/web/navigation/navigation_item_impl.h"
@@ -44,7 +44,7 @@
 const char kSingleFragmentURL[] = "https://chromium.org#:~:text=text";
 const char kTwoFragmentsURL[] =
     "https://chromium.org#:~:text=text&text=other%20text";
-const char kFragmentsRemovedURL[] = "https://chromium.org#";
+const char kFragmentsRemovedURL[] = "https://chromium.org";
 
 const char kSearchEngineURL[] = "https://google.com";
 const char kNonSearchEngineURL[] = "https://notasearchengine.com";
diff --git a/ios/web/web_client.mm b/ios/web/web_client.mm
index f88da06..f4f7b36 100644
--- a/ios/web/web_client.mm
+++ b/ios/web/web_client.mm
@@ -81,11 +81,6 @@
   return @"";
 }
 
-bool WebClient::IsLegacyTLSAllowedForHost(WebState* web_state,
-                                          const std::string& hostname) {
-  return false;
-}
-
 void WebClient::PrepareErrorPage(WebState* web_state,
                                  const GURL& url,
                                  NSError* error,
diff --git a/ios/web_view/internal/cwv_ssl_util.mm b/ios/web_view/internal/cwv_ssl_util.mm
index e50c732..d91be398 100644
--- a/ios/web_view/internal/cwv_ssl_util.mm
+++ b/ios/web_view/internal/cwv_ssl_util.mm
@@ -58,8 +58,5 @@
   if (cert_status & net::CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED) {
     cwv_status |= CWVCertStatusKnownInterceptionBlocked;
   }
-  if (cert_status & net::CERT_STATUS_LEGACY_TLS) {
-    cwv_status |= CWVCertStatusLegacyTLS;
-  }
   return cwv_status;
 }
diff --git a/ios/web_view/internal/web_view_web_client.h b/ios/web_view/internal/web_view_web_client.h
index 6dec7d6..3b5e36fc 100644
--- a/ios/web_view/internal/web_view_web_client.h
+++ b/ios/web_view/internal/web_view_web_client.h
@@ -36,8 +36,6 @@
   NSString* GetDocumentStartScriptForMainFrame(
       web::BrowserState* browser_state) const override;
   std::u16string GetPluginNotSupportedText() const override;
-  bool IsLegacyTLSAllowedForHost(web::WebState* web_state,
-                                 const std::string& hostname) override;
   void PrepareErrorPage(web::WebState* web_state,
                         const GURL& url,
                         NSError* error,
diff --git a/ios/web_view/internal/web_view_web_client.mm b/ios/web_view/internal/web_view_web_client.mm
index ead98b8..5b42259 100644
--- a/ios/web_view/internal/web_view_web_client.mm
+++ b/ios/web_view/internal/web_view_web_client.mm
@@ -126,13 +126,6 @@
   return l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_SUPPORTED);
 }
 
-bool WebViewWebClient::IsLegacyTLSAllowedForHost(web::WebState* web_state,
-                                                 const std::string& hostname) {
-  // TODO(crbug.com/1191799): Legacy TLS should be supported via an interstitial
-  // UI that allows the user to override if desired.
-  return true;
-}
-
 void WebViewWebClient::PrepareErrorPage(
     web::WebState* web_state,
     const GURL& url,
diff --git a/ios/web_view/public/cwv_cert_status.h b/ios/web_view/public/cwv_cert_status.h
index b6b8999..c809e916 100644
--- a/ios/web_view/public/cwv_cert_status.h
+++ b/ios/web_view/public/cwv_cert_status.h
@@ -28,7 +28,6 @@
   CWVCertStatusCertificateTransparencyRequired = 1 << 24,
   CWVCertStatusSymantecLegacy = 1 << 25,
   CWVCertStatusKnownInterceptionBlocked = 1 << 26,
-  CWVCertStatusLegacyTLS = 1 << 27,
 };
 
 #endif  // IOS_WEB_VIEW_PUBLIC_CWV_CERT_STATUS_H_
diff --git a/media/cdm/cdm_paths.cc b/media/cdm/cdm_paths.cc
index 725f420..2bb2fc8 100644
--- a/media/cdm/cdm_paths.cc
+++ b/media/cdm/cdm_paths.cc
@@ -15,10 +15,10 @@
 
 const char kClearKeyCdmBaseDirectory[] = "ClearKeyCdm";
 const char kClearKeyCdmDisplayName[] = "Clear Key CDM";
-const base::Token kClearKeyCdmGuid{0x3a2e0fadde4bd1b7ull,
+const base::Token kClearKeyCdmType{0x3a2e0fadde4bd1b7ull,
                                    0xcb90df3e240d1694ull};
-const base::Token kClearKeyCdmDifferentGuid{0xc3914773474bdb02ull,
-                                            0x8e8de4d84d3ca030ull};
+const base::Token kClearKeyCdmDifferentCdmType{0xc3914773474bdb02ull,
+                                               0x8e8de4d84d3ca030ull};
 
 // As the file system was initially used by the CDM running as a pepper plugin,
 // this ID is based on the pepper plugin MIME type.
diff --git a/media/cdm/cdm_paths.h b/media/cdm/cdm_paths.h
index cbeacc3..eb97687 100644
--- a/media/cdm/cdm_paths.h
+++ b/media/cdm/cdm_paths.h
@@ -23,11 +23,11 @@
 extern const char kClearKeyCdmDisplayName[];
 
 // The default GUID for Clear Key Cdm.
-extern const base::Token kClearKeyCdmGuid;
+extern const base::Token kClearKeyCdmType;
 
 // A different GUID for Clear Key Cdm for testing running different types of
 // CDMs in the system.
-extern const base::Token kClearKeyCdmDifferentGuid;
+extern const base::Token kClearKeyCdmDifferentCdmType;
 
 // Identifier used by the PluginPrivateFileSystem to identify the files stored
 // for the Clear Key CDM.
diff --git a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
index 77d434b..ba08b884 100644
--- a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
+++ b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
@@ -81,9 +81,9 @@
 const char kExternalClearKeyStorageIdTestKeySystem[] =
     "org.chromium.externalclearkey.storageidtest";
 
-// A sub key system that is registered with a different CDM GUID.
-const char kExternalClearKeyDifferentGuidTestKeySystem[] =
-    "org.chromium.externalclearkey.differentguid";
+// A sub key system that is registered with a different CDM type.
+const char kkExternalClearKeyDifferentCdmTypeTestKeySystem[] =
+    "org.chromium.externalclearkey.differentcdmtype";
 
 const int64_t kMsPerSecond = 1000;
 const int64_t kMaxTimerDelayMs = 5 * kMsPerSecond;
@@ -195,7 +195,7 @@
       key_system_string != kExternalClearKeyCrashKeySystem &&
       key_system_string != kExternalClearKeyVerifyCdmHostTestKeySystem &&
       key_system_string != kExternalClearKeyStorageIdTestKeySystem &&
-      key_system_string != kExternalClearKeyDifferentGuidTestKeySystem) {
+      key_system_string != kkExternalClearKeyDifferentCdmTypeTestKeySystem) {
     DVLOG(1) << "Unsupported key system:" << key_system_string;
     return nullptr;
   }
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 98bf1ff..6cd1d63 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -31,11 +31,11 @@
   # media-related content code should access //media/gpu.
   visibility = [
     ":*",
+    "//ash/components/arc/video_accelerator:common",
     "//chrome/gpu",
     "//chromecast/*",
     "//components/arc/mojom:media",
     "//components/arc/mojom:media_mojolpm",
-    "//components/arc/video_accelerator:common",
     "//components/chromeos_camera/*",
     "//components/mirroring/service:mirroring_service",
     "//components/viz/service/main",
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
index 8a1599c..a74e9ed 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
@@ -335,7 +335,8 @@
     return false;
   }
 
-  if (!ActivateAsyncEncoder(pp_activate, encoder_count)) {
+  if (!ActivateAsyncEncoder(pp_activate, encoder_count,
+                            config.is_constrained_h264)) {
     DLOG(ERROR) << "Failed activating an async hardware encoder MFT.";
 
     if (pp_activate) {
@@ -578,7 +579,8 @@
 
 bool MediaFoundationVideoEncodeAccelerator::ActivateAsyncEncoder(
     IMFActivate** pp_activate,
-    uint32_t encoder_count) {
+    uint32_t encoder_count,
+    bool is_constrained_h264) {
   DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -592,6 +594,25 @@
       if (encoder_.Get() != nullptr) {
         DCHECK(SUCCEEDED(hr));
 
+        // Skip NVIDIA GPU due to https://crbug.com/1088650 for constrained
+        // baseline profile H.264 encoding, and go to the next instance
+        // according to merit value.
+        if (codec_ == VideoCodec::kH264 && is_constrained_h264) {
+          // Get the vendor id.
+          base::win::ScopedCoMem<WCHAR> vendor_id;
+          UINT32 id_length;
+          pp_activate[i]->GetAllocatedString(
+              MFT_ENUM_HARDWARE_VENDOR_ID_Attribute, &vendor_id, &id_length);
+          if (!_wcsnicmp(vendor_id, L"VEN_10DE", id_length)) {
+            DLOG(WARNING)
+                << "Skipped NVIDIA GPU due to https://crbug.com/1088650";
+            pp_activate[i]->ShutdownObject();
+            encoder_.Reset();
+            hr = E_FAIL;
+            continue;
+          }
+        }
+
         activate_ = pp_activate[i];
         pp_activate[i] = nullptr;
 
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.h b/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
index 25c1591..19027b7 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
@@ -84,7 +84,9 @@
 
   // Activates the asynchronous encoder instance |encoder_| according to codec
   // merit.
-  bool ActivateAsyncEncoder(IMFActivate** pp_activate, uint32_t activate_count);
+  bool ActivateAsyncEncoder(IMFActivate** pp_activate,
+                            uint32_t activate_count,
+                            bool is_constrained_h264);
 
   // Initializes and allocates memory for input and output parameters.
   bool InitializeInputOutputParameters(VideoCodecProfile output_profile,
diff --git a/media/test/data/multiple_cdm_types.html b/media/test/data/multiple_cdm_types.html
index 84a11fb..c58c5b8 100644
--- a/media/test/data/multiple_cdm_types.html
+++ b/media/test/data/multiple_cdm_types.html
@@ -12,8 +12,8 @@
     console.log(message);
   }
 
-  const EXTERNAL_CLEARKEY_DIFFERENTGUID
-      = 'org.chromium.externalclearkey.differentguid';
+  const EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE
+      = 'org.chromium.externalclearkey.differentcdmtype';
   const crashKeyId = 'crash';
   const normalJwkSet = Utils.createJWKData(KEY_ID, KEY);
   const crashJwkSet = Utils.createJWKData(crashKeyId, KEY);
@@ -49,31 +49,31 @@
   // Using EXTERNAL_CLEARKEY
   var session1;
 
-  // Both using EXTERNAL_CLEARKEY_DIFFERENTGUID
+  // Both using EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE
   var session2;
   var session3;
 
   // The following creates 3 MediaKeys instances each with a MediaKeySession.
-  // MediaKeys using different CDM GUID will run in different processes.
-  // |session1| uses EXTERNAL_CLEARKEY that is registered with the default GUID
-  // for Clear Key CDM. |session2/3| use EXTERNAL_CLEARKEY_DIFFERENTGUID that is
-  // registered with a different GUID. So |session1| will run in process1, and
-  // |session2/3| will run in process2.
+  // MediaKeys using different CDM type will run in different processes.
+  // |session1| uses EXTERNAL_CLEARKEY that is registered with the default type
+  // for Clear Key CDM. |session2/3| use EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE that
+  // is registered with a different type. So |session1| will run in process1,
+  // and |session2/3| will run in process2.
   //
   // Then we send a special response |crashJwkSet| to session2 which will cause
   // the process2 to crash. This will close both |session2/3| as they run in the
   // same process. |session1| should not be affected. Then we try to create
-  // another MediaKeySession using EXTERNAL_CLEARKEY_DIFFERENTGUID, and the
+  // another MediaKeySession using EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE, and the
   // creation should work as a new process should be started.
 
   createMediaKeySession(EXTERNAL_CLEARKEY).then(function(session) {
     log('Session1 created');
     session1 = session;
-    return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTGUID);
+    return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE);
   }).then(function(session) {
     log('Session2 created');
     session2 = session;
-    return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTGUID);
+    return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE);
   }).then(function(session) {
     log('Session3 created');
     session3 = session;
@@ -92,7 +92,7 @@
     return session1.update(normalJwkSet);
   }).then(function() {
     log('Session1 still works');
-    return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTGUID);
+    return createMediaKeySession(EXTERNAL_CLEARKEY_DIFFERENTCDMTYPE);
   }).then(function(session) {
     log('Can still create a session after crash');
     Utils.setResultInTitle('ENDED');
diff --git a/net/BUILD.gn b/net/BUILD.gn
index aaee9f645..035c14b9 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -801,8 +801,6 @@
     "quic/quic_chromium_packet_reader.h",
     "quic/quic_chromium_packet_writer.cc",
     "quic/quic_chromium_packet_writer.h",
-    "quic/quic_client_session_cache.cc",
-    "quic/quic_client_session_cache.h",
     "quic/quic_clock_skew_detector.cc",
     "quic/quic_clock_skew_detector.h",
     "quic/quic_connection_logger.cc",
@@ -4334,7 +4332,6 @@
     "quic/quic_chromium_client_session_test.cc",
     "quic/quic_chromium_client_stream_test.cc",
     "quic/quic_chromium_connection_helper_test.cc",
-    "quic/quic_client_session_cache_unittests.cc",
     "quic/quic_clock_skew_detector_test.cc",
     "quic/quic_connectivity_probing_manager_test.cc",
     "quic/quic_end_to_end_unittest.cc",
@@ -4572,18 +4569,11 @@
   ]
 
   if (is_linux || is_chromeos || is_mac || is_win || is_fuchsia) {
-    deps += [
-      "//third_party/pywebsocket3/",
-      "//third_party/tlslite/",
-    ]
-    data_deps += [
-      "//third_party/pywebsocket3/",
-      "//third_party/tlslite/",
-    ]
+    deps += [ "//third_party/pywebsocket3/" ]
+    data_deps += [ "//third_party/pywebsocket3/" ]
     data += [
       "tools/testserver/",
       "//third_party/pywebsocket3/src/mod_pywebsocket/",
-      "//third_party/tlslite/",
     ]
   }
 
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index c7f10fc..ef046e9 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -559,8 +559,8 @@
 // the device owner.
 NET_ERROR(CERT_KNOWN_INTERCEPTION_BLOCKED, -217)
 
-// The connection uses an obsolete version of SSL/TLS.
-NET_ERROR(SSL_OBSOLETE_VERSION, -218)
+// -218 was SSL_OBSOLETE_VERSION which is not longer used. TLS 1.0/1.1 instead
+// cause SSL_VERSION_OR_CIPHER_MISMATCH now.
 
 // Add new certificate error codes here.
 //
diff --git a/net/base/net_errors_unittest.cc b/net/base/net_errors_unittest.cc
index d1954ec..38edd83 100644
--- a/net/base/net_errors_unittest.cc
+++ b/net/base/net_errors_unittest.cc
@@ -29,7 +29,6 @@
   EXPECT_TRUE(IsCertificateError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
   EXPECT_TRUE(IsCertificateError(ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN));
   EXPECT_TRUE(IsCertificateError(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED));
-  EXPECT_TRUE(IsCertificateError(ERR_SSL_OBSOLETE_VERSION));
 
   // Negative tests.
   EXPECT_FALSE(IsCertificateError(ERR_SSL_PROTOCOL_ERROR));
diff --git a/net/cert/cert_status_flags.cc b/net/cert/cert_status_flags.cc
index fbac0de..64470e7 100644
--- a/net/cert/cert_status_flags.cc
+++ b/net/cert/cert_status_flags.cc
@@ -50,8 +50,6 @@
       return CERT_STATUS_SYMANTEC_LEGACY;
     case ERR_CERT_KNOWN_INTERCEPTION_BLOCKED:
       return (CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED | CERT_STATUS_REVOKED);
-    case ERR_SSL_OBSOLETE_VERSION:
-      return CERT_STATUS_LEGACY_TLS;
     default:
       return 0;
   }
@@ -96,8 +94,6 @@
     return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
   if (cert_status & CERT_STATUS_NO_REVOCATION_MECHANISM)
     return ERR_CERT_NO_REVOCATION_MECHANISM;
-  if (cert_status & CERT_STATUS_LEGACY_TLS)
-    return ERR_SSL_OBSOLETE_VERSION;
 
   // Unknown status. The assumption is 0 (an OK status) won't be used here.
   NOTREACHED();
diff --git a/net/cert/cert_status_flags_list.h b/net/cert/cert_status_flags_list.h
index 523942c8..cd99847 100644
--- a/net/cert/cert_status_flags_list.h
+++ b/net/cert/cert_status_flags_list.h
@@ -44,4 +44,4 @@
 CERT_STATUS_FLAG(CERTIFICATE_TRANSPARENCY_REQUIRED, 1 << 24)
 CERT_STATUS_FLAG(SYMANTEC_LEGACY, 1 << 25)
 CERT_STATUS_FLAG(KNOWN_INTERCEPTION_BLOCKED, 1 << 26)
-CERT_STATUS_FLAG(LEGACY_TLS, 1 << 27)
+// Bit 27 was CERT_STATUS_LEGACY_TLS.
diff --git a/net/disk_cache/cache_util.cc b/net/disk_cache/cache_util.cc
index dd963a9..964247f 100644
--- a/net/disk_cache/cache_util.cc
+++ b/net/disk_cache/cache_util.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/numerics/clamped_math.h"
+#include "base/numerics/ostream_operators.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/net/dns/dns_response_result_extractor.cc b/net/dns/dns_response_result_extractor.cc
index eae438c..2b24683 100644
--- a/net/dns/dns_response_result_extractor.cc
+++ b/net/dns/dns_response_result_extractor.cc
@@ -19,6 +19,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
 #include "base/numerics/checked_math.h"
+#include "base/numerics/ostream_operators.h"
 #include "base/rand_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
diff --git a/net/dns/host_cache_fuzzer.cc b/net/dns/host_cache_fuzzer.cc
index 81bd2394..e431ffc6 100644
--- a/net/dns/host_cache_fuzzer.cc
+++ b/net/dns/host_cache_fuzzer.cc
@@ -9,6 +9,7 @@
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/numerics/clamped_math.h"
+#include "base/numerics/ostream_operators.h"
 #include "base/strings/string_piece_forward.h"
 #include "net/dns/host_cache.h"
 #include "net/dns/host_cache_fuzzer.pb.h"
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 032c1be..c3d9aa1 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -3632,41 +3632,6 @@
   }
 }
 
-// Regression test for https://crbug.com/1044694.
-TEST_F(ProcessAlternativeServicesTest, AltSvcQuicDoesNotSupportTLSHandshake) {
-  // In this example, QUIC v50 is only supported with TLS handshake.
-  // Note that this test only covers the Google-specific AltSvc format
-  // which is now deprecated.
-  quic_context_.params()->supported_versions = {
-      quic::ParsedQuicVersion::Q043(), quic::ParsedQuicVersion::T051()};
-  session_ =
-      std::make_unique<HttpNetworkSession>(session_params_, session_context_);
-  url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
-
-  NetworkIsolationKey network_isolation_key(
-      SchemefulSite(GURL("https://example.com")),
-      SchemefulSite(GURL("https://example.com")));
-
-  scoped_refptr<HttpResponseHeaders> headers(
-      base::MakeRefCounted<HttpResponseHeaders>(""));
-  headers->AddHeader("alt-svc", "quic=\":443\"; v=\"51,43\"");
-
-  session_->http_stream_factory()->ProcessAlternativeServices(
-      session_.get(), network_isolation_key, headers.get(), origin);
-
-  AlternativeServiceInfoVector alternatives =
-      http_server_properties_.GetAlternativeServiceInfos(origin,
-                                                         network_isolation_key);
-  ASSERT_EQ(1u, alternatives.size());
-  EXPECT_EQ(kProtoQUIC, alternatives[0].protocol());
-  EXPECT_EQ(HostPortPair("example.com", 443), alternatives[0].host_port_pair());
-  EXPECT_EQ(1u, alternatives[0].advertised_versions().size());
-  // Q043 and T051 are supported.  Q043 and Q050 are advertised in the Alt-Svc
-  // header.  Therefore only Q043 is parsed.
-  EXPECT_EQ(quic::ParsedQuicVersion::Q043(),
-            alternatives[0].advertised_versions()[0]);
-}
-
 TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcQuicIetf) {
   quic_context_.params()->supported_versions = quic::AllSupportedVersions();
   session_ =
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 450f7bc..8df16fa 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -1231,21 +1231,16 @@
   bool has_valid_entry = false;
   bool has_invalid_entry = false;
   for (const auto& entry : frame.entries) {
-    // |entry.origin| must be a valid origin.
-    GURL url(entry.origin);
-    if (!url.is_valid()) {
-      has_invalid_entry = true;
-      continue;
-    }
-    const url::Origin origin = url::Origin::Create(url);
-    std::string serialized = origin.Serialize();
+    const url::SchemeHostPort scheme_host_port(GURL(entry.origin));
+    // |entry.origin| must be a valid SchemeHostPort.
+    std::string serialized = scheme_host_port.Serialize();
     if (serialized.empty() || entry.origin != serialized) {
       has_invalid_entry = true;
       continue;
     }
     has_valid_entry = true;
     accept_ch_entries_received_via_alps_.insert(
-        std::make_pair(std::move(origin), entry.value));
+        std::make_pair(std::move(scheme_host_port), entry.value));
   }
   LogAcceptChFrameReceivedHistogram(has_valid_entry, has_invalid_entry);
 }
@@ -1508,9 +1503,9 @@
   return true;
 }
 
-base::StringPiece QuicChromiumClientSession::GetAcceptChViaAlpsForOrigin(
-    const url::Origin& origin) const {
-  auto it = accept_ch_entries_received_via_alps_.find(origin);
+base::StringPiece QuicChromiumClientSession::GetAcceptChViaAlps(
+    const url::SchemeHostPort& scheme_host_port) const {
+  auto it = accept_ch_entries_received_via_alps_.find(scheme_host_port);
   if (it == accept_ch_entries_received_via_alps_.end()) {
     LogAcceptChForOriginHistogram(false);
     return {};
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index aca09cbd..716aa55f 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -720,8 +720,8 @@
   // MultiplexedSession methods:
   bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
   bool GetSSLInfo(SSLInfo* ssl_info) const override;
-  base::StringPiece GetAcceptChViaAlpsForOrigin(
-      const url::Origin& origin) const override;
+  base::StringPiece GetAcceptChViaAlps(
+      const url::SchemeHostPort& scheme_host_port) const override;
 
   // Performs a crypto handshake with the server.
   int CryptoConnect(CompletionOnceCallback callback);
@@ -1084,7 +1084,8 @@
   QuicChromiumPathValidationWriterDelegate path_validation_writer_delegate_;
 
   // Map of origin to Accept-CH header field values received via ALPS.
-  base::flat_map<url::Origin, std::string> accept_ch_entries_received_via_alps_;
+  base::flat_map<url::SchemeHostPort, std::string>
+      accept_ch_entries_received_via_alps_;
 
   base::WeakPtrFactory<QuicChromiumClientSession> weak_factory_{this};
 };
diff --git a/net/quic/quic_client_session_cache.cc b/net/quic/quic_client_session_cache.cc
deleted file mode 100644
index fd9bf0b..0000000
--- a/net/quic/quic_client_session_cache.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 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.
-
-#include "net/quic/quic_client_session_cache.h"
-
-#include "base/time/clock.h"
-#include "base/time/default_clock.h"
-
-namespace net {
-
-namespace {
-
-const size_t kDefaultMaxEntries = 1024;
-// Returns false if the SSL |session| doesn't exist or it is expired at |now|.
-bool IsValid(SSL_SESSION* session, time_t now) {
-  if (!session)
-    return false;
-
-  if (now < 0)
-    return false;
-
-  uint64_t now_u64 = static_cast<uint64_t>(now);
-
-  // now_u64 may be slightly behind because of differences in how
-  // time is calculated at this layer versus BoringSSL.
-  // Add a second of wiggle room to account for this.
-  return !(now_u64 < SSL_SESSION_get_time(session) - 1 ||
-           now_u64 >= SSL_SESSION_get_time(session) +
-                          SSL_SESSION_get_timeout(session));
-}
-
-bool DoApplicationStatesMatch(const quic::ApplicationState* state,
-                              quic::ApplicationState* other) {
-  if ((state && !other) || (!state && other))
-    return false;
-  if ((!state && !other) || *state == *other)
-    return true;
-  return false;
-}
-
-}  // namespace
-
-QuicClientSessionCache::QuicClientSessionCache()
-    : QuicClientSessionCache(kDefaultMaxEntries) {}
-
-QuicClientSessionCache::QuicClientSessionCache(size_t max_entries)
-    : clock_(base::DefaultClock::GetInstance()), cache_(max_entries) {
-  memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
-      FROM_HERE, base::BindRepeating(&QuicClientSessionCache::OnMemoryPressure,
-                                     base::Unretained(this)));
-}
-
-QuicClientSessionCache::~QuicClientSessionCache() {
-  Flush();
-}
-
-void QuicClientSessionCache::Insert(
-    const quic::QuicServerId& server_id,
-    bssl::UniquePtr<SSL_SESSION> session,
-    const quic::TransportParameters& params,
-    const quic::ApplicationState* application_state) {
-  DCHECK(session) << "TLS session is not inserted into client cache.";
-  auto iter = cache_.Get(server_id);
-  if (iter == cache_.end()) {
-    CreateAndInsertEntry(server_id, std::move(session), params,
-                         application_state);
-    return;
-  }
-
-  DCHECK(iter->second.params);
-  // The states are both the same, so only need to insert sessions.
-  if (params == *iter->second.params &&
-      DoApplicationStatesMatch(application_state,
-                               iter->second.application_state.get())) {
-    iter->second.PushSession(std::move(session));
-    return;
-  }
-  // Erase the existing entry because this Insert call must come from a
-  // different QUIC session.
-  cache_.Erase(iter);
-  CreateAndInsertEntry(server_id, std::move(session), params,
-                       application_state);
-}
-
-std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup(
-    const quic::QuicServerId& server_id,
-    const SSL_CTX* /*ctx*/) {
-  auto iter = cache_.Get(server_id);
-  if (iter == cache_.end())
-    return nullptr;
-
-  time_t now = clock_->Now().ToTimeT();
-  if (!IsValid(iter->second.PeekSession(), now)) {
-    cache_.Erase(iter);
-    return nullptr;
-  }
-  auto state = std::make_unique<quic::QuicResumptionState>();
-  state->tls_session = iter->second.PopSession();
-  if (iter->second.params != nullptr) {
-    state->transport_params =
-        std::make_unique<quic::TransportParameters>(*iter->second.params);
-  }
-  if (iter->second.application_state != nullptr) {
-    state->application_state = std::make_unique<quic::ApplicationState>(
-        *iter->second.application_state);
-  }
-
-  return state;
-}
-
-void QuicClientSessionCache::ClearEarlyData(
-    const quic::QuicServerId& server_id) {
-  auto iter = cache_.Get(server_id);
-  if (iter == cache_.end())
-    return;
-  for (auto& session : iter->second.sessions) {
-    if (session) {
-      session.reset(SSL_SESSION_copy_without_early_data(session.get()));
-    }
-  }
-}
-
-void QuicClientSessionCache::FlushInvalidEntries() {
-  time_t now = clock_->Now().ToTimeT();
-  auto iter = cache_.begin();
-  while (iter != cache_.end()) {
-    if (!IsValid(iter->second.PeekSession(), now)) {
-      iter = cache_.Erase(iter);
-    } else {
-      ++iter;
-    }
-  }
-}
-
-void QuicClientSessionCache::OnMemoryPressure(
-    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
-  switch (memory_pressure_level) {
-    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
-      break;
-    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
-      FlushInvalidEntries();
-      break;
-    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
-      Flush();
-      break;
-  }
-}
-
-void QuicClientSessionCache::Flush() {
-  cache_.Clear();
-}
-
-void QuicClientSessionCache::CreateAndInsertEntry(
-    const quic::QuicServerId& server_id,
-    bssl::UniquePtr<SSL_SESSION> session,
-    const quic::TransportParameters& params,
-    const quic::ApplicationState* application_state) {
-  Entry entry;
-  entry.PushSession(std::move(session));
-  entry.params = std::make_unique<quic::TransportParameters>(params);
-  if (application_state) {
-    entry.application_state =
-        std::make_unique<quic::ApplicationState>(*application_state);
-  }
-  cache_.Put(server_id, std::move(entry));
-}
-
-QuicClientSessionCache::Entry::Entry() = default;
-QuicClientSessionCache::Entry::Entry(Entry&&) = default;
-QuicClientSessionCache::Entry::~Entry() = default;
-
-void QuicClientSessionCache::Entry::PushSession(
-    bssl::UniquePtr<SSL_SESSION> session) {
-  if (sessions[0] != nullptr) {
-    sessions[1] = std::move(sessions[0]);
-  }
-  sessions[0] = std::move(session);
-}
-
-bssl::UniquePtr<SSL_SESSION> QuicClientSessionCache::Entry::PopSession() {
-  if (sessions[0] == nullptr)
-    return nullptr;
-  bssl::UniquePtr<SSL_SESSION> session = std::move(sessions[0]);
-  sessions[0] = std::move(sessions[1]);
-  sessions[1] = nullptr;
-  return session;
-}
-
-SSL_SESSION* QuicClientSessionCache::Entry::PeekSession() {
-  return sessions[0].get();
-}
-
-}  // namespace net
diff --git a/net/quic/quic_client_session_cache.h b/net/quic/quic_client_session_cache.h
deleted file mode 100644
index c84b2cdd..0000000
--- a/net/quic/quic_client_session_cache.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 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 NET_QUIC_QUIC_CLIENT_SESSION_CACHE_H_
-#define NET_QUIC_QUIC_CLIENT_SESSION_CACHE_H_
-
-#include <stddef.h>
-#include <time.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/containers/lru_cache.h"
-#include "base/memory/memory_pressure_monitor.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
-#include "third_party/boringssl/src/include/openssl/base.h"
-
-namespace base {
-class Clock;
-}
-
-namespace net {
-
-class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache {
- public:
-  QuicClientSessionCache();
-  explicit QuicClientSessionCache(size_t max_entries);
-  ~QuicClientSessionCache() override;
-
-  void Insert(const quic::QuicServerId& server_id,
-              bssl::UniquePtr<SSL_SESSION> session,
-              const quic::TransportParameters& params,
-              const quic::ApplicationState* application_state) override;
-
-  std::unique_ptr<quic::QuicResumptionState> Lookup(
-      const quic::QuicServerId& server_id,
-      const SSL_CTX* ctx) override;
-
-  void ClearEarlyData(const quic::QuicServerId& server_id) override;
-
-  void SetClockForTesting(base::Clock* clock) { clock_ = clock; }
-
-  size_t size() const { return cache_.size(); }
-
-  void Flush();
-
-  void OnMemoryPressure(
-      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
-
- private:
-  struct Entry {
-    Entry();
-    Entry(Entry&&);
-    ~Entry();
-
-    // Adds a new |session| onto sessions, dropping the oldest one if two are
-    // already stored.
-    void PushSession(bssl::UniquePtr<SSL_SESSION> session);
-
-    // Retrieves the latest session from the entry, meanwhile removing it.
-    bssl::UniquePtr<SSL_SESSION> PopSession();
-
-    SSL_SESSION* PeekSession();
-
-    bssl::UniquePtr<SSL_SESSION> sessions[2];
-    std::unique_ptr<quic::TransportParameters> params;
-    std::unique_ptr<quic::ApplicationState> application_state;
-  };
-  void FlushInvalidEntries();
-
-  // Creates a new entry and insert into |cache_|.
-  void CreateAndInsertEntry(const quic::QuicServerId& server_id,
-                            bssl::UniquePtr<SSL_SESSION> session,
-                            const quic::TransportParameters& params,
-                            const quic::ApplicationState* application_state);
-
-  base::Clock* clock_;
-  base::LRUCache<quic::QuicServerId, Entry> cache_;
-  std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_QUIC_CLIENT_SESSION_CACHE_H_
diff --git a/net/quic/quic_client_session_cache_unittests.cc b/net/quic/quic_client_session_cache_unittests.cc
deleted file mode 100644
index 1cc61ab..0000000
--- a/net/quic/quic_client_session_cache_unittests.cc
+++ /dev/null
@@ -1,423 +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.
-
-#include "net/quic/quic_client_session_cache.h"
-
-#include "base/run_loop.h"
-#include "base/test/simple_test_clock.h"
-#include "base/test/task_environment.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "net/base/hex_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/boringssl/src/include/openssl/ssl.h"
-
-namespace net {
-
-namespace {
-
-const base::TimeDelta kTimeout = base::Seconds(1000);
-const quic::QuicVersionLabel kFakeVersionLabel = 0x01234567;
-const quic::QuicVersionLabel kFakeVersionLabel2 = 0x89ABCDEF;
-const uint64_t kFakeIdleTimeoutMilliseconds = 12012;
-const uint8_t kFakeStatelessResetTokenData[16] = {
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F};
-const uint64_t kFakeMaxPacketSize = 9001;
-const uint64_t kFakeInitialMaxData = 101;
-const bool kFakeDisableMigration = true;
-const auto kCustomParameter1 =
-    static_cast<quic::TransportParameters::TransportParameterId>(0xffcd);
-const char* kCustomParameter1Value = "foo";
-const auto kCustomParameter2 =
-    static_cast<quic::TransportParameters::TransportParameterId>(0xff34);
-const char* kCustomParameter2Value = "bar";
-
-std::vector<uint8_t> CreateFakeStatelessResetToken() {
-  return std::vector<uint8_t>(
-      kFakeStatelessResetTokenData,
-      kFakeStatelessResetTokenData + base::size(kFakeStatelessResetTokenData));
-}
-
-quic::TransportParameters::LegacyVersionInformation
-CreateFakeLegacyVersionInformation() {
-  quic::TransportParameters::LegacyVersionInformation
-      legacy_version_information;
-  legacy_version_information.version = kFakeVersionLabel;
-  legacy_version_information.supported_versions.push_back(kFakeVersionLabel);
-  legacy_version_information.supported_versions.push_back(kFakeVersionLabel2);
-  return legacy_version_information;
-}
-
-quic::TransportParameters::VersionInformation CreateFakeVersionInformation() {
-  quic::TransportParameters::VersionInformation version_information;
-  version_information.chosen_version = kFakeVersionLabel;
-  version_information.other_versions.push_back(kFakeVersionLabel);
-  return version_information;
-}
-
-std::unique_ptr<base::SimpleTestClock> MakeTestClock() {
-  std::unique_ptr<base::SimpleTestClock> clock =
-      std::make_unique<base::SimpleTestClock>();
-  // SimpleTestClock starts at the null base::Time which converts to and from
-  // time_t confusingly.
-  clock->SetNow(base::Time::FromTimeT(1000000000));
-  return clock;
-}
-
-// Make a TransportParameters that has a few fields set to help test comparison.
-std::unique_ptr<quic::TransportParameters> MakeFakeTransportParams() {
-  auto params = std::make_unique<quic::TransportParameters>();
-  params->perspective = quic::Perspective::IS_CLIENT;
-  params->legacy_version_information = CreateFakeLegacyVersionInformation();
-  params->version_information = CreateFakeVersionInformation();
-  params->max_idle_timeout_ms.set_value(kFakeIdleTimeoutMilliseconds);
-  params->stateless_reset_token = CreateFakeStatelessResetToken();
-  params->max_udp_payload_size.set_value(kFakeMaxPacketSize);
-  params->initial_max_data.set_value(kFakeInitialMaxData);
-  params->disable_active_migration = kFakeDisableMigration;
-  params->custom_parameters[kCustomParameter1] = kCustomParameter1Value;
-  params->custom_parameters[kCustomParameter2] = kCustomParameter2Value;
-  return params;
-}
-
-namespace {
-
-// Generated by running TlsClientHandshakerTest.ZeroRttResumption and in
-// TlsClientHandshaker::InsertSession calling SSL_SESSION_to_bytes to serialize
-// the received 0-RTT capable ticket.
-static const char kCachedSession[] =
-    "3082068702010102020304040213010420b9c2a657e565db0babd09e192a9fc4d768fbd706"
-    "9f03f9278a4a0be62392e55b0420d87ed2ab8cafc986fd2e288bd2d654cd57c3a2bed1d532"
-    "20726e55fed39d021ea10602045ed16771a205020302a300a382025f3082025b30820143a0"
-    "03020102020104300d06092a864886f70d01010b0500302c3110300e060355040a13074163"
-    "6d6520436f311830160603550403130f496e7465726d656469617465204341301e170d3133"
-    "303130313130303030305a170d3233313233313130303030305a302d3110300e060355040a"
-    "130741636d6520436f3119301706035504031310746573742e6578616d706c652e636f6d30"
-    "59301306072a8648ce3d020106082a8648ce3d030107034200040526220e77278300d06bc0"
-    "86aff4f999a828a2ed5cc75adc2972794befe885aa3a9b843de321b36b0a795289cebff1a5"
-    "428bad5e34665ce5e36daad08fb3ffd8a3523050300e0603551d0f0101ff04040302078030"
-    "130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301b06"
-    "03551d11041430128210746573742e6578616d706c652e636f6d300d06092a864886f70d01"
-    "010b050003820101008c1f1e380831b6437a8b9284d28d4ead38d9503a9fc936db89048aa2"
-    "edd6ec2fb830d962ef7a4f384e679504f4d5520f3272e0b9e702b110aff31711578fa5aeb1"
-    "11e9d184c994b0f97e7b17d1995f3f477f25bc1258398ec0ec729caed55d594a009f48093a"
-    "17f33a7f3bb6e420cc3499838398a421d93c7132efa8bee5ed2645cbc55179c400da006feb"
-    "761badd356cac3bd7a0e6b22a511106a355ec62a4c0ac2541d2996adb4a918c866d10c3e31"
-    "62039a91d4ce600b276740d833380b37f66866d261bf6efa8855e7ae6c7d12a8a864cd9a1f"
-    "4663e07714b0204e51bbc189a2d04c2a5043202379ff1c8cbf30cbb44fde4ee9a1c0c976dc"
-    "4943df2c132ca4020400aa7f047d494e534543555245003072020101020203040402130104"
-    "000420d87ed2ab8cafc986fd2e288bd2d654cd57c3a2bed1d53220726e55fed39d021ea106"
-    "02045ed16771a205020302a300a4020400b20302011db5060404bd909308b807020500ffff"
-    "ffffb9050203093a80ba07040568332d3238bb030101ffbc03040100b20302011db3820307"
-    "30820303308201eba003020102020102300d06092a864886f70d01010b050030243110300e"
-    "060355040a130741636d6520436f3110300e06035504031307526f6f74204341301e170d31"
-    "33303130313130303030305a170d3233313233313130303030305a302c3110300e06035504"
-    "0a130741636d6520436f311830160603550403130f496e7465726d65646961746520434130"
-    "820122300d06092a864886f70d01010105000382010f003082010a0282010100cd3550e70a"
-    "6880e52bf0012b93110c50f723e1d8d2ed489aea3b649f82fae4ad2396a8a19b31d1d64ab2"
-    "79f1c18003184154a5303a82bd57109cfd5d34fd19d3211bcb06e76640e1278998822dd72e"
-    "0d5c059a740d45de325e784e81b4c86097f08b2a8ce057f6b9db5a53641d27e09347d993ee"
-    "acf67be7d297b1a6853775ffaaf78fae924e300b5654fd32f99d3cd82e95f56417ff26d265"
-    "e2b1786c835d67a4d8ae896b6eb34b35a5b1033c209779ed0bf8de25a13a507040ae9e0475"
-    "a26a2f15845b08c3e0554e47dbbc7925b02e580dbcaaa6f2eecde6b8028c5b00b33d44d0a6"
-    "bfb3e72e9d4670de45d1bd79bdc0f2470b71286091c29873152db4b1f30203010001a33830"
-    "36300e0603551d0f0101ff04040302020430130603551d25040c300a06082b060105050703"
-    "01300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101"
-    "00bc4f8234860558dd404a626403819bfc759029d625a002143e75ebdb2898d1befdd326c3"
-    "4b14dc3507d732bb29af7e6af31552db53052a2be0d950efee5e0f699304231611ed8bf73a"
-    "6f216a904c6c2f1a2186d1ed08a8005a7914394d71e7d4b643c808f86365c5fecad8b52934"
-    "2d3b3f03447126d278d75b1dab3ed53f23e36e9b3d695f28727916e5ee56ce22d387c81f05"
-    "919b2a37bd4981eb67d9f57b7072285dbbb61f48b6b14768c069a092aad5a094cf295dafd2"
-    "3ca008f89a5f5ab37a56e5f68df45091c7cb85574677127087a2887ba3baa6d4fc436c6e40"
-    "40885e81621d38974f0c7f0d792418c5adebb10e92a165f8d79b169617ff575c0d4a85b506"
-    "0404bd909308b603010100b70402020403b807020500ffffffffb9050203093a80ba070405"
-    "68332d3238bb030101ff";
-
-}  // namespace
-
-class QuicClientSessionCacheTest : public testing::Test {
- public:
-  QuicClientSessionCacheTest()
-      : ssl_ctx_(SSL_CTX_new(TLS_method())), clock_(MakeTestClock()) {}
-
- protected:
-  bssl::UniquePtr<SSL_SESSION> NewSSLSession() {
-    std::string cached_session = HexDecode(kCachedSession);
-    SSL_SESSION* session = SSL_SESSION_from_bytes(
-        reinterpret_cast<const uint8_t*>(cached_session.data()),
-        cached_session.size(), ssl_ctx_.get());
-    return bssl::UniquePtr<SSL_SESSION>(session);
-  }
-
-  bssl::UniquePtr<SSL_SESSION> MakeTestSession(
-      base::TimeDelta timeout = kTimeout) {
-    bssl::UniquePtr<SSL_SESSION> session = NewSSLSession();
-    SSL_SESSION_set_time(session.get(), clock_->Now().ToTimeT());
-    SSL_SESSION_set_timeout(session.get(), timeout.InSeconds());
-    return session;
-  }
-
-  bssl::UniquePtr<SSL_CTX> ssl_ctx_;
-  std::unique_ptr<base::SimpleTestClock> clock_;
-};
-
-}  // namespace
-
-// Tests that simple insertion and lookup work correctly.
-TEST_F(QuicClientSessionCacheTest, SingleSession) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-
-  auto params2 = MakeFakeTransportParams();
-  auto session2 = MakeTestSession();
-  SSL_SESSION* unowned2 = session2.get();
-  quic::QuicServerId id2("b.com", 443);
-
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-  EXPECT_EQ(nullptr, cache.Lookup(id2, ssl_ctx_.get()));
-  EXPECT_EQ(0u, cache.size());
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  EXPECT_EQ(1u, cache.size());
-  EXPECT_EQ(*params, *(cache.Lookup(id1, ssl_ctx_.get())->transport_params));
-  EXPECT_EQ(nullptr, cache.Lookup(id2, ssl_ctx_.get()));
-  // No session is available for id1, even though the entry exists.
-  EXPECT_EQ(1u, cache.size());
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-  // Lookup() will trigger a deletion of invalid entry.
-  EXPECT_EQ(0u, cache.size());
-
-  auto session3 = MakeTestSession();
-  SSL_SESSION* unowned3 = session3.get();
-  quic::QuicServerId id3("c.com", 443);
-  cache.Insert(id3, std::move(session3), *params, nullptr);
-  cache.Insert(id2, std::move(session2), *params2, nullptr);
-  EXPECT_EQ(2u, cache.size());
-  EXPECT_EQ(unowned2, cache.Lookup(id2, ssl_ctx_.get())->tls_session.get());
-  EXPECT_EQ(unowned3, cache.Lookup(id3, ssl_ctx_.get())->tls_session.get());
-
-  // Verify that the cache is cleared after Lookups.
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-  EXPECT_EQ(nullptr, cache.Lookup(id2, ssl_ctx_.get()));
-  EXPECT_EQ(nullptr, cache.Lookup(id3, ssl_ctx_.get()));
-  EXPECT_EQ(0u, cache.size());
-}
-
-TEST_F(QuicClientSessionCacheTest, MultipleSessions) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-  auto session2 = MakeTestSession();
-  SSL_SESSION* unowned2 = session2.get();
-  auto session3 = MakeTestSession();
-  SSL_SESSION* unowned3 = session3.get();
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  cache.Insert(id1, std::move(session2), *params, nullptr);
-  cache.Insert(id1, std::move(session3), *params, nullptr);
-  // The latest session is popped first.
-  EXPECT_EQ(unowned3, cache.Lookup(id1, ssl_ctx_.get())->tls_session.get());
-  EXPECT_EQ(unowned2, cache.Lookup(id1, ssl_ctx_.get())->tls_session.get());
-  // Only two sessions are cached.
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-}
-
-// Test that when a different TransportParameter is inserted for
-// the same server id, the existing entry is removed.
-TEST_F(QuicClientSessionCacheTest, DifferentTransportParams) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-  auto session2 = MakeTestSession();
-  auto session3 = MakeTestSession();
-  SSL_SESSION* unowned3 = session3.get();
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  cache.Insert(id1, std::move(session2), *params, nullptr);
-  // tweak the transport parameters a little bit.
-  params->perspective = quic::Perspective::IS_SERVER;
-  cache.Insert(id1, std::move(session3), *params, nullptr);
-  auto resumption_state = cache.Lookup(id1, ssl_ctx_.get());
-  EXPECT_EQ(unowned3, resumption_state->tls_session.get());
-  EXPECT_EQ(*params.get(), *resumption_state->transport_params);
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-}
-
-TEST_F(QuicClientSessionCacheTest, DifferentApplicationState) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-  auto session2 = MakeTestSession();
-  auto session3 = MakeTestSession();
-  SSL_SESSION* unowned3 = session3.get();
-  quic::ApplicationState state;
-  state.push_back('a');
-
-  cache.Insert(id1, std::move(session), *params, &state);
-  cache.Insert(id1, std::move(session2), *params, &state);
-  cache.Insert(id1, std::move(session3), *params, nullptr);
-  auto resumption_state = cache.Lookup(id1, ssl_ctx_.get());
-  EXPECT_EQ(unowned3, resumption_state->tls_session.get());
-  EXPECT_EQ(nullptr, resumption_state->application_state);
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-}
-
-TEST_F(QuicClientSessionCacheTest, BothStatesDifferent) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-  auto session2 = MakeTestSession();
-  auto session3 = MakeTestSession();
-  SSL_SESSION* unowned3 = session3.get();
-  quic::ApplicationState state;
-  state.push_back('a');
-
-  cache.Insert(id1, std::move(session), *params, &state);
-  cache.Insert(id1, std::move(session2), *params, &state);
-  params->perspective = quic::Perspective::IS_SERVER;
-  cache.Insert(id1, std::move(session3), *params, nullptr);
-  auto resumption_state = cache.Lookup(id1, ssl_ctx_.get());
-  EXPECT_EQ(unowned3, resumption_state->tls_session.get());
-  EXPECT_EQ(*params.get(), *resumption_state->transport_params);
-  EXPECT_EQ(nullptr, resumption_state->application_state);
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-}
-
-// When the size limit is exceeded, the oldest entry should be erased.
-TEST_F(QuicClientSessionCacheTest, SizeLimit) {
-  QuicClientSessionCache cache(2);
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-
-  auto session2 = MakeTestSession();
-  SSL_SESSION* unowned2 = session2.get();
-  quic::QuicServerId id2("b.com", 443);
-
-  auto session3 = MakeTestSession();
-  SSL_SESSION* unowned3 = session3.get();
-  quic::QuicServerId id3("c.com", 443);
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  cache.Insert(id2, std::move(session2), *params, nullptr);
-  cache.Insert(id3, std::move(session3), *params, nullptr);
-
-  EXPECT_EQ(2u, cache.size());
-  EXPECT_EQ(unowned2, cache.Lookup(id2, ssl_ctx_.get())->tls_session.get());
-  EXPECT_EQ(unowned3, cache.Lookup(id3, ssl_ctx_.get())->tls_session.get());
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-}
-
-TEST_F(QuicClientSessionCacheTest, ClearEarlyData) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-  SSL_CTX_set_early_data_enabled(ssl_ctx_.get(), 1);
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-  auto session2 = MakeTestSession();
-
-  EXPECT_TRUE(SSL_SESSION_early_data_capable(session.get()));
-  EXPECT_TRUE(SSL_SESSION_early_data_capable(session2.get()));
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  cache.Insert(id1, std::move(session2), *params, nullptr);
-
-  cache.ClearEarlyData(id1);
-
-  auto resumption_state = cache.Lookup(id1, ssl_ctx_.get());
-  EXPECT_FALSE(
-      SSL_SESSION_early_data_capable(resumption_state->tls_session.get()));
-  resumption_state = cache.Lookup(id1, ssl_ctx_.get());
-  EXPECT_FALSE(
-      SSL_SESSION_early_data_capable(resumption_state->tls_session.get()));
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-}
-
-// Expired session isn't considered valid and nullptr will be returned upon
-// Lookup.
-TEST_F(QuicClientSessionCacheTest, Expiration) {
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-
-  auto session2 = MakeTestSession(3 * kTimeout);
-  SSL_SESSION* unowned2 = session2.get();
-  quic::QuicServerId id2("b.com", 443);
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  cache.Insert(id2, std::move(session2), *params, nullptr);
-
-  EXPECT_EQ(2u, cache.size());
-  // Expire the session.
-  clock_->Advance(kTimeout * 2);
-  // The entry has not been removed yet.
-  EXPECT_EQ(2u, cache.size());
-
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-  EXPECT_EQ(1u, cache.size());
-  EXPECT_EQ(unowned2, cache.Lookup(id2, ssl_ctx_.get())->tls_session.get());
-  EXPECT_EQ(1u, cache.size());
-}
-
-TEST_F(QuicClientSessionCacheTest, FlushOnMemoryNotifications) {
-  base::test::TaskEnvironment task_environment;
-  QuicClientSessionCache cache;
-  cache.SetClockForTesting(clock_.get());
-
-  auto params = MakeFakeTransportParams();
-  auto session = MakeTestSession();
-  quic::QuicServerId id1("a.com", 443);
-
-  auto session2 = MakeTestSession(3 * kTimeout);
-  quic::QuicServerId id2("b.com", 443);
-
-  cache.Insert(id1, std::move(session), *params, nullptr);
-  cache.Insert(id2, std::move(session2), *params, nullptr);
-
-  EXPECT_EQ(2u, cache.size());
-  // Expire the session.
-  clock_->Advance(kTimeout * 2);
-  // The entry has not been removed yet.
-  EXPECT_EQ(2u, cache.size());
-
-  // Fire a notification that will flush expired sessions.
-  base::MemoryPressureListener::NotifyMemoryPressure(
-      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
-  base::RunLoop().RunUntilIdle();
-
-  // session is expired and should be flushed.
-  EXPECT_EQ(nullptr, cache.Lookup(id1, ssl_ctx_.get()));
-  EXPECT_EQ(1u, cache.size());
-
-  // Fire notification that will flush everything.
-  base::MemoryPressureListener::NotifyMemoryPressure(
-      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0u, cache.size());
-}
-
-}  // namespace net
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 4c24a1be..bc3f864 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -109,8 +109,6 @@
       return HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1;
     case quic::QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_999;
-    case quic::QUIC_VERSION_51:
-      return HttpResponseInfo::CONNECTION_INFO_QUIC_T051;
   }
   NOTREACHED();
   return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
@@ -449,8 +447,7 @@
     return {};
   }
 
-  const url::Origin origin = url::Origin::Create(request_info_->url);
-  return session()->GetAcceptChViaAlpsForOrigin(origin);
+  return session()->GetAcceptChViaAlps(url::SchemeHostPort(request_info_->url));
 }
 
 void QuicHttpStream::ReadTrailingHeaders() {
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 9336c7d..cadb887 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -13,6 +13,7 @@
 #include "base/containers/contains.h"
 #include "base/feature_list.h"
 #include "base/location.h"
+#include "base/memory/memory_pressure_monitor.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -23,6 +24,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/default_clock.h"
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
@@ -46,7 +48,6 @@
 #include "net/quic/quic_chromium_connection_helper.h"
 #include "net/quic/quic_chromium_packet_reader.h"
 #include "net/quic/quic_chromium_packet_writer.h"
-#include "net/quic/quic_client_session_cache.h"
 #include "net/quic/quic_context.h"
 #include "net/quic/quic_crypto_client_stream_factory.h"
 #include "net/quic/quic_http_stream.h"
@@ -60,6 +61,7 @@
 #include "net/ssl/ssl_key_logger.h"
 #include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
 #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_client_session_cache.h"
 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
 #include "net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h"
 #include "net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index.h"
@@ -232,11 +234,16 @@
  public:
   QuicCryptoClientConfigOwner(
       std::unique_ptr<quic::ProofVerifier> proof_verifier,
-      std::unique_ptr<QuicClientSessionCache> session_cache,
+      std::unique_ptr<quic::QuicClientSessionCache> session_cache,
       QuicStreamFactory* quic_stream_factory)
       : config_(std::move(proof_verifier), std::move(session_cache)),
+        clock_(base::DefaultClock::GetInstance()),
         quic_stream_factory_(quic_stream_factory) {
     DCHECK(quic_stream_factory_);
+    memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
+        FROM_HERE,
+        base::BindRepeating(&QuicCryptoClientConfigOwner::OnMemoryPressure,
+                            base::Unretained(this)));
   }
 
   QuicCryptoClientConfigOwner(const QuicCryptoClientConfigOwner&) = delete;
@@ -251,6 +258,30 @@
 
   QuicStreamFactory* quic_stream_factory() { return quic_stream_factory_; }
 
+  void OnMemoryPressure(
+      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+    quic::SessionCache* session_cache = config_.mutable_session_cache();
+    if (!session_cache) {
+      return;
+    }
+    time_t now = clock_->Now().ToTimeT();
+    uint64_t now_u64 = 0;
+    if (now > 0) {
+      now_u64 = static_cast<uint64_t>(now);
+    }
+    switch (memory_pressure_level) {
+      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+        break;
+      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+        session_cache->RemoveExpiredEntries(
+            quic::QuicWallTime::FromUNIXSeconds(now_u64));
+        break;
+      case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+        session_cache->Clear();
+        break;
+    }
+  }
+
  private:
   friend class CryptoClientConfigHandle;
 
@@ -268,6 +299,8 @@
 
   int num_refs_ = 0;
   quic::QuicCryptoClientConfig config_;
+  base::Clock* clock_;
+  std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
   QuicStreamFactory* const quic_stream_factory_;
 };
 
@@ -2174,7 +2207,7 @@
               sct_auditing_delegate_,
               HostsFromOrigins(params_.origins_to_force_quic_on),
               actual_network_isolation_key),
-          std::make_unique<QuicClientSessionCache>(), this);
+          std::make_unique<quic::QuicClientSessionCache>(), this);
 
   quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config();
   crypto_config->set_user_agent_id(params_.user_agent_id);
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index ddfe672f5..11dd934 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -1291,21 +1291,9 @@
       result = ct_result;
   }
 
-  // If no other errors occurred, check whether the connection used a legacy TLS
-  // version.
-  if (result == OK &&
-      SSL_version(ssl_.get()) < context_->config().version_min_warn) {
-    server_cert_verify_result_.cert_status |= CERT_STATUS_LEGACY_TLS;
-
-    // Only set the resulting net error if it hasn't been previously bypassed.
-    if (!IsAllowedBadCert(server_cert_.get(), nullptr))
-      result = ERR_SSL_OBSOLETE_VERSION;
-  }
-
   is_fatal_cert_error_ =
       IsCertStatusError(server_cert_verify_result_.cert_status) &&
       result != ERR_CERT_KNOWN_INTERCEPTION_BLOCKED &&
-      result != ERR_SSL_OBSOLETE_VERSION &&
       context_->transport_security_state()->ShouldSSLErrorsBeFatal(
           host_and_port_.host());
 
@@ -1314,9 +1302,7 @@
       // Certificate exceptions are only applicable for the origin name. For
       // simplicity, we do not allow certificate exceptions for the public name
       // and map all bypassable errors to fatal ones.
-      result = result == ERR_SSL_OBSOLETE_VERSION
-                   ? ERR_SSL_VERSION_OR_CIPHER_MISMATCH
-                   : ERR_ECH_FALLBACK_CERTIFICATE_INVALID;
+      result = ERR_ECH_FALLBACK_CERTIFICATE_INVALID;
     }
     if (ssl_config_.ignore_certificate_errors) {
       result = OK;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index a4dd4b90..2708956 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -1000,24 +1000,14 @@
 };
 
 std::vector<uint16_t> GetTLSVersions() {
-  return {SSL_PROTOCOL_VERSION_TLS1, SSL_PROTOCOL_VERSION_TLS1_1,
-          SSL_PROTOCOL_VERSION_TLS1_2, SSL_PROTOCOL_VERSION_TLS1_3};
+  return {SSL_PROTOCOL_VERSION_TLS1_2, SSL_PROTOCOL_VERSION_TLS1_3};
 }
 
 class SSLClientSocketVersionTest
     : public SSLClientSocketTest,
       public ::testing::WithParamInterface<uint16_t> {
  protected:
-  SSLClientSocketVersionTest() {
-    // If the test is using legacy TLS versions, explicitly disable warnings
-    // (e.g., to cover cases like post-interstitial or when legacy TLS is
-    // explicitly allowed via configuration).
-    if (version() < SSL_PROTOCOL_VERSION_TLS1_2) {
-      SSLContextConfig config;
-      config.version_min_warn = SSL_PROTOCOL_VERSION_TLS1;
-      ssl_config_service_->UpdateSSLConfigAndNotify(config);
-    }
-  }
+  SSLClientSocketVersionTest() = default;
 
   uint16_t version() const { return GetParam(); }
 
@@ -1042,14 +1032,6 @@
               socket_factory_);
       socket_factory_ = wrapped_socket_factory_.get();
     }
-    // If the test is using legacy TLS versions, explicitly disable warnings
-    // (e.g., to cover cases like post-interstitial or when legacy TLS is
-    // explicitly allowed via configuration).
-    if (version() < SSL_PROTOCOL_VERSION_TLS1_2) {
-      SSLContextConfig config;
-      config.version_min_warn = SSL_PROTOCOL_VERSION_TLS1;
-      ssl_config_service_->UpdateSSLConfigAndNotify(config);
-    }
   }
 
   // Convienient wrapper to call Read()/ReadIfReady() depending on whether
@@ -2504,6 +2486,30 @@
   EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
 }
 
+// Test that connecting to a server only supporting TLS 1.0 will fail and
+// results in ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
+TEST_F(SSLClientSocketTest, TLS1_NotSupported) {
+  SSLServerConfig config;
+  config.version_max = SSL_PROTOCOL_VERSION_TLS1;
+  config.version_min = SSL_PROTOCOL_VERSION_TLS1;
+  ASSERT_TRUE(StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, config));
+  int rv;
+  ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
+  EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
+}
+
+// Test that connecting to a server only supporting TLS 1.1 will fail and
+// results in ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
+TEST_F(SSLClientSocketTest, TLS1_1_NotSupported) {
+  SSLServerConfig config;
+  config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
+  config.version_min = SSL_PROTOCOL_VERSION_TLS1_1;
+  ASSERT_TRUE(StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, config));
+  int rv;
+  ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv));
+  EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
+}
+
 // When creating an SSLClientSocket, it is allowed to pass in a
 // ClientSocketHandle that is not obtained from a client socket pool.
 // Here we verify that such a simple ClientSocketHandle, not associated with any
@@ -5349,38 +5355,6 @@
   EXPECT_THAT(rv, IsError(ERR_ECH_FALLBACK_CERTIFICATE_INVALID));
 }
 
-// Test that the ECH fallback handshake rejects legacy TLS versions.
-TEST_F(SSLClientSocketTest, ECHFallbackLegacyVersion) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
-
-  static const char kPublicName[] = "public.example";
-  std::vector<uint8_t> ech_config_list;
-  bssl::UniquePtr<SSL_ECH_KEYS> keys =
-      MakeTestECHKeys(kPublicName, /*max_name_len=*/64, &ech_config_list);
-  ASSERT_TRUE(keys);
-
-  // Configure TLS 1.1 as allowed, but with a bypassable error.
-  SSLContextConfig context_config;
-  context_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
-  context_config.version_min_warn = SSL_PROTOCOL_VERSION_TLS1_2;
-  ssl_config_service_->UpdateSSLConfigAndNotify(context_config);
-
-  SSLServerConfig server_config;
-  server_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
-  ASSERT_TRUE(
-      StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config));
-
-  // We do not implement bypassable errors for the fallback handshake, so this
-  // should report a fatal ERR_SSL_VERSION_OR_CIPHER_MISMATCH, not
-  // ERR_SSL_OBSOLETE_VERSION.
-  SSLConfig client_config;
-  client_config.ech_config_list = std::move(ech_config_list);
-  int rv;
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
-  EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
-}
-
 TEST_F(SSLClientSocketTest, InvalidECHConfigList) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
@@ -5500,11 +5474,6 @@
   SSLContextConfig client_context_config;
   client_context_config.version_min = GetParam().version;
   client_context_config.version_max = GetParam().version;
-  // If the test is using legacy TLS versions, explicitly disable warnings
-  // (e.g., to cover cases like post-interstitial or when legacy TLS is
-  // explicitly allowed via configuration).
-  if (GetParam().version < SSL_PROTOCOL_VERSION_TLS1_2)
-    client_context_config.version_min_warn = SSL_PROTOCOL_VERSION_TLS1;
   ssl_config_service_->UpdateSSLConfigAndNotify(client_context_config);
 
   SSLConfig client_config;
@@ -5574,151 +5543,6 @@
   }
 }
 
-// Set version_min_warn to TLS 1.2 and check that TLS 1.0 and 1.1 fail (with the
-// expected error and cert status) but TLS 1.2 and 1.3 pass.
-TEST_F(SSLClientSocketTest, SetVersionMinWarnToTLS12) {
-  const struct TestCase {
-    uint16_t ssl_version;
-    int expected_net_error;
-    CertStatus expected_cert_status;
-  } kTestCases[]{
-      {SSL_PROTOCOL_VERSION_TLS1, ERR_SSL_OBSOLETE_VERSION,
-       CERT_STATUS_LEGACY_TLS},
-      {SSL_PROTOCOL_VERSION_TLS1_1, ERR_SSL_OBSOLETE_VERSION,
-       CERT_STATUS_LEGACY_TLS},
-      {SSL_PROTOCOL_VERSION_TLS1_2, OK, 0},
-      {SSL_PROTOCOL_VERSION_TLS1_3, OK, 0},
-  };
-
-  for (const auto& test_case : kTestCases) {
-    SCOPED_TRACE(test_case.ssl_version);
-
-    SSLServerConfig server_config;
-    server_config.version_min = test_case.ssl_version;
-    server_config.version_max = test_case.ssl_version;
-    ASSERT_TRUE(
-        StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config));
-
-    SSLContextConfig client_context_config;
-    client_context_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
-    client_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
-    client_context_config.version_min_warn = SSL_PROTOCOL_VERSION_TLS1_2;
-    ssl_config_service_->UpdateSSLConfigAndNotify(client_context_config);
-
-    SSLConfig client_config;
-
-    // Try to connect, then check that the expected error is returned and no
-    // unexpected cert_status are set.
-    int rv;
-    ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
-    EXPECT_THAT(rv, IsError(test_case.expected_net_error));
-    SSLInfo info;
-    ASSERT_TRUE(sock_->GetSSLInfo(&info));
-    EXPECT_EQ(test_case.expected_cert_status,
-              info.cert_status & test_case.expected_cert_status);
-    net::CertStatus extra_cert_errors =
-        test_case.expected_cert_status ^
-        (info.cert_status & CERT_STATUS_ALL_ERRORS);
-    EXPECT_FALSE(extra_cert_errors);
-  }
-}
-
-// Check that TLS 1.0 and TLS 1.1 failure is bypassed when you add
-// allowed_bad_certs (with the expected error and cert status).
-TEST_F(SSLClientSocketTest, NoErrorWhenAddedToAllowedBadCerts) {
-  SSLServerConfig server_config;
-  server_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
-  server_config.version_max = SSL_PROTOCOL_VERSION_TLS1;
-  ASSERT_TRUE(
-      StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config));
-
-  SSLConfig client_config;
-  client_config.allowed_bad_certs.emplace_back(
-      embedded_test_server()->GetCertificate(), CERT_STATUS_LEGACY_TLS);
-
-  // Connection should proceed without a net error but with
-  // CERT_STATUS_LEGACY_TLS.
-  int rv;
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
-  EXPECT_THAT(rv, IsOk());
-  SSLInfo info;
-  ASSERT_TRUE(sock_->GetSSLInfo(&info));
-  EXPECT_EQ(CERT_STATUS_LEGACY_TLS, info.cert_status);
-}
-
-// Check that if the we have bypassed a certificate error previously and then
-// the server responded with TLS 1.0, we fill in both cert status flags.
-TEST_F(SSLClientSocketTest, BypassedCertShouldSetLegacyTLSStatus) {
-  SSLServerConfig server_config;
-  server_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
-  server_config.version_max = SSL_PROTOCOL_VERSION_TLS1;
-  ASSERT_TRUE(StartEmbeddedTestServer(EmbeddedTestServer::CERT_MISMATCHED_NAME,
-                                      server_config));
-  cert_verifier_->set_default_result(ERR_CERT_COMMON_NAME_INVALID);
-
-  SSLConfig client_config;
-  client_config.allowed_bad_certs.emplace_back(
-      embedded_test_server()->GetCertificate(),
-      CERT_STATUS_COMMON_NAME_INVALID);
-
-  // Connection should proceed, and CERT_STATUS_LEGACY_TLS and
-  // CERT_STATUS_COMMON_NAME_INVALID should be set.
-  int rv;
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
-  EXPECT_THAT(rv, IsOk());
-  SSLInfo info;
-  ASSERT_TRUE(sock_->GetSSLInfo(&info));
-  EXPECT_TRUE(info.cert_status & CERT_STATUS_LEGACY_TLS);
-  EXPECT_TRUE(info.cert_status & CERT_STATUS_COMMON_NAME_INVALID);
-}
-
-// Checks that other errors are prioritized over legacy TLS errors.
-TEST_F(SSLClientSocketTest, PrioritizeCertErrorsOverLegacyTLS) {
-  SSLServerConfig server_config;
-  server_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
-  server_config.version_max = SSL_PROTOCOL_VERSION_TLS1;
-  ASSERT_TRUE(
-      StartEmbeddedTestServer(EmbeddedTestServer::CERT_EXPIRED, server_config));
-  cert_verifier_->set_default_result(ERR_CERT_DATE_INVALID);
-
-  SSLConfig client_config;
-
-  // Connection should fail with ERR_CERT_DATE_INVALID and only the date invalid
-  // cert status.
-  int rv;
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
-  EXPECT_THAT(rv, IsError(ERR_CERT_DATE_INVALID));
-  SSLInfo info;
-  ASSERT_TRUE(sock_->GetSSLInfo(&info));
-  EXPECT_FALSE(info.cert_status & CERT_STATUS_LEGACY_TLS);
-  EXPECT_TRUE(info.cert_status & CERT_STATUS_DATE_INVALID);
-}
-
-// Checks that legacy TLS errors are not fatal.
-TEST_F(SSLClientSocketTest, LegacyTLSErrorsNotFatal) {
-  SSLServerConfig server_config;
-  server_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
-  server_config.version_max = SSL_PROTOCOL_VERSION_TLS1;
-  ASSERT_TRUE(
-      StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config));
-
-  SSLConfig client_config;
-
-  // Connection should fail with ERR_SSL_OBSOLETE_VERSION and the legacy TLS
-  // cert status.
-  int rv;
-  const base::Time expiry = base::Time::Now() + base::Seconds(1000);
-  transport_security_state_->AddHSTS(host_port_pair().host(), expiry, true);
-  ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
-  EXPECT_THAT(rv, IsError(ERR_SSL_OBSOLETE_VERSION));
-  SSLInfo info;
-  ASSERT_TRUE(sock_->GetSSLInfo(&info));
-  EXPECT_TRUE(info.cert_status & CERT_STATUS_LEGACY_TLS);
-
-  // The error should not be marked as fatal.
-  EXPECT_FALSE(info.is_fatal_cert_error);
-}
-
 TEST_F(SSLClientSocketZeroRTTTest, EarlyDataReasonNewSession) {
   const char kReasonHistogram[] = "Net.SSLHandshakeEarlyDataReason";
 
diff --git a/net/spdy/multiplexed_session.cc b/net/spdy/multiplexed_session.cc
index 08cdbbd..06bd12a 100644
--- a/net/spdy/multiplexed_session.cc
+++ b/net/spdy/multiplexed_session.cc
@@ -33,9 +33,9 @@
   has_ssl_info_ = session_->GetSSLInfo(&ssl_info_);
 }
 
-base::StringPiece MultiplexedSessionHandle::GetAcceptChViaAlpsForOrigin(
-    const url::Origin& origin) const {
-  return session_ ? session_->GetAcceptChViaAlpsForOrigin(origin)
+base::StringPiece MultiplexedSessionHandle::GetAcceptChViaAlps(
+    const url::SchemeHostPort& scheme_host_port) const {
+  return session_ ? session_->GetAcceptChViaAlps(scheme_host_port)
                   : base::StringPiece();
 }
 
diff --git a/net/spdy/multiplexed_session.h b/net/spdy/multiplexed_session.h
index 49d3ebc..c5110cc2 100644
--- a/net/spdy/multiplexed_session.h
+++ b/net/spdy/multiplexed_session.h
@@ -10,7 +10,10 @@
 #include "net/base/net_errors.h"
 #include "net/http/http_stream.h"
 #include "net/ssl/ssl_info.h"
-#include "url/origin.h"
+
+namespace url {
+class SchemeHostPort;
+}
 
 namespace net {
 
@@ -27,12 +30,16 @@
   // and does not modify |endpoint| if it is unavailable.
   virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0;
 
-  // The value corresponding to |origin| in the ACCEPT_CH frame received
-  // during TLS handshake via the ALPS extension, or the empty string if the
-  // server did not send one.  Unlike Accept-CH header fields received in HTTP
-  // responses, this value is available before any requests are made.
-  virtual base::StringPiece GetAcceptChViaAlpsForOrigin(
-      const url::Origin& origin) const = 0;
+  // The value corresponding to |scheme_host_port| in the ACCEPT_CH frame
+  // received during TLS handshake via the ALPS extension, or the empty string
+  // if the server did not send one.  Unlike Accept-CH header fields received in
+  // HTTP responses, this value is available before any requests are made.
+  //
+  // Note that this uses url::SchemeHostPort instead of url::Origin because this
+  // is based around network authorities, as opposed to general RFC 6454
+  // origins.
+  virtual base::StringPiece GetAcceptChViaAlps(
+      const url::SchemeHostPort& scheme_host_port) const = 0;
 };
 
 // A handle to a multiplexed session which will be valid even after the
@@ -53,11 +60,16 @@
   // Caches SSL info from the underlying session.
   void SaveSSLInfo();
 
-  // The value corresponding to |origin| in the ACCEPT_CH frame received
-  // during TLS handshake via the ALPS extension, or the empty string if the
-  // server did not send one or if the underlying session is not available.
-  base::StringPiece GetAcceptChViaAlpsForOrigin(
-      const url::Origin& origin) const;
+  // The value corresponding to |scheme_host_port| in the ACCEPT_CH frame
+  // received during TLS handshake via the ALPS extension, or the empty string
+  // if the server did not send one or if the underlying session is not
+  // available.
+  //
+  // Note that this uses url::SchemeHostPort instead of url::Origin because this
+  // is based around network authorities, as opposed to general RFC 6454
+  // origins.
+  virtual base::StringPiece GetAcceptChViaAlps(
+      const url::SchemeHostPort& scheme_host_port) const;
 
  private:
   base::WeakPtr<MultiplexedSession> session_;
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 57feac8..b3b3820 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -29,7 +29,7 @@
 #include "net/spdy/spdy_session.h"
 #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
 #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
-#include "url/origin.h"
+#include "url/scheme_host_port.h"
 
 namespace net {
 
@@ -721,8 +721,7 @@
     return {};
   }
 
-  const url::Origin origin = url::Origin::Create(request_info_->url);
-  return session()->GetAcceptChViaAlpsForOrigin(origin);
+  return session()->GetAcceptChViaAlps(url::SchemeHostPort(request_info_->url));
 }
 
 }  // namespace net
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index b33a7294..4766a5b 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -1146,21 +1146,16 @@
   bool has_valid_entry = false;
   bool has_invalid_entry = false;
   for (const auto& entry : alps_decoder.GetAcceptCh()) {
-    // |entry.origin| must be a valid origin.
-    GURL url(entry.origin);
-    if (!url.is_valid()) {
-      has_invalid_entry = true;
-      continue;
-    }
-    const url::Origin origin = url::Origin::Create(url);
-    std::string serialized = origin.Serialize();
+    const url::SchemeHostPort scheme_host_port(GURL(entry.origin));
+    // |entry.origin| must be a valid SchemeHostPort.
+    std::string serialized = scheme_host_port.Serialize();
     if (serialized.empty() || entry.origin != serialized) {
       has_invalid_entry = true;
       continue;
     }
     has_valid_entry = true;
     accept_ch_entries_received_via_alps_.insert(
-        std::make_pair(std::move(origin), entry.value));
+        std::make_pair(std::move(scheme_host_port), entry.value));
   }
 
   SpdyAcceptChEntries value;
@@ -1498,9 +1493,9 @@
   return socket_->GetSSLInfo(ssl_info);
 }
 
-base::StringPiece SpdySession::GetAcceptChViaAlpsForOrigin(
-    const url::Origin& origin) const {
-  auto it = accept_ch_entries_received_via_alps_.find(origin);
+base::StringPiece SpdySession::GetAcceptChViaAlps(
+    const url::SchemeHostPort& scheme_host_port) const {
+  auto it = accept_ch_entries_received_via_alps_.find(scheme_host_port);
   if (it == accept_ch_entries_received_via_alps_.end()) {
     LogSpdyAcceptChForOriginHistogram(false);
     return {};
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index abaf1fd..0152b1c9 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -514,8 +514,8 @@
   // MultiplexedSession methods:
   bool GetRemoteEndpoint(IPEndPoint* endpoint) override;
   bool GetSSLInfo(SSLInfo* ssl_info) const override;
-  base::StringPiece GetAcceptChViaAlpsForOrigin(
-      const url::Origin& origin) const override;
+  base::StringPiece GetAcceptChViaAlps(
+      const url::SchemeHostPort& scheme_host_port) const override;
 
   // Returns true if ALPN was negotiated for the underlying socket.
   bool WasAlpnNegotiated() const;
@@ -1290,7 +1290,8 @@
   Http2PriorityDependencies priority_dependency_state_;
 
   // Map of origin to Accept-CH header field values received via ALPS.
-  base::flat_map<url::Origin, std::string> accept_ch_entries_received_via_alps_;
+  base::flat_map<url::SchemeHostPort, std::string>
+      accept_ch_entries_received_via_alps_;
 
   // Network quality estimator to which the ping RTTs should be reported. May be
   // nullptr.
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 0e33550d..ca8aacd 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -7316,8 +7316,8 @@
                                       kNoEntries, 1);
 
   histogram_tester.ExpectTotalCount("Net.SpdySession.AcceptChForOrigin", 0);
-  EXPECT_EQ("", session_->GetAcceptChViaAlpsForOrigin(
-                    url::Origin::Create(GURL("https://www.example.org"))));
+  EXPECT_EQ("", session_->GetAcceptChViaAlps(
+                    url::SchemeHostPort(GURL("https://www.example.org"))));
   histogram_tester.ExpectUniqueSample("Net.SpdySession.AcceptChForOrigin",
                                       false, 1);
 }
@@ -7378,13 +7378,13 @@
 
   histogram_tester.ExpectTotalCount("Net.SpdySession.AcceptChForOrigin", 0);
 
-  EXPECT_EQ("foo", session_->GetAcceptChViaAlpsForOrigin(
-                       url::Origin::Create(GURL("https://www.example.com"))));
+  EXPECT_EQ("foo", session_->GetAcceptChViaAlps(
+                       url::SchemeHostPort(GURL("https://www.example.com"))));
   histogram_tester.ExpectUniqueSample("Net.SpdySession.AcceptChForOrigin", true,
                                       1);
 
-  EXPECT_EQ("", session_->GetAcceptChViaAlpsForOrigin(
-                    url::Origin::Create(GURL("https://www.example.org"))));
+  EXPECT_EQ("", session_->GetAcceptChViaAlps(
+                    url::SchemeHostPort(GURL("https://www.example.org"))));
   histogram_tester.ExpectTotalCount("Net.SpdySession.AcceptChForOrigin", 2);
   histogram_tester.ExpectBucketCount("Net.SpdySession.AcceptChForOrigin", true,
                                      1);
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc
index bdb1f3d1..603de2c2 100644
--- a/net/ssl/ssl_config.cc
+++ b/net/ssl/ssl_config.cc
@@ -10,8 +10,7 @@
 
 // Note these lines must be kept in sync with
 // services/network/public/mojom/ssl_config.mojom.
-const uint16_t kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_TLS1;
-const uint16_t kDefaultSSLVersionMinWarn = SSL_PROTOCOL_VERSION_TLS1_2;
+const uint16_t kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_TLS1_2;
 const uint16_t kDefaultSSLVersionMax = SSL_PROTOCOL_VERSION_TLS1_3;
 
 SSLConfig::CertAndStatus::CertAndStatus() = default;
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h
index 5fba4dc..811cdf0 100644
--- a/net/ssl/ssl_config.h
+++ b/net/ssl/ssl_config.h
@@ -36,9 +36,6 @@
 // Default minimum protocol version.
 NET_EXPORT extern const uint16_t kDefaultSSLVersionMin;
 
-// Default minimum protocol version to warn about.
-NET_EXPORT extern const uint16_t kDefaultSSLVersionMinWarn;
-
 // Default maximum protocol version.
 NET_EXPORT extern const uint16_t kDefaultSSLVersionMax;
 
diff --git a/net/ssl/ssl_config_service.cc b/net/ssl/ssl_config_service.cc
index eaacabd..bda2ddc6 100644
--- a/net/ssl/ssl_config_service.cc
+++ b/net/ssl/ssl_config_service.cc
@@ -16,12 +16,10 @@
 // same.
 bool SSLContextConfigsAreEqual(const net::SSLContextConfig& config1,
                                const net::SSLContextConfig& config2) {
-  return std::tie(config1.version_min, config1.version_min_warn,
-                  config1.version_max, config1.disabled_cipher_suites,
-                  config1.cecpq2_enabled) ==
-         std::tie(config2.version_min, config2.version_min_warn,
-                  config2.version_max, config2.disabled_cipher_suites,
-                  config2.cecpq2_enabled);
+  return std::tie(config1.version_min, config1.version_max,
+                  config1.disabled_cipher_suites, config1.cecpq2_enabled) ==
+         std::tie(config2.version_min, config2.version_max,
+                  config2.disabled_cipher_suites, config2.cecpq2_enabled);
 }
 
 }  // namespace
diff --git a/net/ssl/ssl_config_service.h b/net/ssl/ssl_config_service.h
index 070a52b..9d1e97d2 100644
--- a/net/ssl/ssl_config_service.h
+++ b/net/ssl/ssl_config_service.h
@@ -24,14 +24,9 @@
 
   // The minimum and maximum protocol versions that are enabled.
   // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined in ssl_config.h.)
-  // SSL 2.0 and SSL 3.0 are not supported. If version_max < version_min, it
-  // means no protocol versions are enabled.
-  //
-  // version_min_warn is the minimum protocol version that won't cause cert
-  // errors (e.g., in Chrome we'll show a security interstitial for connections
-  // using a version lower than version_min_warn).
+  // SSL 2.0/3.0 and TLS 1.0/1.1 are not supported. If version_max <
+  // version_min, it means no protocol versions are enabled.
   uint16_t version_min = kDefaultSSLVersionMin;
-  uint16_t version_min_warn = kDefaultSSLVersionMinWarn;
   uint16_t version_max = kDefaultSSLVersionMax;
 
   // Presorted list of cipher suites which should be explicitly prevented from
diff --git a/net/test/spawned_test_server/base_test_server.cc b/net/test/spawned_test_server/base_test_server.cc
index 04fcd16..c1bfd46f 100644
--- a/net/test/spawned_test_server/base_test_server.cc
+++ b/net/test/spawned_test_server/base_test_server.cc
@@ -148,8 +148,6 @@
   switch (type_) {
     case TYPE_HTTP:
       return "http";
-    case TYPE_HTTPS:
-      return "https";
     case TYPE_WS:
       return "ws";
     case TYPE_WSS:
@@ -435,10 +433,6 @@
     }
   }
 
-  if (type_ == TYPE_HTTPS) {
-    arguments->SetKey("https", base::Value());
-  }
-
   return GenerateAdditionalArguments(arguments);
 }
 
diff --git a/net/test/spawned_test_server/base_test_server.h b/net/test/spawned_test_server/base_test_server.h
index f9db4c9..0ddb207 100644
--- a/net/test/spawned_test_server/base_test_server.h
+++ b/net/test/spawned_test_server/base_test_server.h
@@ -40,7 +40,6 @@
   enum Type {
     TYPE_BASIC_AUTH_PROXY,
     TYPE_HTTP,
-    TYPE_HTTPS,
     TYPE_WS,
     TYPE_WSS,
     TYPE_PROXY,
@@ -167,10 +166,7 @@
       const std::vector<StringPair>& text_to_replace,
       std::string* replacement_path);
 
-  static bool UsingSSL(Type type) {
-    return type == BaseTestServer::TYPE_HTTPS ||
-           type == BaseTestServer::TYPE_WSS;
-  }
+  static bool UsingSSL(Type type) { return type == BaseTestServer::TYPE_WSS; }
 
   // Enable HTTP basic authentication. Currently this only works for TYPE_WS and
   // TYPE_WSS.
diff --git a/net/test/spawned_test_server/local_test_server.cc b/net/test/spawned_test_server/local_test_server.cc
index cb87253b..6c039ee 100644
--- a/net/test/spawned_test_server/local_test_server.cc
+++ b/net/test/spawned_test_server/local_test_server.cc
@@ -174,7 +174,6 @@
   third_party_dir = third_party_dir.AppendASCII("third_party");
 
   std::vector<base::FilePath> ret = {
-      third_party_dir.AppendASCII("tlslite"),
       third_party_dir.AppendASCII("pywebsocket3").AppendASCII("src"),
   };
 
@@ -219,9 +218,6 @@
   switch (type()) {
     case TYPE_HTTP:  // The default type is HTTP, no argument required.
       break;
-    case TYPE_HTTPS:
-      command_line->AppendArg("--https");
-      break;
     case TYPE_WS:
     case TYPE_WSS:
       command_line->AppendArg("--websocket");
diff --git a/net/test/spawned_test_server/remote_test_server.cc b/net/test/spawned_test_server/remote_test_server.cc
index 9891783..597a752 100644
--- a/net/test/spawned_test_server/remote_test_server.cc
+++ b/net/test/spawned_test_server/remote_test_server.cc
@@ -37,7 +37,6 @@
 std::string GetServerTypeString(BaseTestServer::Type type) {
   switch (type) {
     case BaseTestServer::TYPE_HTTP:
-    case BaseTestServer::TYPE_HTTPS:
       return "http";
     case BaseTestServer::TYPE_WS:
     case BaseTestServer::TYPE_WSS:
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn
index 4f2ef16..80382a4d 100644
--- a/net/third_party/quiche/BUILD.gn
+++ b/net/third_party/quiche/BUILD.gn
@@ -279,6 +279,8 @@
     "src/quic/core/crypto/proof_source.cc",
     "src/quic/core/crypto/proof_source.h",
     "src/quic/core/crypto/proof_verifier.h",
+    "src/quic/core/crypto/quic_client_session_cache.cc",
+    "src/quic/core/crypto/quic_client_session_cache.h",
     "src/quic/core/crypto/quic_compressed_certs_cache.cc",
     "src/quic/core/crypto/quic_compressed_certs_cache.h",
     "src/quic/core/crypto/quic_crypter.cc",
@@ -1359,6 +1361,7 @@
     "src/quic/core/crypto/null_decrypter_test.cc",
     "src/quic/core/crypto/null_encrypter_test.cc",
     "src/quic/core/crypto/p256_key_exchange_test.cc",
+    "src/quic/core/crypto/quic_client_session_cache_test.cc",
     "src/quic/core/crypto/quic_compressed_certs_cache_test.cc",
     "src/quic/core/crypto/quic_crypto_client_config_test.cc",
     "src/quic/core/crypto/quic_crypto_server_config_test.cc",
diff --git a/net/tools/testserver/run_testserver.cc b/net/tools/testserver/run_testserver.cc
index c3ea0e3d..3bfabcf 100644
--- a/net/tools/testserver/run_testserver.cc
+++ b/net/tools/testserver/run_testserver.cc
@@ -52,14 +52,13 @@
   }
 
   // If populated, EmbeddedTestServer is used instead of the SpawnedTestServer.
-  absl::optional<net::test_server::EmbeddedTestServer::Type>
-      embedded_test_server_type;
+  absl::optional<net::EmbeddedTestServer::Type> embedded_test_server_type;
 
   net::SpawnedTestServer::Type server_type;
   if (command_line->HasSwitch("http")) {
-    embedded_test_server_type = net::test_server::EmbeddedTestServer::TYPE_HTTP;
+    embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP;
   } else if (command_line->HasSwitch("https")) {
-    server_type = net::SpawnedTestServer::TYPE_HTTPS;
+    embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS;
   } else if (command_line->HasSwitch("ws")) {
     server_type = net::SpawnedTestServer::TYPE_WS;
   } else if (command_line->HasSwitch("wss")) {
@@ -68,17 +67,19 @@
     // If no scheme switch is specified, select http or https scheme.
     // TODO(toyoshim): Remove this estimation.
     if (command_line->HasSwitch("ssl-cert")) {
-      server_type = net::SpawnedTestServer::TYPE_HTTPS;
+      embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTPS;
     } else {
-      embedded_test_server_type =
-          net::test_server::EmbeddedTestServer::TYPE_HTTP;
+      embedded_test_server_type = net::EmbeddedTestServer::TYPE_HTTP;
     }
   }
 
   net::SpawnedTestServer::SSLOptions ssl_options;
+  net::EmbeddedTestServer::ServerCertificate server_certificate;
   if (command_line->HasSwitch("ssl-cert")) {
-    if (!net::SpawnedTestServer::UsingSSL(server_type) ||
-        embedded_test_server_type.has_value()) {
+    if ((embedded_test_server_type.has_value() &&
+         *embedded_test_server_type != net::EmbeddedTestServer::TYPE_HTTPS) ||
+        (!embedded_test_server_type.has_value() &&
+         !net::SpawnedTestServer::UsingSSL(server_type))) {
       printf("Error: --ssl-cert is specified on non-secure scheme\n");
       PrintUsage();
       return -1;
@@ -87,12 +88,15 @@
     if (cert_option == "ok") {
       ssl_options.server_certificate =
           net::SpawnedTestServer::SSLOptions::CERT_OK;
+      server_certificate = net::EmbeddedTestServer::CERT_OK;
     } else if (cert_option == "mismatched-name") {
       ssl_options.server_certificate =
           net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
+      server_certificate = net::EmbeddedTestServer::CERT_MISMATCHED_NAME;
     } else if (cert_option == "expired") {
       ssl_options.server_certificate =
           net::SpawnedTestServer::SSLOptions::CERT_EXPIRED;
+      server_certificate = net::EmbeddedTestServer::CERT_EXPIRED;
     } else {
       printf("Error: --ssl-cert has invalid value %s\n", cert_option.c_str());
       PrintUsage();
@@ -118,8 +122,11 @@
 
   // Use EmbeddedTestServer, if it supports the provided configuration.
   if (embedded_test_server_type.has_value()) {
-    net::test_server::EmbeddedTestServer embedded_test_server(
-        *embedded_test_server_type);
+    net::EmbeddedTestServer embedded_test_server(*embedded_test_server_type);
+    if (*embedded_test_server_type == net::EmbeddedTestServer::TYPE_HTTPS) {
+      embedded_test_server.SetSSLConfig(server_certificate);
+    }
+
     embedded_test_server.AddDefaultHandlers(doc_root);
     if (!embedded_test_server.Start()) {
       printf("Error: failed to start embedded test server. Exiting.\n");
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index 594c0f3d..ef1b78c 100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -10,8 +10,6 @@
 By default, it listens on an ephemeral port and sends the port number back to
 the originating process over a pipe. The originating process can specify an
 explicit port if necessary.
-It can use https if you specify the flag --https=CERT where CERT is the path
-to a pem file containing the certificate and private key that should be used.
 """
 
 from __future__ import print_function
@@ -33,16 +31,12 @@
 # unconditionally (since they contain modifications from anything that might be
 # obtained from e.g. PyPi).
 sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party', 'pywebsocket3', 'src'))
-sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party', 'tlslite'))
 
 import mod_pywebsocket.standalone
 from mod_pywebsocket.standalone import WebSocketServer
 # import manually
 mod_pywebsocket.standalone.ssl = ssl
 
-import tlslite
-import tlslite.api
-
 import testserver_base
 
 SERVER_HTTP = 0
@@ -93,64 +87,6 @@
   pass
 
 
-class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
-                  testserver_base.ClientRestrictingServerMixIn,
-                  testserver_base.BrokenPipeHandlerMixIn,
-                  testserver_base.StoppableHTTPServer):
-  """This is a specialization of StoppableHTTPServer that add https support and
-  client verification."""
-
-  def __init__(self, server_address, request_hander_class, pem_cert_and_key,
-               ssl_client_auth, ssl_client_cas):
-    self.cert_chain = tlslite.api.X509CertChain()
-    self.cert_chain.parsePemList(pem_cert_and_key)
-    # Force using only python implementation - otherwise behavior is different
-    # depending on whether m2crypto Python module is present (error is thrown
-    # when it is). m2crypto uses a C (based on OpenSSL) implementation under
-    # the hood.
-    self.private_key = tlslite.api.parsePEMKey(pem_cert_and_key,
-                                               private=True,
-                                               implementations=['python'])
-    self.ssl_client_auth = ssl_client_auth
-    self.ssl_client_cas = []
-
-    if ssl_client_auth:
-      for ca_file in ssl_client_cas:
-        s = open(ca_file).read()
-        x509 = tlslite.api.X509()
-        x509.parse(s)
-        self.ssl_client_cas.append(x509.subject)
-
-    self.ssl_handshake_settings = tlslite.api.HandshakeSettings()
-    # Enable SSLv3 for testing purposes.
-    self.ssl_handshake_settings.minVersion = (3, 0)
-
-    self.session_cache = tlslite.api.SessionCache()
-    testserver_base.StoppableHTTPServer.__init__(self,
-                                                 server_address,
-                                                 request_hander_class)
-
-  def handshake(self, tlsConnection):
-    """Creates the SSL connection."""
-
-    try:
-      self.tlsConnection = tlsConnection
-      tlsConnection.handshakeServer(certChain=self.cert_chain,
-                                    privateKey=self.private_key,
-                                    sessionCache=self.session_cache,
-                                    reqCert=self.ssl_client_auth,
-                                    settings=self.ssl_handshake_settings,
-                                    reqCAs=self.ssl_client_cas)
-      tlsConnection.ignoreAbruptClose = True
-      return True
-    except tlslite.api.TLSAbruptCloseError:
-      # Ignore abrupt close.
-      return True
-    except tlslite.api.TLSError as error:
-      print("Handshake failure:", str(error))
-      return False
-
-
 class TestPageHandler(testserver_base.BasePageHandler):
   def __init__(self, request, client_address, socket_server):
     connect_handlers = [self.DefaultConnectResponseHandler]
@@ -372,30 +308,9 @@
       dns_sans = [host]
 
     if self.options.server_type == SERVER_HTTP:
-      if self.options.https:
-        if not self.options.cert_and_key_file:
-          raise testserver_base.OptionError('server cert file not specified')
-        if not os.path.isfile(self.options.cert_and_key_file):
-          raise testserver_base.OptionError(
-              'specified server cert file not found: ' +
-              self.options.cert_and_key_file + ' exiting...')
-        pem_cert_and_key = open(self.options.cert_and_key_file, 'r').read()
-
-        for ca_cert in self.options.ssl_client_ca:
-          if not os.path.isfile(ca_cert):
-            raise testserver_base.OptionError(
-                'specified trusted client CA file not found: ' + ca_cert +
-                ' exiting...')
-
-        server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
-                             self.options.ssl_client_auth,
-                             self.options.ssl_client_ca)
-        print('HTTPS server started on https://%s:%d...' %
-              (host, server.server_port))
-      else:
-        server = HTTPServer((host, port), TestPageHandler)
-        print('HTTP server started on http://%s:%d...' %
-              (host, server.server_port))
+      server = HTTPServer((host, port), TestPageHandler)
+      print('HTTP server started on http://%s:%d...' %
+            (host, server.server_port))
 
       server.data_dir = self.__make_data_dir()
       server.file_root_url = self.options.file_root_url
@@ -468,9 +383,6 @@
                                   const=SERVER_WEBSOCKET, default=SERVER_HTTP,
                                   dest='server_type',
                                   help='start up a WebSocket server.')
-    self.option_parser.add_option('--https', action='store_true',
-                                  dest='https', help='Specify that https '
-                                  'should be used.')
     self.option_parser.add_option('--cert-and-key-file',
                                   dest='cert_and_key_file', help='specify the '
                                   'path to the file containing the certificate '
diff --git a/net/tools/testserver/testserver.pydeps b/net/tools/testserver/testserver.pydeps
index 013a778c..a4deed6 100644
--- a/net/tools/testserver/testserver.pydeps
+++ b/net/tools/testserver/testserver.pydeps
@@ -1,5 +1,5 @@
 # Generated by running:
-#   build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps --allowlist third_party/tlslite/tlslite/utils net/tools/testserver/testserver.py
+#   build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps net/tools/testserver/testserver.py
 ../../../third_party/pywebsocket3/src/mod_pywebsocket/__init__.py
 ../../../third_party/pywebsocket3/src/mod_pywebsocket/_stream_exceptions.py
 ../../../third_party/pywebsocket3/src/mod_pywebsocket/common.py
@@ -17,62 +17,5 @@
 ../../../third_party/pywebsocket3/src/mod_pywebsocket/stream.py
 ../../../third_party/pywebsocket3/src/mod_pywebsocket/util.py
 ../../../third_party/pywebsocket3/src/mod_pywebsocket/websocket_server.py
-../../../third_party/tlslite/tlslite/__init__.py
-../../../third_party/tlslite/tlslite/api.py
-../../../third_party/tlslite/tlslite/basedb.py
-../../../third_party/tlslite/tlslite/checker.py
-../../../third_party/tlslite/tlslite/constants.py
-../../../third_party/tlslite/tlslite/errors.py
-../../../third_party/tlslite/tlslite/handshakesettings.py
-../../../third_party/tlslite/tlslite/integration/__init__.py
-../../../third_party/tlslite/tlslite/integration/asyncstatemachine.py
-../../../third_party/tlslite/tlslite/integration/clienthelper.py
-../../../third_party/tlslite/tlslite/integration/httptlsconnection.py
-../../../third_party/tlslite/tlslite/integration/imap4_tls.py
-../../../third_party/tlslite/tlslite/integration/pop3_tls.py
-../../../third_party/tlslite/tlslite/integration/smtp_tls.py
-../../../third_party/tlslite/tlslite/integration/tlsasyncdispatchermixin.py
-../../../third_party/tlslite/tlslite/integration/tlssocketservermixin.py
-../../../third_party/tlslite/tlslite/integration/xmlrpcserver.py
-../../../third_party/tlslite/tlslite/integration/xmlrpctransport.py
-../../../third_party/tlslite/tlslite/mathtls.py
-../../../third_party/tlslite/tlslite/messages.py
-../../../third_party/tlslite/tlslite/session.py
-../../../third_party/tlslite/tlslite/sessioncache.py
-../../../third_party/tlslite/tlslite/tlsconnection.py
-../../../third_party/tlslite/tlslite/tlsrecordlayer.py
-../../../third_party/tlslite/tlslite/utils/__init__.py
-../../../third_party/tlslite/tlslite/utils/aes.py
-../../../third_party/tlslite/tlslite/utils/aesgcm.py
-../../../third_party/tlslite/tlslite/utils/asn1parser.py
-../../../third_party/tlslite/tlslite/utils/cipherfactory.py
-../../../third_party/tlslite/tlslite/utils/codec.py
-../../../third_party/tlslite/tlslite/utils/compat.py
-../../../third_party/tlslite/tlslite/utils/cryptomath.py
-../../../third_party/tlslite/tlslite/utils/datefuncs.py
-../../../third_party/tlslite/tlslite/utils/keyfactory.py
-../../../third_party/tlslite/tlslite/utils/openssl_aes.py
-../../../third_party/tlslite/tlslite/utils/openssl_rc4.py
-../../../third_party/tlslite/tlslite/utils/openssl_rsakey.py
-../../../third_party/tlslite/tlslite/utils/openssl_tripledes.py
-../../../third_party/tlslite/tlslite/utils/p256.py
-../../../third_party/tlslite/tlslite/utils/pem.py
-../../../third_party/tlslite/tlslite/utils/pycrypto_aes.py
-../../../third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
-../../../third_party/tlslite/tlslite/utils/pycrypto_rc4.py
-../../../third_party/tlslite/tlslite/utils/pycrypto_rsakey.py
-../../../third_party/tlslite/tlslite/utils/pycrypto_tripledes.py
-../../../third_party/tlslite/tlslite/utils/python_aes.py
-../../../third_party/tlslite/tlslite/utils/python_aesgcm.py
-../../../third_party/tlslite/tlslite/utils/python_rc4.py
-../../../third_party/tlslite/tlslite/utils/python_rsakey.py
-../../../third_party/tlslite/tlslite/utils/rc4.py
-../../../third_party/tlslite/tlslite/utils/rijndael.py
-../../../third_party/tlslite/tlslite/utils/rsakey.py
-../../../third_party/tlslite/tlslite/utils/tackwrapper.py
-../../../third_party/tlslite/tlslite/utils/tripledes.py
-../../../third_party/tlslite/tlslite/verifierdb.py
-../../../third_party/tlslite/tlslite/x509.py
-../../../third_party/tlslite/tlslite/x509certchain.py
 testserver.py
 testserver_base.py
diff --git a/net/tools/testserver/testserver_base.py b/net/tools/testserver/testserver_base.py
index 25cb7af..319afd4e 100644
--- a/net/tools/testserver/testserver_base.py
+++ b/net/tools/testserver/testserver_base.py
@@ -14,8 +14,6 @@
 import sys
 import warnings
 
-import tlslite.errors
-
 # Ignore deprecation warnings, they make our output more cluttered.
 warnings.filterwarnings("ignore", category=DeprecationWarning)
 
@@ -73,9 +71,6 @@
 
   def handle_error(self, request, client_address):
     value = sys.exc_info()[1]
-    if isinstance(value, tlslite.errors.TLSClosedConnectionError):
-      print("testserver.py: Closed connection")
-      return
     if isinstance(value, socket.error):
       err = value.args[0]
       if sys.platform in ('win32', 'cygwin'):
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 3f505c8..a63f5da 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -2184,12 +2184,14 @@
 
   std::u16string result;
   for (size_t i = 0; i < selection_.size(); ++i) {
-    static constexpr char16_t kNewLineChar = L'\n';
     std::u16string current_selection_text = selection_[i].GetText();
     if (i != 0) {
       if (selection_[i - 1].page_index() > selection_[i].page_index())
         std::swap(current_selection_text, result);
-      result.push_back(kNewLineChar);
+#if defined(OS_WIN)
+      result.push_back(L'\r');
+#endif
+      result.push_back(L'\n');
     }
     result.append(current_selection_text);
   }
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
index 7c6ea91c..3c1f8a2a 100644
--- a/pdf/pdfium/pdfium_engine_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -663,9 +663,8 @@
 
   engine->SelectAll();
 #if defined(OS_WIN)
-  // TODO(crbug.com/1269974): Make line endings more consistent.
   constexpr char kExpectedText[] =
-      "Hello, world!\r\nGoodbye, world!\nHello, world!\r\nGoodbye, world!";
+      "Hello, world!\r\nGoodbye, world!\r\nHello, world!\r\nGoodbye, world!";
 #else
   constexpr char kExpectedText[] =
       "Hello, world!\nGoodbye, world!\nHello, world!\nGoodbye, world!";
diff --git a/remoting/protocol/video_channel_state_observer.h b/remoting/protocol/video_channel_state_observer.h
index 6780f43..d0714b2 100644
--- a/remoting/protocol/video_channel_state_observer.h
+++ b/remoting/protocol/video_channel_state_observer.h
@@ -13,10 +13,6 @@
 
 class VideoChannelStateObserver {
  public:
-  // Signals to the video-scheduler that the encoder is ready to accept captured
-  // frames for encoding and sending.
-  virtual void OnEncoderReady() = 0;
-
   virtual void OnKeyFrameRequested() = 0;
   virtual void OnTargetBitrateChanged(int bitrate_kbps) = 0;
 
diff --git a/remoting/protocol/webrtc_frame_scheduler_simple.cc b/remoting/protocol/webrtc_frame_scheduler_simple.cc
index d05706f..4469f44 100644
--- a/remoting/protocol/webrtc_frame_scheduler_simple.cc
+++ b/remoting/protocol/webrtc_frame_scheduler_simple.cc
@@ -57,12 +57,6 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 }
 
-void WebrtcFrameSchedulerSimple::OnEncoderReady() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  encoder_ready_ = true;
-  ScheduleNextFrame();
-}
-
 void WebrtcFrameSchedulerSimple::OnKeyFrameRequested() {
   DCHECK(thread_checker_.CalledOnValidThread());
   key_frame_request_ = true;
@@ -147,6 +141,8 @@
 
 void WebrtcFrameSchedulerSimple::SetMaxFramerateFps(int max_framerate_fps) {
   // TODO(http://crbug.com/1268253): Implement this.
+  encoder_ready_ = true;
+  ScheduleNextFrame();
 }
 
 void WebrtcFrameSchedulerSimple::SetTickClockForTest(
diff --git a/remoting/protocol/webrtc_frame_scheduler_simple.h b/remoting/protocol/webrtc_frame_scheduler_simple.h
index 1088c5a4..e6c444d1 100644
--- a/remoting/protocol/webrtc_frame_scheduler_simple.h
+++ b/remoting/protocol/webrtc_frame_scheduler_simple.h
@@ -33,7 +33,6 @@
   ~WebrtcFrameSchedulerSimple() override;
 
   // VideoChannelStateObserver implementation.
-  void OnEncoderReady() override;
   void OnKeyFrameRequested() override;
   void OnTargetBitrateChanged(int bitrate_kbps) override;
   void OnFrameEncoded(
@@ -63,7 +62,10 @@
   base::RepeatingClosure capture_callback_;
   bool paused_ = false;
 
-  // Set to true when the encoder is ready to receive frames.
+  // Set to true when the encoder is ready to receive frames (which is when the
+  // output sink gets added to the VideoTrackSource). The sink's requested
+  // framerate will then be passed to SetMaxFramerateFps(), which will set this
+  // flag.
   bool encoder_ready_ = false;
 
   // Set to true when a key frame was requested.
diff --git a/remoting/protocol/webrtc_frame_scheduler_unittest.cc b/remoting/protocol/webrtc_frame_scheduler_unittest.cc
index cea15d5a..4b7c3458 100644
--- a/remoting/protocol/webrtc_frame_scheduler_unittest.cc
+++ b/remoting/protocol/webrtc_frame_scheduler_unittest.cc
@@ -36,7 +36,7 @@
     scheduler_->Start(
         base::BindRepeating(&WebrtcFrameSchedulerTest::CaptureCallback,
                             base::Unretained(this)));
-    scheduler_->OnEncoderReady();
+    scheduler_->SetMaxFramerateFps(30);
   }
   ~WebrtcFrameSchedulerTest() override = default;
 
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
index 6b18953..6fb285f 100644
--- a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
+++ b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
@@ -107,7 +107,6 @@
   MockVideoChannelStateObserver() = default;
   ~MockVideoChannelStateObserver() override = default;
 
-  MOCK_METHOD(void, OnEncoderReady, (), (override));
   MOCK_METHOD(void, OnKeyFrameRequested, (), (override));
   MOCK_METHOD(void, OnTargetBitrateChanged, (int bitrate_kbps), (override));
   MOCK_METHOD(void,
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc
index 8b060792..ab40828 100644
--- a/remoting/protocol/webrtc_video_stream.cc
+++ b/remoting/protocol/webrtc_video_stream.cc
@@ -123,11 +123,6 @@
   observer_ = observer;
 }
 
-void WebrtcVideoStream::OnEncoderReady() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  scheduler_->OnEncoderReady();
-}
-
 void WebrtcVideoStream::OnKeyFrameRequested() {
   DCHECK(thread_checker_.CalledOnValidThread());
   scheduler_->OnKeyFrameRequested();
@@ -187,7 +182,6 @@
 
 void WebrtcVideoStream::OnSinkAddedOrUpdated(const rtc::VideoSinkWants& wants) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  OnEncoderReady();
 
   VLOG(0) << "WebRTC requested max framerate: " << wants.max_framerate_fps
           << " FPS";
diff --git a/remoting/protocol/webrtc_video_stream.h b/remoting/protocol/webrtc_video_stream.h
index 52c80da2..83c2366d 100644
--- a/remoting/protocol/webrtc_video_stream.h
+++ b/remoting/protocol/webrtc_video_stream.h
@@ -62,7 +62,6 @@
   void SelectSource(int id) override;
 
   // VideoChannelStateObserver interface.
-  void OnEncoderReady() override;
   void OnKeyFrameRequested() override;
   void OnTargetBitrateChanged(int bitrate_kbps) override;
   void OnFrameEncoded(WebrtcVideoEncoder::EncodeResult encode_result,
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index 6bcb599..f9eea2783 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -122,12 +122,6 @@
   if (sysno == __NR_getrusage) {
     return RestrictGetrusage();
   }
-
-  if (sysno == __NR_sigaltstack) {
-    // Required for better stack overflow detection in ASan. Disallowed in
-    // non-ASan builds.
-    return Allow();
-  }
 #endif  // defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||
         // defined(MEMORY_SANITIZER)
 
@@ -156,12 +150,6 @@
     return Allow();
   }
 
-#if defined(OS_ANDROID)
-  // Needed for thread creation.
-  if (sysno == __NR_sigaltstack)
-    return Allow();
-#endif
-
 #if defined(__NR_rseq) && !defined(OS_ANDROID)
   // See https://crbug.com/1104160. Rseq can only be disabled right before an
   // execve, because glibc registers it with the kernel and so far it's unclear
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
index 374ef187..9996e3d0 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
@@ -128,7 +128,6 @@
     case __NR_set_thread_area:
 #endif
     case __NR_set_tid_address:
-    case __NR_sigaltstack:
 #if defined(__i386__) || defined(__arm__)
     case __NR_ugetrlimit:
 #else
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
index e7caffd..b3cf6fc 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
@@ -341,6 +341,11 @@
     case __NR_rt_sigprocmask:
     case __NR_rt_sigreturn:
     case __NR_rt_sigtimedwait:
+    // Used by Crashpad or Bionic to set up signal handler stacks. An alternate
+    // signal handler stack allows the kernel to deliver signals to threads
+    // whose stack pointers no longer point to their main stack, e.g. stack
+    // overflow.
+    case __NR_sigaltstack:
 #if defined(__i386__) || defined(__arm__) || \
     (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
     case __NR_rt_sigtimedwait_time64:
@@ -353,7 +358,6 @@
     case __NR_rt_sigqueueinfo:
     case __NR_rt_sigsuspend:
     case __NR_rt_tgsigqueueinfo:
-    case __NR_sigaltstack:
 #if !defined(__aarch64__)
     case __NR_signalfd:
 #endif
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc
index 0daf268..2db3ac67 100644
--- a/sandbox/policy/win/sandbox_win.cc
+++ b/sandbox/policy/win/sandbox_win.cc
@@ -371,27 +371,6 @@
   if (result != SBOX_ALL_OK)
     return result;
 
-// Add the policy for debug message only in debug
-#ifndef NDEBUG
-  base::FilePath app_dir;
-  if (!base::PathService::Get(base::DIR_MODULE, &app_dir))
-    return SBOX_ERROR_GENERIC;
-
-  wchar_t long_path_buf[MAX_PATH];
-  DWORD long_path_return_value =
-      GetLongPathName(app_dir.value().c_str(), long_path_buf, MAX_PATH);
-  if (long_path_return_value == 0 || long_path_return_value >= MAX_PATH)
-    return SBOX_ERROR_NO_SPACE;
-
-  base::FilePath debug_message(long_path_buf);
-  debug_message = debug_message.AppendASCII("debug_message.exe");
-  result = policy->AddRule(TargetPolicy::SUBSYS_PROCESS,
-                           TargetPolicy::PROCESS_MIN_EXEC,
-                           debug_message.value().c_str());
-  if (result != SBOX_ALL_OK)
-    return result;
-#endif  // NDEBUG
-
 // Add the policy for read-only PDB file access for stack traces.
 #if !defined(OFFICIAL_BUILD)
   base::FilePath exe;
diff --git a/sandbox/win/src/interceptors_64.cc b/sandbox/win/src/interceptors_64.cc
index 950cb2e1..61006e2 100644
--- a/sandbox/win/src/interceptors_64.cc
+++ b/sandbox/win/src/interceptors_64.cc
@@ -217,44 +217,6 @@
                                     handle_attributes, token);
 }
 
-SANDBOX_INTERCEPT BOOL WINAPI
-TargetCreateProcessW64(LPCWSTR application_name,
-                       LPWSTR command_line,
-                       LPSECURITY_ATTRIBUTES process_attributes,
-                       LPSECURITY_ATTRIBUTES thread_attributes,
-                       BOOL inherit_handles,
-                       DWORD flags,
-                       LPVOID environment,
-                       LPCWSTR current_directory,
-                       LPSTARTUPINFOW startup_info,
-                       LPPROCESS_INFORMATION process_information) {
-  CreateProcessWFunction orig_fn =
-      reinterpret_cast<CreateProcessWFunction>(g_originals[CREATE_PROCESSW_ID]);
-  return TargetCreateProcessW(
-      orig_fn, application_name, command_line, process_attributes,
-      thread_attributes, inherit_handles, flags, environment, current_directory,
-      startup_info, process_information);
-}
-
-SANDBOX_INTERCEPT BOOL WINAPI
-TargetCreateProcessA64(LPCSTR application_name,
-                       LPSTR command_line,
-                       LPSECURITY_ATTRIBUTES process_attributes,
-                       LPSECURITY_ATTRIBUTES thread_attributes,
-                       BOOL inherit_handles,
-                       DWORD flags,
-                       LPVOID environment,
-                       LPCSTR current_directory,
-                       LPSTARTUPINFOA startup_info,
-                       LPPROCESS_INFORMATION process_information) {
-  CreateProcessAFunction orig_fn =
-      reinterpret_cast<CreateProcessAFunction>(g_originals[CREATE_PROCESSA_ID]);
-  return TargetCreateProcessA(
-      orig_fn, application_name, command_line, process_attributes,
-      thread_attributes, inherit_handles, flags, environment, current_directory,
-      startup_info, process_information);
-}
-
 SANDBOX_INTERCEPT HANDLE WINAPI
 TargetCreateThread64(LPSECURITY_ATTRIBUTES thread_attributes,
                      SIZE_T stack_size,
diff --git a/sandbox/win/src/interceptors_64.h b/sandbox/win/src/interceptors_64.h
index bcfdf8a..a5d80e3 100644
--- a/sandbox/win/src/interceptors_64.h
+++ b/sandbox/win/src/interceptors_64.h
@@ -146,32 +146,6 @@
                              ULONG handle_attributes,
                              PHANDLE token);
 
-// Interception of CreateProcessW in kernel32.dll.
-SANDBOX_INTERCEPT BOOL WINAPI
-TargetCreateProcessW64(LPCWSTR application_name,
-                       LPWSTR command_line,
-                       LPSECURITY_ATTRIBUTES process_attributes,
-                       LPSECURITY_ATTRIBUTES thread_attributes,
-                       BOOL inherit_handles,
-                       DWORD flags,
-                       LPVOID environment,
-                       LPCWSTR current_directory,
-                       LPSTARTUPINFOW startup_info,
-                       LPPROCESS_INFORMATION process_information);
-
-// Interception of CreateProcessA in kernel32.dll.
-SANDBOX_INTERCEPT BOOL WINAPI
-TargetCreateProcessA64(LPCSTR application_name,
-                       LPSTR command_line,
-                       LPSECURITY_ATTRIBUTES process_attributes,
-                       LPSECURITY_ATTRIBUTES thread_attributes,
-                       BOOL inherit_handles,
-                       DWORD flags,
-                       LPVOID environment,
-                       LPCSTR current_directory,
-                       LPSTARTUPINFOA startup_info,
-                       LPPROCESS_INFORMATION process_information);
-
 // Interception of CreateThread in kernel32.dll.
 SANDBOX_INTERCEPT HANDLE WINAPI
 TargetCreateThread64(LPSECURITY_ATTRIBUTES thread_attributes,
diff --git a/sandbox/win/src/ipc_tags.h b/sandbox/win/src/ipc_tags.h
index e9ae5a94..4d3d249 100644
--- a/sandbox/win/src/ipc_tags.h
+++ b/sandbox/win/src/ipc_tags.h
@@ -23,7 +23,6 @@
   NTOPENPROCESS,
   NTOPENPROCESSTOKEN,
   NTOPENPROCESSTOKENEX,
-  CREATEPROCESSW,
   NTCREATEKEY,
   NTOPENKEY,
   GDI_GDIDLLINITIALIZE,
diff --git a/sandbox/win/src/process_policy_test.cc b/sandbox/win/src/process_policy_test.cc
index c321c3a0..f4d7d22d 100644
--- a/sandbox/win/src/process_policy_test.cc
+++ b/sandbox/win/src/process_policy_test.cc
@@ -18,226 +18,8 @@
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace {
-
-// Creates a process with the |exe| and |command| parameter using the
-// unicode and ascii version of the api.
-sandbox::SboxTestResult CreateProcessHelper(const std::wstring& exe,
-                                            const std::wstring& command) {
-  base::win::ScopedProcessInformation pi;
-  STARTUPINFOW si = {sizeof(si)};
-  const wchar_t* exe_name = nullptr;
-  if (!exe.empty())
-    exe_name = exe.c_str();
-
-  std::unique_ptr<wchar_t, base::FreeDeleter> writable_command(
-      _wcsdup(command.c_str()));
-
-  // Create the process with the unicode version of the API.
-  sandbox::SboxTestResult ret1 = sandbox::SBOX_TEST_FAILED;
-  PROCESS_INFORMATION temp_process_info = {};
-  if (::CreateProcessW(
-          exe_name, command.empty() ? nullptr : writable_command.get(), nullptr,
-          nullptr, false, 0, nullptr, nullptr, &si, &temp_process_info)) {
-    pi.Set(temp_process_info);
-    ret1 = sandbox::SBOX_TEST_SUCCEEDED;
-  } else {
-    DWORD last_error = GetLastError();
-    if ((ERROR_NOT_ENOUGH_QUOTA == last_error) ||
-        (ERROR_ACCESS_DENIED == last_error) ||
-        (ERROR_FILE_NOT_FOUND == last_error)) {
-      ret1 = sandbox::SBOX_TEST_DENIED;
-    } else {
-      ret1 = sandbox::SBOX_TEST_FAILED;
-    }
-  }
-
-  pi.Close();
-
-  // Do the same with the ansi version of the api
-  STARTUPINFOA sia = {sizeof(sia)};
-  sandbox::SboxTestResult ret2 = sandbox::SBOX_TEST_FAILED;
-
-  std::string narrow_cmd_line =
-      base::SysWideToMultiByte(command.c_str(), CP_UTF8);
-  if (::CreateProcessA(
-          exe_name ? base::SysWideToMultiByte(exe_name, CP_UTF8).c_str()
-                   : nullptr,
-          command.empty() ? nullptr : &narrow_cmd_line[0], nullptr, nullptr,
-          false, 0, nullptr, nullptr, &sia, &temp_process_info)) {
-    pi.Set(temp_process_info);
-    ret2 = sandbox::SBOX_TEST_SUCCEEDED;
-  } else {
-    DWORD last_error = GetLastError();
-    if ((ERROR_NOT_ENOUGH_QUOTA == last_error) ||
-        (ERROR_ACCESS_DENIED == last_error) ||
-        (ERROR_FILE_NOT_FOUND == last_error)) {
-      ret2 = sandbox::SBOX_TEST_DENIED;
-    } else {
-      ret2 = sandbox::SBOX_TEST_FAILED;
-    }
-  }
-
-  if (ret1 == ret2)
-    return ret1;
-
-  return sandbox::SBOX_TEST_FAILED;
-}
-
-}  // namespace
-
 namespace sandbox {
 
-SBOX_TESTS_COMMAND int Process_RunApp1(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  std::wstring path = MakePathToSys(argv[0], false);
-
-  // TEST 1: Try with the path in the app_name.
-  return CreateProcessHelper(path, std::wstring());
-}
-
-SBOX_TESTS_COMMAND int Process_RunApp2(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  std::wstring path = MakePathToSys(argv[0], false);
-
-  // TEST 2: Try with the path in the cmd_line.
-  std::wstring cmd_line = L"\"";
-  cmd_line += path;
-  cmd_line += L"\"";
-  return CreateProcessHelper(std::wstring(), cmd_line);
-}
-
-SBOX_TESTS_COMMAND int Process_RunApp3(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  // TEST 3: Try file name in the cmd_line.
-  return CreateProcessHelper(std::wstring(), argv[0]);
-}
-
-SBOX_TESTS_COMMAND int Process_RunApp4(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  // TEST 4: Try file name in the app_name and current directory sets correctly.
-  std::wstring system32 = MakePathToSys(L"", false);
-  wchar_t current_directory[MAX_PATH + 1];
-  DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory);
-  if (!ret)
-    return SBOX_TEST_FIRST_ERROR;
-  if (ret >= MAX_PATH)
-    return SBOX_TEST_FAILED;
-
-  current_directory[ret] = L'\\';
-  current_directory[ret + 1] = L'\0';
-  if (!::SetCurrentDirectory(system32.c_str()))
-    return SBOX_TEST_SECOND_ERROR;
-
-  const int result4 = CreateProcessHelper(argv[0], std::wstring());
-  return ::SetCurrentDirectory(current_directory) ? result4 : SBOX_TEST_FAILED;
-}
-
-SBOX_TESTS_COMMAND int Process_RunApp5(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  std::wstring path = MakePathToSys(argv[0], false);
-
-  // TEST 5: Try with the path in the cmd_line and arguments.
-  std::wstring cmd_line = L"\"";
-  cmd_line += path;
-  cmd_line += L"\" /I";
-  return CreateProcessHelper(std::wstring(), cmd_line);
-}
-
-SBOX_TESTS_COMMAND int Process_RunApp6(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  // TEST 6: Try with the file_name in the cmd_line and arguments.
-  std::wstring cmd_line = argv[0];
-  cmd_line += L" /I";
-  return CreateProcessHelper(std::wstring(), cmd_line);
-}
-
-// Creates a process and checks if it's possible to get a handle to it's token.
-SBOX_TESTS_COMMAND int Process_GetChildProcessToken(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  std::wstring path = MakePathToSys(argv[0], false);
-
-  STARTUPINFOW si = {sizeof(si)};
-
-  PROCESS_INFORMATION temp_process_info = {};
-  if (!::CreateProcessW(path.c_str(), nullptr, nullptr, nullptr, false,
-                        CREATE_SUSPENDED, nullptr, nullptr, &si,
-                        &temp_process_info)) {
-    return SBOX_TEST_FAILED;
-  }
-  base::win::ScopedProcessInformation pi(temp_process_info);
-
-  HANDLE token = nullptr;
-  bool result =
-      ::OpenProcessToken(pi.process_handle(), TOKEN_IMPERSONATE, &token);
-  DWORD error = ::GetLastError();
-
-  base::win::ScopedHandle token_handle(token);
-
-  if (!::TerminateProcess(pi.process_handle(), 0))
-    return SBOX_TEST_FAILED;
-
-  if (result && token)
-    return SBOX_TEST_SUCCEEDED;
-
-  if (ERROR_ACCESS_DENIED == error)
-    return SBOX_TEST_DENIED;
-
-  return SBOX_TEST_FAILED;
-}
-
-// Creates a suspended process using CreateProcessA then kill it.
-SBOX_TESTS_COMMAND int Process_CreateProcessA(int argc, wchar_t** argv) {
-  if (argc != 1)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  if (!argv || !argv[0])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  STARTUPINFOA si = {sizeof(si)};
-
-  std::wstring path = MakePathToSys(argv[0], false);
-
-  PROCESS_INFORMATION temp_process_info = {};
-  // Create suspended to avoid popping calc.
-  if (!::CreateProcessA(base::SysWideToMultiByte(path, CP_UTF8).c_str(),
-                        nullptr, nullptr, nullptr, false, CREATE_SUSPENDED,
-                        nullptr, nullptr, &si, &temp_process_info)) {
-    return SBOX_TEST_FAILED;
-  }
-  base::win::ScopedProcessInformation pi(temp_process_info);
-
-  if (!::TerminateProcess(pi.process_handle(), 0))
-    return SBOX_TEST_FAILED;
-
-  return SBOX_TEST_SUCCEEDED;
-}
-
 SBOX_TESTS_COMMAND int Process_OpenToken(int argc, wchar_t** argv) {
   HANDLE token;
   if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) {
@@ -314,110 +96,6 @@
   return SBOX_TEST_SUCCEEDED;
 }
 
-// Creates a process and checks its exit code. Succeeds on exit code 0.
-SBOX_TESTS_COMMAND int Process_CheckExitCode(int argc, wchar_t** argv) {
-  if (argc != 3)
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  if (!argv || !argv[0] || !argv[1] || !argv[2])
-    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
-  std::wstring path = MakePathToSys(argv[0], false);
-  std::wstring cmdline = argv[1];
-  std::wstring cwd = argv[2];
-
-  STARTUPINFOW si = {sizeof(si)};
-
-  PROCESS_INFORMATION temp_process_info = {};
-  if (!::CreateProcessW(path.c_str(), &cmdline[0], nullptr, nullptr, false, 0,
-                        nullptr, cwd.c_str(), &si, &temp_process_info)) {
-    return SBOX_TEST_FAILED;
-  }
-  base::win::ScopedProcessInformation pi(temp_process_info);
-  DWORD ret = WaitForSingleObject(pi.process_handle(), 1000);
-  if (ret != WAIT_OBJECT_0)
-    return SBOX_TEST_FAILED;
-
-  DWORD exit_code;
-  if (!GetExitCodeProcess(pi.process_handle(), &exit_code))
-    return SBOX_TEST_FAILED;
-
-  if (exit_code != 0)
-    return SBOX_TEST_FAILED;
-
-  return SBOX_TEST_SUCCEEDED;
-}
-
-TEST(ProcessPolicyTest, TestAllAccess) {
-  // Check if the "all access" rule fails to be added when the token is too
-  // powerful.
-  TestRunner runner;
-
-  // Check the failing case.
-  runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN);
-  EXPECT_EQ(SBOX_ERROR_UNSUPPORTED,
-            runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS,
-                                        TargetPolicy::PROCESS_ALL_EXEC,
-                                        L"this is not important"));
-
-  // Check the working case.
-  runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_INTERACTIVE);
-
-  EXPECT_EQ(SBOX_ALL_OK,
-            runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS,
-                                        TargetPolicy::PROCESS_ALL_EXEC,
-                                        L"this is not important"));
-}
-
-TEST(ProcessPolicyTest, CreateProcessAW) {
-  TestRunner runner;
-  std::wstring maybe_virtual_exe_path = MakePathToSys(L"findstr.exe", false);
-  std::wstring non_virtual_exe_path = MakePathToSys32(L"findstr.exe", false);
-  ASSERT_TRUE(!maybe_virtual_exe_path.empty());
-
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_MIN_EXEC,
-                             maybe_virtual_exe_path.c_str()));
-
-  if (non_virtual_exe_path != maybe_virtual_exe_path) {
-    EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                               TargetPolicy::PROCESS_MIN_EXEC,
-                               non_virtual_exe_path.c_str()));
-  }
-
-  // Need to add directory rules for the directories that we use in
-  // SetCurrentDirectory.
-  EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L""));
-
-  wchar_t current_directory[MAX_PATH];
-  DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory);
-  ASSERT_TRUE(0 != ret && ret < MAX_PATH);
-
-  wcscat_s(current_directory, MAX_PATH, L"\\");
-  EXPECT_TRUE(
-      runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, current_directory));
-
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp1 calc.exe"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp2 calc.exe"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp3 calc.exe"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp4 calc.exe"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp5 calc.exe"));
-  EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp6 calc.exe"));
-
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_RunApp1 findstr.exe"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_RunApp2 findstr.exe"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_RunApp3 findstr.exe"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_RunApp4 findstr.exe"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_RunApp5 findstr.exe"));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_RunApp6 findstr.exe"));
-}
-
 // Tests that the broker correctly handles a process crashing within the job.
 // Fails on Windows ARM64: https://crbug.com/905526
 #if defined(ARCH_CPU_ARM64)
@@ -431,87 +109,11 @@
             runner.RunTest(L"Process_Crash"));
 }
 
-TEST(ProcessPolicyTest, CreateProcessWithCWD) {
-  TestRunner runner;
-  std::wstring sys_path = MakePathToSys(L"", false);
-  while (!sys_path.empty() && sys_path.back() == L'\\')
-    sys_path.erase(sys_path.length() - 1);
-
-  std::wstring exe_path = MakePathToSys(L"cmd.exe", false);
-  std::wstring cmd_line =
-      L"\"/c if \\\"%CD%\\\" NEQ \\\"" + sys_path + L"\\\" exit 1\"";
-
-  ASSERT_TRUE(!exe_path.empty());
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_MIN_EXEC, exe_path.c_str()));
-
-  std::wstring command =
-      L"Process_CheckExitCode cmd.exe " + cmd_line + L" " + sys_path;
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command.c_str()));
-}
-
 TEST(ProcessPolicyTest, OpenToken) {
   TestRunner runner;
   EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_OpenToken"));
 }
 
-TEST(ProcessPolicyTest, TestGetProcessTokenMinAccess) {
-  TestRunner runner;
-  std::wstring exe_path = MakePathToSys(L"findstr.exe", false);
-  ASSERT_TRUE(!exe_path.empty());
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_MIN_EXEC, exe_path.c_str()));
-
-  EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"Process_GetChildProcessToken findstr.exe"));
-}
-
-TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccess) {
-  TestRunner runner(JOB_UNPROTECTED, USER_INTERACTIVE, USER_INTERACTIVE);
-  std::wstring exe_path = MakePathToSys(L"findstr.exe", false);
-  ASSERT_TRUE(!exe_path.empty());
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_ALL_EXEC, exe_path.c_str()));
-
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_GetChildProcessToken findstr.exe"));
-}
-
-TEST(ProcessPolicyTest, TestGetProcessTokenMinAccessNoJob) {
-  TestRunner runner(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
-  std::wstring exe_path = MakePathToSys(L"findstr.exe", false);
-  ASSERT_TRUE(!exe_path.empty());
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_MIN_EXEC, exe_path.c_str()));
-
-  EXPECT_EQ(SBOX_TEST_DENIED,
-            runner.RunTest(L"Process_GetChildProcessToken findstr.exe"));
-}
-
-TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccessNoJob) {
-  TestRunner runner(JOB_NONE, USER_INTERACTIVE, USER_INTERACTIVE);
-  std::wstring exe_path = MakePathToSys(L"findstr.exe", false);
-  ASSERT_TRUE(!exe_path.empty());
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_ALL_EXEC, exe_path.c_str()));
-
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_GetChildProcessToken findstr.exe"));
-}
-
-TEST(ProcessPolicyTest, TestCreateProcessA) {
-  TestRunner runner;
-  sandbox::TargetPolicy* policy = runner.GetPolicy();
-  policy->SetJobLevel(JOB_NONE, 0);
-  policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
-  std::wstring exe_path = MakePathToSys(L"calc.exe", false);
-  ASSERT_TRUE(!exe_path.empty());
-  EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS,
-                             TargetPolicy::PROCESS_ALL_EXEC, exe_path.c_str()));
-  EXPECT_EQ(SBOX_TEST_SUCCEEDED,
-            runner.RunTest(L"Process_CreateProcessA calc.exe"));
-}
-
 // This tests that the CreateThread works with CSRSS not locked down.
 // In other words, that the interception passes through OK.
 TEST(ProcessPolicyTest, TestCreateThreadWithCsrss) {
diff --git a/sandbox/win/src/process_thread_dispatcher.cc b/sandbox/win/src/process_thread_dispatcher.cc
index 0711b9b..d47e575f 100644
--- a/sandbox/win/src/process_thread_dispatcher.cc
+++ b/sandbox/win/src/process_thread_dispatcher.cc
@@ -18,87 +18,9 @@
 #include "sandbox/win/src/process_thread_policy.h"
 #include "sandbox/win/src/sandbox.h"
 
-namespace {
-
-// Extracts the application name from a command line.
-//
-// The application name is the first element of the command line. If
-// there is no quotes, the first element is delimited by the first space.
-// If there are quotes, the first element is delimited by the quotes.
-//
-// The create process call is smarter than us. It tries really hard to launch
-// the process even if the command line is wrong. For example:
-// "c:\program files\test param" will first try to launch c:\program.exe then
-// c:\program files\test.exe. We don't do that, we stop after at the first
-// space when there is no quotes.
-std::wstring GetPathFromCmdLine(const std::wstring& cmd_line) {
-  std::wstring exe_name;
-  // Check if it starts with '"'.
-  if (cmd_line[0] == L'\"') {
-    // Find the position of the second '"', this terminates the path.
-    std::wstring::size_type pos = cmd_line.find(L'\"', 1);
-    if (std::wstring::npos == pos)
-      return cmd_line;
-    exe_name = cmd_line.substr(1, pos - 1);
-  } else {
-    // There is no '"', that means that the appname is terminated at the
-    // first space.
-    std::wstring::size_type pos = cmd_line.find(L' ');
-    if (std::wstring::npos == pos) {
-      // There is no space, the cmd_line contains only the app_name
-      exe_name = cmd_line;
-    } else {
-      exe_name = cmd_line.substr(0, pos);
-    }
-  }
-
-  return exe_name;
-}
-
-// Returns true is the path in parameter is relative. False if it's
-// absolute.
-bool IsPathRelative(const std::wstring& path) {
-  // A path is Relative if it's not a UNC path beginnning with \\ or a
-  // path beginning with a drive. (i.e. X:\)
-  if (path.find(L"\\\\") == 0 || path.find(L":\\") == 1)
-    return false;
-  return true;
-}
-
-// Converts a relative path to an absolute path.
-bool ConvertToAbsolutePath(const std::wstring& child_current_directory,
-                           bool use_env_path,
-                           std::wstring* path) {
-  wchar_t file_buffer[MAX_PATH];
-  wchar_t* file_part = nullptr;
-
-  // Here we should start by looking at the path where the child application was
-  // started. We don't have this information yet.
-  DWORD result = 0;
-  if (use_env_path) {
-    // Try with the complete path
-    result = ::SearchPath(nullptr, path->c_str(), nullptr, MAX_PATH,
-                          file_buffer, &file_part);
-  }
-
-  if (0 == result) {
-    // Try with the current directory of the child
-    result = ::SearchPath(child_current_directory.c_str(), path->c_str(),
-                          nullptr, MAX_PATH, file_buffer, &file_part);
-  }
-
-  if (0 == result || result >= MAX_PATH)
-    return false;
-
-  *path = file_buffer;
-  return true;
-}
-
-}  // namespace
 namespace sandbox {
 
-ThreadProcessDispatcher::ThreadProcessDispatcher(PolicyBase* policy_base)
-    : policy_base_(policy_base) {
+ThreadProcessDispatcher::ThreadProcessDispatcher() {
   static const IPCCall open_thread = {
       {IpcTag::NTOPENTHREAD, {UINT32_TYPE, UINT32_TYPE}},
       reinterpret_cast<CallbackGeneric>(
@@ -119,12 +41,6 @@
       reinterpret_cast<CallbackGeneric>(
           &ThreadProcessDispatcher::NtOpenProcessTokenEx)};
 
-  static const IPCCall create_params = {
-      {IpcTag::CREATEPROCESSW,
-       {WCHAR_TYPE, WCHAR_TYPE, WCHAR_TYPE, WCHAR_TYPE, INOUTPTR_TYPE}},
-      reinterpret_cast<CallbackGeneric>(
-          &ThreadProcessDispatcher::CreateProcessW)};
-
   // NOTE(liamjm): 2nd param is size_t: Using VOIDPTR_TYPE as they are
   // the same size on windows.
   static_assert(sizeof(size_t) == sizeof(void*),
@@ -139,7 +55,6 @@
   ipc_calls_.push_back(open_process);
   ipc_calls_.push_back(process_token);
   ipc_calls_.push_back(process_tokenex);
-  ipc_calls_.push_back(create_params);
   ipc_calls_.push_back(create_thread_params);
 }
 
@@ -155,12 +70,6 @@
       NOTREACHED();
       return false;
 
-    case IpcTag::CREATEPROCESSW:
-      return INTERCEPT_EAT(manager, kKerneldllName, CreateProcessW,
-                           CREATE_PROCESSW_ID, 44) &&
-             INTERCEPT_EAT(manager, L"kernel32.dll", CreateProcessA,
-                           CREATE_PROCESSA_ID, 44);
-
     default:
       return false;
   }
@@ -211,48 +120,6 @@
   return true;
 }
 
-bool ThreadProcessDispatcher::CreateProcessW(IPCInfo* ipc,
-                                             std::wstring* name,
-                                             std::wstring* cmd_line,
-                                             std::wstring* cur_dir,
-                                             std::wstring* target_cur_dir,
-                                             CountedBuffer* info) {
-  if (sizeof(PROCESS_INFORMATION) != info->Size())
-    return false;
-
-  // Check if there is an application name.
-  std::wstring exe_name;
-  if (!name->empty())
-    exe_name = *name;
-  else
-    exe_name = GetPathFromCmdLine(*cmd_line);
-
-  if (IsPathRelative(exe_name)) {
-    if (!ConvertToAbsolutePath(*cur_dir, name->empty(), &exe_name)) {
-      // Cannot find the path. Maybe the file does not exist.
-      ipc->return_info.win32_result = ERROR_FILE_NOT_FOUND;
-      return true;
-    }
-  }
-
-  const wchar_t* const_exe_name = exe_name.c_str();
-  CountedParameterSet<NameBased> params;
-  params[NameBased::NAME] = ParamPickerMake(const_exe_name);
-
-  EvalResult eval =
-      policy_base_->EvalPolicy(IpcTag::CREATEPROCESSW, params.GetBase());
-
-  PROCESS_INFORMATION* proc_info =
-      reinterpret_cast<PROCESS_INFORMATION*>(info->Buffer());
-  // Here we force the app_name to be the one we used for the policy lookup.
-  // If our logic was wrong, at least we wont allow create a random process.
-  DWORD ret = ProcessPolicy::CreateProcessWAction(
-      eval, *ipc->client_info, exe_name, *cmd_line, *target_cur_dir, proc_info);
-
-  ipc->return_info.win32_result = ret;
-  return true;
-}
-
 bool ThreadProcessDispatcher::CreateThread(IPCInfo* ipc,
                                            SIZE_T stack_size,
                                            LPTHREAD_START_ROUTINE start_address,
diff --git a/sandbox/win/src/process_thread_dispatcher.h b/sandbox/win/src/process_thread_dispatcher.h
index 7a23243..4e2240f 100644
--- a/sandbox/win/src/process_thread_dispatcher.h
+++ b/sandbox/win/src/process_thread_dispatcher.h
@@ -7,8 +7,6 @@
 
 #include <stdint.h>
 
-#include <string>
-
 #include "sandbox/win/src/crosscall_server.h"
 #include "sandbox/win/src/ipc_tags.h"
 #include "sandbox/win/src/sandbox_policy_base.h"
@@ -18,7 +16,7 @@
 // This class handles process and thread-related IPC calls.
 class ThreadProcessDispatcher : public Dispatcher {
  public:
-  explicit ThreadProcessDispatcher(PolicyBase* policy_base);
+  explicit ThreadProcessDispatcher();
 
   ThreadProcessDispatcher(const ThreadProcessDispatcher&) = delete;
   ThreadProcessDispatcher& operator=(const ThreadProcessDispatcher&) = delete;
@@ -48,22 +46,12 @@
                             uint32_t desired_access,
                             uint32_t attributes);
 
-  // Processes IPC requests coming from calls to CreateProcessW() in the target.
-  bool CreateProcessW(IPCInfo* ipc,
-                      std::wstring* name,
-                      std::wstring* cmd_line,
-                      std::wstring* cur_dir,
-                      std::wstring* target_cur_dir,
-                      CountedBuffer* info);
-
   // Processes IPC requests coming from calls to CreateThread() in the target.
   bool CreateThread(IPCInfo* ipc,
                     SIZE_T stack_size,
                     LPTHREAD_START_ROUTINE start_address,
                     LPVOID parameter,
                     DWORD creation_flags);
-
-  PolicyBase* policy_base_;
 };
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/process_thread_interception.cc b/sandbox/win/src/process_thread_interception.cc
index 29d0cada..4a9fff2 100644
--- a/sandbox/win/src/process_thread_interception.cc
+++ b/sandbox/win/src/process_thread_interception.cc
@@ -266,172 +266,6 @@
   return status;
 }
 
-BOOL WINAPI TargetCreateProcessW(CreateProcessWFunction orig_CreateProcessW,
-                                 LPCWSTR application_name,
-                                 LPWSTR command_line,
-                                 LPSECURITY_ATTRIBUTES process_attributes,
-                                 LPSECURITY_ATTRIBUTES thread_attributes,
-                                 BOOL inherit_handles,
-                                 DWORD flags,
-                                 LPVOID environment,
-                                 LPCWSTR current_directory,
-                                 LPSTARTUPINFOW startup_info,
-                                 LPPROCESS_INFORMATION process_information) {
-  if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() &&
-      orig_CreateProcessW(application_name, command_line, process_attributes,
-                          thread_attributes, inherit_handles, flags,
-                          environment, current_directory, startup_info,
-                          process_information)) {
-    return true;
-  }
-
-  // We don't trust that the IPC can work this early.
-  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
-    return false;
-
-  // Don't call GetLastError before InitCalled() succeeds because kernel32 may
-  // not be mapped yet.
-  DWORD original_error = ::GetLastError();
-
-  do {
-    if (!ValidParameter(process_information, sizeof(PROCESS_INFORMATION),
-                        WRITE))
-      break;
-
-    void* memory = GetGlobalIPCMemory();
-    if (!memory)
-      break;
-
-    const wchar_t* cur_dir = nullptr;
-
-    wchar_t this_current_directory[MAX_PATH];
-    DWORD result = ::GetCurrentDirectory(MAX_PATH, this_current_directory);
-    if (0 != result && result < MAX_PATH)
-      cur_dir = this_current_directory;
-
-    SharedMemIPCClient ipc(memory);
-    CrossCallReturn answer = {0};
-
-    InOutCountedBuffer proc_info(process_information,
-                                 sizeof(PROCESS_INFORMATION));
-
-    ResultCode code =
-        CrossCall(ipc, IpcTag::CREATEPROCESSW, application_name, command_line,
-                  cur_dir, current_directory, proc_info, &answer);
-    if (SBOX_ALL_OK != code)
-      break;
-
-    ::SetLastError(answer.win32_result);
-    if (ERROR_SUCCESS != answer.win32_result)
-      return false;
-
-    return true;
-  } while (false);
-
-  ::SetLastError(original_error);
-  return false;
-}
-
-BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA,
-                                 LPCSTR application_name,
-                                 LPSTR command_line,
-                                 LPSECURITY_ATTRIBUTES process_attributes,
-                                 LPSECURITY_ATTRIBUTES thread_attributes,
-                                 BOOL inherit_handles,
-                                 DWORD flags,
-                                 LPVOID environment,
-                                 LPCSTR current_directory,
-                                 LPSTARTUPINFOA startup_info,
-                                 LPPROCESS_INFORMATION process_information) {
-  if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() &&
-      orig_CreateProcessA(application_name, command_line, process_attributes,
-                          thread_attributes, inherit_handles, flags,
-                          environment, current_directory, startup_info,
-                          process_information)) {
-    return true;
-  }
-
-  // We don't trust that the IPC can work this early.
-  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
-    return false;
-
-  // Don't call GetLastError before InitCalled() succeeds because kernel32 may
-  // not be mapped yet.
-  DWORD original_error = ::GetLastError();
-
-  do {
-    if (!ValidParameter(process_information, sizeof(PROCESS_INFORMATION),
-                        WRITE))
-      break;
-
-    void* memory = GetGlobalIPCMemory();
-    if (!memory)
-      break;
-
-    // Convert the input params to unicode.
-    UNICODE_STRING* cmd_unicode = nullptr;
-    UNICODE_STRING* app_unicode = nullptr;
-    UNICODE_STRING* cwd_unicode = nullptr;
-    if (command_line) {
-      cmd_unicode = AnsiToUnicode(command_line);
-      if (!cmd_unicode)
-        break;
-    }
-
-    if (application_name) {
-      app_unicode = AnsiToUnicode(application_name);
-      if (!app_unicode) {
-        operator delete(cmd_unicode, NT_ALLOC);
-        break;
-      }
-    }
-
-    if (current_directory) {
-      cwd_unicode = AnsiToUnicode(current_directory);
-      if (!cwd_unicode) {
-        operator delete(cmd_unicode, NT_ALLOC);
-        operator delete(app_unicode, NT_ALLOC);
-        break;
-      }
-    }
-
-    const wchar_t* cmd_line = cmd_unicode ? cmd_unicode->Buffer : nullptr;
-    const wchar_t* app_name = app_unicode ? app_unicode->Buffer : nullptr;
-    const wchar_t* cwd = cwd_unicode ? cwd_unicode->Buffer : nullptr;
-    const wchar_t* cur_dir = nullptr;
-
-    wchar_t target_current_directory[MAX_PATH];
-    DWORD result = ::GetCurrentDirectory(MAX_PATH, target_current_directory);
-    if (0 != result && result < MAX_PATH)
-      cur_dir = target_current_directory;
-
-    SharedMemIPCClient ipc(memory);
-    CrossCallReturn answer = {0};
-
-    InOutCountedBuffer proc_info(process_information,
-                                 sizeof(PROCESS_INFORMATION));
-
-    ResultCode code = CrossCall(ipc, IpcTag::CREATEPROCESSW, app_name, cmd_line,
-                                cur_dir, cwd, proc_info, &answer);
-
-    operator delete(cmd_unicode, NT_ALLOC);
-    operator delete(app_unicode, NT_ALLOC);
-    operator delete(cwd_unicode, NT_ALLOC);
-
-    if (SBOX_ALL_OK != code)
-      break;
-
-    ::SetLastError(answer.win32_result);
-    if (ERROR_SUCCESS != answer.win32_result)
-      return false;
-
-    return true;
-  } while (false);
-
-  ::SetLastError(original_error);
-  return false;
-}
-
 HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread,
                                  LPSECURITY_ATTRIBUTES thread_attributes,
                                  SIZE_T stack_size,
diff --git a/sandbox/win/src/process_thread_interception.h b/sandbox/win/src/process_thread_interception.h
index 2608d7d..6b98ba05 100644
--- a/sandbox/win/src/process_thread_interception.h
+++ b/sandbox/win/src/process_thread_interception.h
@@ -14,10 +14,6 @@
 
 namespace {
 
-using CreateProcessWFunction = decltype(&::CreateProcessW);
-
-using CreateProcessAFunction = decltype(&::CreateProcessA);
-
 using CreateThreadFunction = decltype(&::CreateThread);
 
 using GetUserDefaultLCIDFunction = decltype(&::GetUserDefaultLCID);
@@ -57,33 +53,6 @@
                            ULONG handle_attributes,
                            PHANDLE token);
 
-// Interception of CreateProcessW and A in kernel32.dll.
-SANDBOX_INTERCEPT BOOL WINAPI
-TargetCreateProcessW(CreateProcessWFunction orig_CreateProcessW,
-                     LPCWSTR application_name,
-                     LPWSTR command_line,
-                     LPSECURITY_ATTRIBUTES process_attributes,
-                     LPSECURITY_ATTRIBUTES thread_attributes,
-                     BOOL inherit_handles,
-                     DWORD flags,
-                     LPVOID environment,
-                     LPCWSTR current_directory,
-                     LPSTARTUPINFOW startup_info,
-                     LPPROCESS_INFORMATION process_information);
-
-SANDBOX_INTERCEPT BOOL WINAPI
-TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA,
-                     LPCSTR application_name,
-                     LPSTR command_line,
-                     LPSECURITY_ATTRIBUTES process_attributes,
-                     LPSECURITY_ATTRIBUTES thread_attributes,
-                     BOOL inherit_handles,
-                     DWORD flags,
-                     LPVOID environment,
-                     LPCSTR current_directory,
-                     LPSTARTUPINFOA startup_info,
-                     LPPROCESS_INFORMATION process_information);
-
 // Interception of CreateThread in kernel32.dll.
 SANDBOX_INTERCEPT HANDLE WINAPI
 TargetCreateThread(CreateThreadFunction orig_CreateThread,
diff --git a/sandbox/win/src/process_thread_policy.cc b/sandbox/win/src/process_thread_policy.cc
index b851c5b..636f1dd 100644
--- a/sandbox/win/src/process_thread_policy.cc
+++ b/sandbox/win/src/process_thread_policy.cc
@@ -17,90 +17,8 @@
 #include "sandbox/win/src/sandbox_types.h"
 #include "sandbox/win/src/win_utils.h"
 
-namespace {
-
-// These are the only safe rights that can be given to a sandboxed
-// process for the process created by the broker. All others are potential
-// vectors of privilege elevation.
-const DWORD kProcessRights = SYNCHRONIZE | PROCESS_QUERY_INFORMATION |
-                             PROCESS_QUERY_LIMITED_INFORMATION |
-                             PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME;
-
-const DWORD kThreadRights = SYNCHRONIZE | THREAD_TERMINATE |
-                            THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION |
-                            THREAD_QUERY_LIMITED_INFORMATION |
-                            THREAD_SET_LIMITED_INFORMATION;
-
-// Creates a child process and duplicates the handles to 'target_process'. The
-// remaining parameters are the same as CreateProcess().
-bool CreateProcessExWHelper(HANDLE target_process,
-                            bool give_full_access,
-                            LPCWSTR lpApplicationName,
-                            LPWSTR lpCommandLine,
-                            LPSECURITY_ATTRIBUTES lpProcessAttributes,
-                            LPSECURITY_ATTRIBUTES lpThreadAttributes,
-                            bool bInheritHandles,
-                            DWORD dwCreationFlags,
-                            LPVOID lpEnvironment,
-                            LPCWSTR lpCurrentDirectory,
-                            LPSTARTUPINFOW lpStartupInfo,
-                            LPPROCESS_INFORMATION lpProcessInformation) {
-  if (!::CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes,
-                        lpThreadAttributes, bInheritHandles, dwCreationFlags,
-                        lpEnvironment, lpCurrentDirectory, lpStartupInfo,
-                        lpProcessInformation)) {
-    return false;
-  }
-
-  DWORD process_access = kProcessRights;
-  DWORD thread_access = kThreadRights;
-  if (give_full_access) {
-    process_access = PROCESS_ALL_ACCESS;
-    thread_access = THREAD_ALL_ACCESS;
-  }
-  if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hProcess,
-                         target_process, &lpProcessInformation->hProcess,
-                         process_access, false, DUPLICATE_CLOSE_SOURCE)) {
-    ::CloseHandle(lpProcessInformation->hThread);
-    return false;
-  }
-  if (!::DuplicateHandle(::GetCurrentProcess(), lpProcessInformation->hThread,
-                         target_process, &lpProcessInformation->hThread,
-                         thread_access, false, DUPLICATE_CLOSE_SOURCE)) {
-    return false;
-  }
-  return true;
-}
-
-}  // namespace
-
 namespace sandbox {
 
-bool ProcessPolicy::GenerateRules(const wchar_t* name,
-                                  TargetPolicy::Semantics semantics,
-                                  LowLevelPolicy* policy) {
-  std::unique_ptr<PolicyRule> process;
-  switch (semantics) {
-    case TargetPolicy::PROCESS_MIN_EXEC: {
-      process = std::make_unique<PolicyRule>(GIVE_READONLY);
-      break;
-    };
-    case TargetPolicy::PROCESS_ALL_EXEC: {
-      process = std::make_unique<PolicyRule>(GIVE_ALLACCESS);
-      break;
-    };
-    default: { return false; };
-  }
-
-  if (!process->AddStringMatch(IF, NameBased::NAME, name, CASE_INSENSITIVE)) {
-    return false;
-  }
-  if (!policy->AddRule(IpcTag::CREATEPROCESSW, process.get())) {
-    return false;
-  }
-  return true;
-}
-
 NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info,
                                          uint32_t desired_access,
                                          uint32_t thread_id,
@@ -212,37 +130,6 @@
   return status;
 }
 
-DWORD ProcessPolicy::CreateProcessWAction(EvalResult eval_result,
-                                          const ClientInfo& client_info,
-                                          const std::wstring& app_name,
-                                          const std::wstring& command_line,
-                                          const std::wstring& current_dir,
-                                          PROCESS_INFORMATION* process_info) {
-  // The only action supported is ASK_BROKER which means create the process.
-  if (GIVE_ALLACCESS != eval_result && GIVE_READONLY != eval_result) {
-    return ERROR_ACCESS_DENIED;
-  }
-
-  STARTUPINFO startup_info = {0};
-  startup_info.cb = sizeof(startup_info);
-  std::unique_ptr<wchar_t, base::FreeDeleter> cmd_line(
-      _wcsdup(command_line.c_str()));
-
-  bool should_give_full_access = (GIVE_ALLACCESS == eval_result);
-
-  const wchar_t* cwd = current_dir.c_str();
-  if (current_dir.empty())
-    cwd = nullptr;
-
-  if (!CreateProcessExWHelper(client_info.process, should_give_full_access,
-                              app_name.c_str(), cmd_line.get(), nullptr,
-                              nullptr, false, 0, nullptr, cwd, &startup_info,
-                              process_info)) {
-    return ERROR_ACCESS_DENIED;
-  }
-  return ERROR_SUCCESS;
-}
-
 DWORD ProcessPolicy::CreateThreadAction(
     const ClientInfo& client_info,
     const SIZE_T stack_size,
diff --git a/sandbox/win/src/process_thread_policy.h b/sandbox/win/src/process_thread_policy.h
index 407e08e6..5ef36037 100644
--- a/sandbox/win/src/process_thread_policy.h
+++ b/sandbox/win/src/process_thread_policy.h
@@ -7,8 +7,6 @@
 
 #include <stdint.h>
 
-#include <string>
-
 #include "sandbox/win/src/crosscall_server.h"
 #include "sandbox/win/src/policy_low_level.h"
 #include "sandbox/win/src/sandbox_policy.h"
@@ -18,15 +16,6 @@
 // This class centralizes most of the knowledge related to process execution.
 class ProcessPolicy {
  public:
-  // Creates the required low-level policy rules to evaluate a high-level.
-  // policy rule for process creation
-  // 'name' is the executable to be spawn.
-  // 'semantics' is the desired semantics.
-  // 'policy' is the policy generator to which the rules are going to be added.
-  static bool GenerateRules(const wchar_t* name,
-                            TargetPolicy::Semantics semantics,
-                            LowLevelPolicy* policy);
-
   // Opens a thread from the child process and returns the handle.
   // client_info contains the information about the child process,
   // desired_access is the access requested by the child and thread_id
@@ -62,19 +51,6 @@
                                            uint32_t attributes,
                                            HANDLE* handle);
 
-  // Processes a 'CreateProcessW()' request from the target.
-  // 'client_info' : the target process that is making the request.
-  // 'eval_result' : The desired policy action to accomplish.
-  // 'app_name' : The full path of the process to be created.
-  // 'command_line' : The command line passed to the created process.
-  // 'current_dir' : The CWD with which to spawn the child process.
-  static DWORD CreateProcessWAction(EvalResult eval_result,
-                                    const ClientInfo& client_info,
-                                    const std::wstring& app_name,
-                                    const std::wstring& command_line,
-                                    const std::wstring& current_dir,
-                                    PROCESS_INFORMATION* process_info);
-
   // Processes a 'CreateThread()' request from the target.
   // 'client_info' : the target process that is making the request.
   static DWORD CreateThreadAction(const ClientInfo& client_info,
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index 7ef1c8b6..e8cbba9 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -44,14 +44,6 @@
     FILES_ALLOW_DIR_ANY,   // Allows open or create with directory semantics
                            // only.
     NAMEDPIPES_ALLOW_ANY,  // Allows creation of a named pipe.
-    PROCESS_MIN_EXEC,      // Allows to create a process with minimal rights
-                           // over the resulting process and thread handles.
-                           // No other parameters besides the command line are
-                           // passed to the child process.
-    PROCESS_ALL_EXEC,      // Allows the creation of a process and return full
-                           // access on the returned handles.
-                           // This flag can be used only when the main token of
-                           // the sandboxed application is at least INTERACTIVE.
     REG_ALLOW_READONLY,    // Allows readonly access to a registry key.
     REG_ALLOW_ANY,         // Allows read and write access to a registry key.
     FAKE_USER_GDI_INIT,    // Fakes user32 and gdi32 initialization. This can
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index e310759..3dbbb293 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -712,19 +712,6 @@
       }
       break;
     }
-    case SUBSYS_PROCESS: {
-      if (lockdown_level_ < USER_INTERACTIVE &&
-          TargetPolicy::PROCESS_ALL_EXEC == semantics) {
-        // This is unsupported. This is a huge security risk to give full access
-        // to a process handle.
-        return SBOX_ERROR_UNSUPPORTED;
-      }
-      if (!ProcessPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
-        NOTREACHED();
-        return SBOX_ERROR_BAD_PARAMS;
-      }
-      break;
-    }
     case SUBSYS_NAMED_PIPES: {
       if (!NamedPipePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
         NOTREACHED();
diff --git a/sandbox/win/src/sandbox_policy_diagnostic.cc b/sandbox/win/src/sandbox_policy_diagnostic.cc
index 0760571..57d4c68 100644
--- a/sandbox/win/src/sandbox_policy_diagnostic.cc
+++ b/sandbox/win/src/sandbox_policy_diagnostic.cc
@@ -175,8 +175,6 @@
       return "NtOpenProcessToken";
     case IpcTag::NTOPENPROCESSTOKENEX:
       return "NtOpenProcessTokenEx";
-    case IpcTag::CREATEPROCESSW:
-      return "CreateProcessW";
     case IpcTag::NTCREATEKEY:
       return "NtCreateKey";
     case IpcTag::NTOPENKEY:
diff --git a/sandbox/win/src/top_level_dispatcher.cc b/sandbox/win/src/top_level_dispatcher.cc
index a751cbdf..f087453 100644
--- a/sandbox/win/src/top_level_dispatcher.cc
+++ b/sandbox/win/src/top_level_dispatcher.cc
@@ -42,10 +42,9 @@
   ipc_targets_[static_cast<size_t>(IpcTag::CREATENAMEDPIPEW)] = dispatcher;
   named_pipe_dispatcher_.reset(dispatcher);
 
-  dispatcher = new ThreadProcessDispatcher(policy_);
+  dispatcher = new ThreadProcessDispatcher();
   ipc_targets_[static_cast<size_t>(IpcTag::NTOPENTHREAD)] = dispatcher;
   ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESS)] = dispatcher;
-  ipc_targets_[static_cast<size_t>(IpcTag::CREATEPROCESSW)] = dispatcher;
   ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESSTOKEN)] = dispatcher;
   ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESSTOKENEX)] = dispatcher;
   ipc_targets_[static_cast<size_t>(IpcTag::CREATETHREAD)] = dispatcher;
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index a0c95bb..bf42c74 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -406,7 +406,6 @@
       "//net/tools/testserver/",
       "//services/test/data",
       "//third_party/pywebsocket3/src/mod_pywebsocket/",
-      "//third_party/tlslite/",
     ]
   }
 
diff --git a/services/network/first_party_sets/first_party_sets.h b/services/network/first_party_sets/first_party_sets.h
index 2750995..dcc7e477 100644
--- a/services/network/first_party_sets/first_party_sets.h
+++ b/services/network/first_party_sets/first_party_sets.h
@@ -13,6 +13,7 @@
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
 #include "base/sequence_checker.h"
+#include "base/thread_annotations.h"
 #include "net/base/schemeful_site.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/same_party_context.h"
@@ -101,7 +102,10 @@
   // non-singleton) First-Party Set.
   bool IsInNontrivialFirstPartySet(const net::SchemefulSite& site) const;
 
-  int64_t size() const { return sets_.size(); }
+  int64_t size() const {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return sets_.size();
+  }
 
   // Returns a mapping from owner to set members. For convenience of iteration,
   // the members of the set includes the owner.
@@ -151,22 +155,23 @@
   // Represents the mapping of site -> site, where keys are members of sets, and
   // values are owners of the sets. Owners are explicitly represented as members
   // of the set.
-  base::flat_map<net::SchemefulSite, net::SchemefulSite> sets_;
+  base::flat_map<net::SchemefulSite, net::SchemefulSite> sets_
+      GUARDED_BY_CONTEXT(sequence_checker_);
   absl::optional<
       std::pair<net::SchemefulSite, base::flat_set<net::SchemefulSite>>>
-      manually_specified_set_;
+      manually_specified_set_ GUARDED_BY_CONTEXT(sequence_checker_);
 
-  std::string raw_persisted_sets_;
+  std::string raw_persisted_sets_ GUARDED_BY_CONTEXT(sequence_checker_);
 
-  bool persisted_sets_ready_ = false;
-  bool component_sets_ready_ = false;
-  bool manual_sets_ready_ = false;
+  bool persisted_sets_ready_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+  bool component_sets_ready_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+  bool manual_sets_ready_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+  // The callback runs after the site state clearing is completed.
+  base::OnceCallback<void(const std::string&)> on_site_data_cleared_
+      GUARDED_BY_CONTEXT(sequence_checker_);
 
   SEQUENCE_CHECKER(sequence_checker_);
 
-  // The callback runs after the site state clearing is completed.
-  base::OnceCallback<void(const std::string&)> on_site_data_cleared_;
-
   FRIEND_TEST_ALL_PREFIXES(FirstPartySetsTest, ComputeSetsDiff_SitesJoined);
   FRIEND_TEST_ALL_PREFIXES(FirstPartySetsTest, ComputeSetsDiff_SitesLeft);
   FRIEND_TEST_ALL_PREFIXES(FirstPartySetsTest, ComputeSetsDiff_OwnerChanged);
diff --git a/services/network/public/mojom/ssl_config.mojom b/services/network/public/mojom/ssl_config.mojom
index 48098ab..ebd823a 100644
--- a/services/network/public/mojom/ssl_config.mojom
+++ b/services/network/public/mojom/ssl_config.mojom
@@ -20,13 +20,9 @@
   bool sha1_local_anchors_enabled = false;
   bool symantec_enforcement_disabled = false;
 
-  // SSL 2.0 and 3.0 are not supported. Note these lines must be kept in sync
-  // with net/ssl/ssl_config.cc.
-  SSLVersion version_min = kTLS1;
-  // version_min_warn is the minimum protocol version that won't cause cert
-  // errors (e.g., in Chrome we'll show a security interstitial for connections
-  // using a version lower than version_min_warn).
-  SSLVersion version_min_warn = kTLS12;
+  // SSL 2.0/3.0 and TLS 1.0/1.1 are not supported. Note these lines must be
+  // kept in sync with net/ssl/ssl_config.cc.
+  SSLVersion version_min = kTLS12;
   SSLVersion version_max = kTLS13;
 
   // Though cipher suites are sent in TLS as "uint8_t CipherSuite[2]", in
diff --git a/services/network/public/mojom/tls_socket.mojom b/services/network/public/mojom/tls_socket.mojom
index 55db8a8..1356dbc 100644
--- a/services/network/public/mojom/tls_socket.mojom
+++ b/services/network/public/mojom/tls_socket.mojom
@@ -18,7 +18,7 @@
 // Represents the options that consumers can specify when requesting a
 // TLSClientSocket.
 struct TLSClientSocketOptions {
-  SSLVersion version_min = kTLS1;
+  SSLVersion version_min = kTLS12;
   SSLVersion version_max = kTLS13;
 
   // If true, the SSLInfo will be returned in the UpgradeToTLS callback on
diff --git a/services/network/ssl_config_type_converter.cc b/services/network/ssl_config_type_converter.cc
index 4b5daac..286559a 100644
--- a/services/network/ssl_config_type_converter.cc
+++ b/services/network/ssl_config_type_converter.cc
@@ -30,8 +30,6 @@
 
   net_config.version_min =
       MojoSSLVersionToNetSSLVersion(mojo_config->version_min);
-  net_config.version_min_warn =
-      MojoSSLVersionToNetSSLVersion(mojo_config->version_min_warn);
   net_config.version_max =
       MojoSSLVersionToNetSSLVersion(mojo_config->version_max);
   DCHECK_LE(net_config.version_min, net_config.version_max);
diff --git a/services/network/tls_client_socket_unittest.cc b/services/network/tls_client_socket_unittest.cc
index 63f4898..d4629ea9 100644
--- a/services/network/tls_client_socket_unittest.cc
+++ b/services/network/tls_client_socket_unittest.cc
@@ -483,8 +483,8 @@
   data_provider.set_connect_data(net::MockConnect(net::SYNCHRONOUS, net::OK));
   mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
   net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
-  ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_1;
-  ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
+  ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_2;
+  ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_3;
   mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
 
   SocketHandle client_socket;
@@ -500,8 +500,8 @@
   base::RunLoop run_loop;
   mojom::TLSClientSocketOptionsPtr options =
       mojom::TLSClientSocketOptions::New();
-  options->version_min = mojom::SSLVersion::kTLS11;
-  options->version_max = mojom::SSLVersion::kTLS12;
+  options->version_min = mojom::SSLVersion::kTLS12;
+  options->version_max = mojom::SSLVersion::kTLS13;
   int net_error = net::ERR_FAILED;
   auto upgrade_callback = base::BindLambdaForTesting(
       [&](int result, mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
diff --git a/services/tracing/perfetto/privacy_filtered_fields-inl.h b/services/tracing/perfetto/privacy_filtered_fields-inl.h
index 095499b..01853ce 100644
--- a/services/tracing/perfetto/privacy_filtered_fields-inl.h
+++ b/services/tracing/perfetto/privacy_filtered_fields-inl.h
@@ -182,7 +182,7 @@
     kChromeApplicationStateInfoIndices, nullptr};
 
 // Proto Message: ChromeRendererSchedulerState
-constexpr int kChromeRendererSchedulerStateIndices[] = {1, -1};
+constexpr int kChromeRendererSchedulerStateIndices[] = {1, 2, 3, -1};
 constexpr MessageInfo kChromeRendererSchedulerState = {
     kChromeRendererSchedulerStateIndices, nullptr};
 
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index b08876d..4e8cd9e 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -3187,7 +3187,8 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android31.textpb"
+          "--avd-config=../../tools/android/avd/proto/generic_android31.textpb",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11_12.media_unittests.filter"
         ],
         "merge": {
           "args": [
@@ -5793,7 +5794,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5881,7 +5882,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -6057,7 +6058,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -6145,7 +6146,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 31d7789e..8724a04 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -13718,7 +13718,7 @@
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android30.textpb",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11.media_unittests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11_12.media_unittests.filter"
         ],
         "merge": {
           "args": [
@@ -43662,7 +43662,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -43750,7 +43750,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -43926,7 +43926,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44014,7 +44014,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44265,7 +44265,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44353,7 +44353,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44529,7 +44529,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44617,7 +44617,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44868,7 +44868,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -44956,7 +44956,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -45132,7 +45132,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M96",
-              "revision": "version:96.0.4664.70"
+              "revision": "version:96.0.4664.71"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -45220,7 +45220,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M97",
-              "revision": "version:97.0.4692.26"
+              "revision": "version:97.0.4692.27"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 6756399..fafa9f1 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -3848,7 +3848,7 @@
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 31
+          "shards": 40
         },
         "test": "browser_tests",
         "test_id_prefix": "ninja://chrome/test:browser_tests/"
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 0c4dc4f..7f6e6c69 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -231,7 +231,7 @@
 
 source_set("media_unittests_filters") {
   data = [
-    "//testing/buildbot/filters/android.emulator_11.media_unittests.filter",
+    "//testing/buildbot/filters/android.emulator_11_12.media_unittests.filter",
     "//testing/buildbot/filters/android.emulator_m.media_unittests.filter",
     "//testing/buildbot/filters/android.emulator_p.media_unittests.filter",
     "//testing/buildbot/filters/fuchsia.debug.media_unittests.filter",
diff --git a/testing/buildbot/filters/android.emulator_11.media_unittests.filter b/testing/buildbot/filters/android.emulator_11_12.media_unittests.filter
similarity index 100%
rename from testing/buildbot/filters/android.emulator_11.media_unittests.filter
rename to testing/buildbot/filters/android.emulator_11_12.media_unittests.filter
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 86c825b..51111add 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -578,7 +578,7 @@
         # These are very slow on the ASAN trybot for some reason.
         # crbug.com/794372
         'swarming': {
-          'shards': 31,
+          'shards': 40,
         },
       },
       'Linux ChromiumOS MSan Tests': {
@@ -2000,7 +2000,12 @@
     'modifications': {
       'android-11-x86-rel': {
         'args': [
-          '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11.media_unittests.filter',
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11_12.media_unittests.filter',
+        ],
+      },
+      'android-12-x64-fyi-rel': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11_12.media_unittests.filter',
         ],
       },
       'android-marshmallow-x86-rel-non-cq': {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index ac879589..9ed78c4 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -363,7 +363,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M97',
-          'revision': 'version:97.0.4692.26',
+          'revision': 'version:97.0.4692.27',
         }
       ],
     },
@@ -387,7 +387,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M96',
-          'revision': 'version:96.0.4664.70',
+          'revision': 'version:96.0.4664.71',
         }
       ],
     },
@@ -435,7 +435,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M97',
-          'revision': 'version:97.0.4692.26',
+          'revision': 'version:97.0.4692.27',
         }
       ],
     },
@@ -459,7 +459,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M96',
-          'revision': 'version:96.0.4664.70',
+          'revision': 'version:96.0.4664.71',
         }
       ],
     },
@@ -507,7 +507,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M97',
-          'revision': 'version:97.0.4692.26',
+          'revision': 'version:97.0.4692.27',
         }
       ],
     },
@@ -531,7 +531,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M96',
-          'revision': 'version:96.0.4664.70',
+          'revision': 'version:96.0.4664.71',
         }
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index dc8df521..07536c4 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3444,24 +3444,6 @@
             ]
         }
     ],
-    "DownloadProgressMessage": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_10s_20210819",
-                    "params": {
-                        "message_dismiss_duration_seconds": "10"
-                    },
-                    "enable_features": [
-                        "DownloadProgressMessage"
-                    ]
-                }
-            ]
-        }
-    ],
     "DriveFsBidirectionalNativeMessaging": [
         {
             "platforms": [
@@ -7087,25 +7069,6 @@
             ]
         }
     ],
-    "SafeBrowsingRealTimeUrlLookupReferrerChainForEnterprise": [
-        {
-            "platforms": [
-                "chromeos",
-                "chromeos_lacros",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SafeBrowsingRealTimeUrlLookupReferrerChainForEnterprise"
-                    ]
-                }
-            ]
-        }
-    ],
     "SafeBrowsingVisualFeaturesSizes": [
         {
             "platforms": [
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn
index 04f43d6..029724d6 100644
--- a/third_party/android_deps/BUILD.gn
+++ b/third_party/android_deps/BUILD.gn
@@ -382,7 +382,7 @@
 
 # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
 java_prebuilt("org_jetbrains_kotlin_kotlin_stdlib_java") {
-  jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib/kotlin-stdlib-1.5.31.jar"
+  jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib/kotlin-stdlib-1.6.0.jar"
   output_name = "org_jetbrains_kotlin_kotlin_stdlib"
   supports_android = true
   deps = [
@@ -702,7 +702,7 @@
 
 # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
 java_prebuilt("org_jetbrains_kotlin_kotlin_stdlib_common_java") {
-  jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib_common/kotlin-stdlib-common-1.5.31.jar"
+  jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib_common/kotlin-stdlib-common-1.6.0.jar"
   output_name = "org_jetbrains_kotlin_kotlin_stdlib_common"
   supports_android = true
 
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/README.chromium b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/README.chromium
index 855ba45..d6d839a 100644
--- a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/README.chromium
+++ b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/README.chromium
@@ -1,7 +1,7 @@
 Name: Kotlin Stdlib
 Short Name: kotlin-stdlib
 URL: https://kotlinlang.org/
-Version: 1.5.31
+Version: 1.6.0
 License: Apache Version 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/cipd.yaml b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/cipd.yaml
index e222a87..d518be1 100644
--- a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/cipd.yaml
+++ b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/cipd.yaml
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 # To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:2@1.5.31.cr0
+# cipd create --pkg-def cipd.yaml -tag version:2@1.6.0.cr0
 package: chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib
 description: "Kotlin Stdlib"
 data:
-- file: kotlin-stdlib-1.5.31.jar
+- file: kotlin-stdlib-1.6.0.jar
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/README.chromium b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/README.chromium
index 656cdb4..c924213d 100644
--- a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/README.chromium
+++ b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/README.chromium
@@ -1,7 +1,7 @@
 Name: Kotlin Stdlib Common
 Short Name: kotlin-stdlib-common
 URL: https://kotlinlang.org/
-Version: 1.5.31
+Version: 1.6.0
 License: Apache Version 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/cipd.yaml b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/cipd.yaml
index 8950046..661ced8 100644
--- a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/cipd.yaml
+++ b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/cipd.yaml
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 # To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:2@1.5.31.cr0
+# cipd create --pkg-def cipd.yaml -tag version:2@1.6.0.cr0
 package: chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common
 description: "Kotlin Stdlib Common"
 data:
-- file: kotlin-stdlib-common-1.5.31.jar
+- file: kotlin-stdlib-common-1.6.0.jar
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index b3d791c1..7c82d96 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -398,6 +398,10 @@
 const base::Feature kTextFragmentAnchor{"TextFragmentAnchor",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables CSS selector fragment anchors. https://crbug.com/1252460
+const base::Feature kCssSelectorFragmentAnchor{
+    "CssSelectorFragmentAnchor", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // File handling integration. https://crbug.com/829689
 const base::Feature kFileHandlingAPI{"FileHandlingAPI",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
@@ -1131,6 +1135,14 @@
 const base::Feature kEarlyCodeCache{"EarlyCodeCache",
                                     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Allow use of an http-equiv meta tag to set client hints.
+const base::Feature kClientHintsMetaHTTPEquivAcceptCH{
+    "ClientHintsMetaHTTPEquivAcceptCH", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Allow use of a named meta tag to set client hints.
+const base::Feature kClientHintsMetaNameAcceptCH{
+    "ClientHintsMetaNameAcceptCH", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Allow third-party delegation of client hint information.
 const base::Feature kClientHintThirdPartyDelegation{
     "ClientHintThirdPartyDelegation", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/third_party/blink/common/permissions_policy/permissions_policy.cc b/third_party/blink/common/permissions_policy/permissions_policy.cc
index 17fbb498..36d36d2 100644
--- a/third_party/blink/common/permissions_policy/permissions_policy.cc
+++ b/third_party/blink/common/permissions_policy/permissions_policy.cc
@@ -250,6 +250,23 @@
 PermissionsPolicy::~PermissionsPolicy() = default;
 
 // static
+std::unique_ptr<PermissionsPolicy> PermissionsPolicy::CreateForFencedFrame(
+    const url::Origin& origin) {
+  return CreateForFencedFrame(origin, GetPermissionsPolicyFeatureList());
+}
+
+std::unique_ptr<PermissionsPolicy> PermissionsPolicy::CreateForFencedFrame(
+    const url::Origin& origin,
+    const PermissionsPolicyFeatureList& features) {
+  std::unique_ptr<PermissionsPolicy> new_policy =
+      base::WrapUnique(new PermissionsPolicy(origin, features));
+  for (const auto& feature : features) {
+    new_policy->inherited_policies_[feature.first] = false;
+  }
+  return new_policy;
+}
+
+// static
 std::unique_ptr<PermissionsPolicy> PermissionsPolicy::CreateFromParentPolicy(
     const PermissionsPolicy* parent_policy,
     const ParsedPermissionsPolicy& container_policy,
diff --git a/third_party/blink/common/permissions_policy/permissions_policy_unittest.cc b/third_party/blink/common/permissions_policy/permissions_policy_unittest.cc
index 8a1bee26..a2765e7e 100644
--- a/third_party/blink/common/permissions_policy/permissions_policy_unittest.cc
+++ b/third_party/blink/common/permissions_policy/permissions_policy_unittest.cc
@@ -56,6 +56,10 @@
     return PermissionsPolicy::CreateFromParentPolicy(parent, frame_policy,
                                                      origin, feature_list_);
   }
+  std::unique_ptr<PermissionsPolicy> CreateForFencedFrame(
+      const url::Origin& origin) {
+    return PermissionsPolicy::CreateForFencedFrame(origin, feature_list_);
+  }
 
   bool PolicyContainsInheritedValue(const PermissionsPolicy* policy,
                                     mojom::PermissionsPolicyFeature feature) {
@@ -1644,4 +1648,10 @@
   EXPECT_FALSE(policy3->IsFeatureEnabled(kDefaultSelfFeature));
 }
 
+TEST_F(PermissionsPolicyTest, CreateForFencedFrame) {
+  std::unique_ptr<PermissionsPolicy> policy = CreateForFencedFrame(origin_a_);
+  EXPECT_FALSE(policy->IsFeatureEnabled(kDefaultOnFeature));
+  EXPECT_FALSE(policy->IsFeatureEnabled(kDefaultSelfFeature));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/common/storage_key/storage_key.cc b/third_party/blink/common/storage_key/storage_key.cc
index 15d295e..4334e06 100644
--- a/third_party/blink/common/storage_key/storage_key.cc
+++ b/third_party/blink/common/storage_key/storage_key.cc
@@ -189,6 +189,15 @@
 }
 
 // static
+StorageKey StorageKey::CreateWithOptionalNonce(
+    const url::Origin& origin,
+    const net::SchemefulSite& top_level_site,
+    const base::UnguessableToken* nonce) {
+  DCHECK(!nonce || !nonce->is_empty());
+  return StorageKey(origin, top_level_site, nonce);
+}
+
+// static
 blink::StorageKey StorageKey::FromNetIsolationInfo(
     const net::IsolationInfo& isolation_info) {
   DCHECK(isolation_info.frame_origin().has_value());
diff --git a/third_party/blink/common/storage_key/storage_key_mojom_traits.cc b/third_party/blink/common/storage_key/storage_key_mojom_traits.cc
index ce94be06..a25f5f6a 100644
--- a/third_party/blink/common/storage_key/storage_key_mojom_traits.cc
+++ b/third_party/blink/common/storage_key/storage_key_mojom_traits.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/public/common/storage_key/storage_key_mojom_traits.h"
 
+#include "base/stl_util.h"
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
 #include "net/base/schemeful_site.h"
@@ -29,20 +30,8 @@
   if (!data.ReadNonce(&nonce))
     return false;
 
-  if (nonce.has_value()) {
-    // This call does not need or use the top_level_site. But since the
-    // implementation sets the top_level_site to be same-site with the origin we
-    // should confirm that's still the case.
-    //
-    // TODO(crbug.com/1199077): This should be represented by a union since the
-    // usages of top_level_site and nonce are mutally exclusive.
-    if (top_level_site != net::SchemefulSite(origin))
-      return false;
-
-    *out = blink::StorageKey::CreateWithNonce(origin, *nonce);
-  } else {
-    *out = blink::StorageKey(origin, top_level_site);
-  }
+  *out = blink::StorageKey::CreateWithOptionalNonce(
+      origin, top_level_site, base::OptionalOrNullptr(nonce));
   return true;
 }
 
diff --git a/third_party/blink/perf_tests/layout/grid-with-block-constraints-dependence.html b/third_party/blink/perf_tests/layout/grid-with-block-constraints-dependence.html
new file mode 100644
index 0000000..7aaa992
--- /dev/null
+++ b/third_party/blink/perf_tests/layout/grid-with-block-constraints-dependence.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<script src="../resources/runner.js"></script>
+<div id=c1 style="display: grid; grid-template: auto / 1fr;">
+  <div id=c2 style="display: grid; grid-template: auto / 1fr;">
+    <div id=c3 style="display: grid; grid-template: auto auto / 1fr;">
+      <div id="target" style="display: grid; height: 100px;"></div>
+      <div id=i1 style="display: grid;">
+        <div id=i2 style="display: grid;">
+          <div id=i3 style="width: 100%; height: 100%;">
+            <canvas id=i4 width=50 height=50 style="width: 100%; height: 100%;"></canvas>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+<script>
+PerfTestRunner.measureRunsPerSecond({
+    description: 'Layout of nested grid with a replaced element dependant on block-constraints.',
+    run: () => {
+      document.getElementById('target').innerText = 'text';
+      PerfTestRunner.forceLayout();
+      document.getElementById('target').innerText = '';
+      PerfTestRunner.forceLayout();
+    },
+});
+</script>
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 121360f..74cd5008 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -130,6 +130,7 @@
     kFreezeBackgroundTabOnNetworkIdle;
 BLINK_COMMON_EXPORT extern const base::Feature kStorageAccessAPI;
 BLINK_COMMON_EXPORT extern const base::Feature kTextFragmentAnchor;
+BLINK_COMMON_EXPORT extern const base::Feature kCssSelectorFragmentAnchor;
 BLINK_COMMON_EXPORT extern const base::Feature kFontAccess;
 BLINK_COMMON_EXPORT extern const base::Feature kFontAccessPersistent;
 BLINK_COMMON_EXPORT extern const base::Feature kComputePressure;
@@ -535,6 +536,11 @@
 
 BLINK_COMMON_EXPORT extern const base::Feature kEarlyCodeCache;
 
+BLINK_COMMON_EXPORT extern const base::Feature
+    kClientHintsMetaHTTPEquivAcceptCH;
+
+BLINK_COMMON_EXPORT extern const base::Feature kClientHintsMetaNameAcceptCH;
+
 BLINK_COMMON_EXPORT extern const base::Feature kClientHintThirdPartyDelegation;
 
 #if defined(OS_ANDROID)
diff --git a/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h b/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
index 0d9f2183..da15485f 100644
--- a/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
+++ b/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
@@ -29,9 +29,6 @@
   static mojo::PendingRemote<network::mojom::URLLoaderFactory> default_factory(
       BundleInfoType& bundle);
 
-  static mojo::PendingRemote<network::mojom::URLLoaderFactory> appcache_factory(
-      BundleInfoType& bundle);
-
   static blink::PendingURLLoaderFactoryBundle::SchemeMap
   scheme_specific_factories(BundleInfoType& bundle);
 
diff --git a/third_party/blink/public/common/permissions_policy/permissions_policy.h b/third_party/blink/public/common/permissions_policy/permissions_policy.h
index 786b760..e99803f2 100644
--- a/third_party/blink/public/common/permissions_policy/permissions_policy.h
+++ b/third_party/blink/public/common/permissions_policy/permissions_policy.h
@@ -180,6 +180,11 @@
   static std::unique_ptr<PermissionsPolicy> CopyStateFrom(
       const PermissionsPolicy*);
 
+  // Creates a PermissionsPolicy for a fenced frame. All permissions are
+  // disabled in fenced frames.
+  static std::unique_ptr<PermissionsPolicy> CreateForFencedFrame(
+      const url::Origin& origin);
+
   bool IsFeatureEnabled(mojom::PermissionsPolicyFeature feature) const;
 
   // Returns whether or not the given feature is enabled by this policy for a
@@ -224,6 +229,10 @@
       const url::Origin& origin,
       const PermissionsPolicyFeatureList& features);
 
+  static std::unique_ptr<PermissionsPolicy> CreateForFencedFrame(
+      const url::Origin& origin,
+      const PermissionsPolicyFeatureList& features);
+
   bool InheritedValueForFeature(
       const PermissionsPolicy* parent_policy,
       std::pair<mojom::PermissionsPolicyFeature,
diff --git a/third_party/blink/public/common/storage_key/storage_key.h b/third_party/blink/public/common/storage_key/storage_key.h
index 9e95be6..da5cd80 100644
--- a/third_party/blink/public/common/storage_key/storage_key.h
+++ b/third_party/blink/public/common/storage_key/storage_key.h
@@ -43,6 +43,8 @@
   // StorageKey without a top-level site specified. Eventually these will all
   // merge into a static function(s) that will require the caller to explicitly
   // specify that they do not want a top-level site.
+  // TODO(https://crbug.com/1271615): Remove or mark as test-only most of these
+  // constructors and factory methods.
   explicit StorageKey(const url::Origin& origin)
       : StorageKey(origin, net::SchemefulSite(origin), nullptr) {}
 
@@ -59,6 +61,12 @@
   static StorageKey CreateWithNonce(const url::Origin& origin,
                                     const base::UnguessableToken& nonce);
 
+  // Same to the above, but this method does take a top-level site.
+  static StorageKey CreateWithOptionalNonce(
+      const url::Origin& origin,
+      const net::SchemefulSite& top_level_site,
+      const base::UnguessableToken* nonce);
+
   // Copyable and Moveable.
   StorageKey(const StorageKey& other) = default;
   StorageKey& operator=(const StorageKey& other) = default;
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index d84641fc..1a97a014 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -8930,6 +8930,7 @@
       # Proxy bypass list, similar to the one passed to --proxy-bypass-list
       optional string proxyBypassList
       # An optional list of origins to grant unlimited cross-origin access to.
+      # Parts of the URL other than those constituting origin are ignored.
       optional array of string originsWithUniversalNetworkAccess
 
     returns
diff --git a/third_party/blink/public/mojom/manifest/manifest.mojom b/third_party/blink/public/mojom/manifest/manifest.mojom
index 09eff5d..ed42676 100644
--- a/third_party/blink/public/mojom/manifest/manifest.mojom
+++ b/third_party/blink/public/mojom/manifest/manifest.mojom
@@ -105,7 +105,8 @@
   ManifestLaunchHandler? launch_handler;
 
   // TODO(crbug.com/1259777): This field is non-standard and part of a Chrome
-  // experiment. See: https://github.com/w3c/manifest/issues/676#issuecomment-810628993
+  // experiment. See:
+  // https://github.com/WICG/manifest-incubations/blob/gh-pages/translations-explainer.md
   // A mapping of locales to their translations.
   map<mojo_base.mojom.String16, ManifestTranslationItem> translations;
 };
diff --git a/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom b/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom
index 4b3d073..5b9b8a0 100644
--- a/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom
+++ b/third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom
@@ -99,6 +99,18 @@
   GetUserMedia(string origin, int32 request_id, bool audio, bool video, string
                audio_constraints, string video_constraints);
 
+  // Lets WebRTCInternals know that a getUserMedia() call has resolved.
+  // |request_id| is an id assigned to the getusermedia call and its
+  //   callback/error
+  // |stream_id| is information about the stream such as the stream id.
+  // |audio_track_info| describes the streams audio track (if any).
+  // |video_track_info| describes the streams video track (if any).
+  // The stream_id, audio_track_info and video_track_info strings are
+  // for display only and should not be parsed by the browser for
+  // security reasons.
+  GetUserMediaSuccess(int32 request_id, string stream_id,
+    string audio_track_info, string video_track_info);
+
   // Logs WebRtc log for the connection id.
   WebRtcEventLogWrite(int32 lid, array<uint8> output);
 
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 1db13e8..9317e2e5 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -574,7 +574,7 @@
   kLinkRelPreload = 901,
   kLinkHeaderDnsPrefetch = 902,
   kLinkHeaderPreconnect = 903,
-  kClientHintsMetaAcceptCH = 904,
+  kClientHintsMetaHTTPEquivAcceptCH = 904,
   kHTMLElementDeprecatedWidth = 905,
   kClientHintsContentDPR = 906,
   kElementAttachShadowOpen = 907,
@@ -3387,6 +3387,7 @@
   kV8Navigator_AdAuctionComponents_Method = 4078,
   kClientHintsUAFullVersionList = 4079,
   kWebAppManifestLaunchHandler = 4080,
+  kClientHintsMetaNameAcceptCH = 4081,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index f1986243..d0d5a12 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -162,6 +162,7 @@
   BLINK_PLATFORM_EXPORT static void EnableSharedStorageAPI(bool);
   BLINK_PLATFORM_EXPORT static void EnableSharedWorker(bool);
   BLINK_PLATFORM_EXPORT static void EnableTextFragmentAnchor(bool);
+  BLINK_PLATFORM_EXPORT static void EnableCSSSelectorFragmentAnchor(bool);
   BLINK_PLATFORM_EXPORT static void EnableTouchEventFeatureDetection(bool);
   BLINK_PLATFORM_EXPORT static void EnableScrollUnification(bool);
   BLINK_PLATFORM_EXPORT static void EnableUserActivationSameOriginVisibility(
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 3c414cc..9023ed6 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -359,8 +359,6 @@
   // document.
   std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
       service_worker_network_provider;
-  // The AppCache host id for this navigation.
-  base::UnguessableToken appcache_host_id;
 
   // This is `true` only for commit requests coming from
   // `RenderFrameImpl::SynchronouslyConmmitAboutBlankForBug778318`.
diff --git a/third_party/blink/renderer/DEPS b/third_party/blink/renderer/DEPS
index 3f1b9ab3..ed8d99a 100644
--- a/third_party/blink/renderer/DEPS
+++ b/third_party/blink/renderer/DEPS
@@ -35,6 +35,7 @@
     "+base/notreached.h",
     "+base/numerics/checked_math.h",
     "+base/numerics/clamped_math.h",
+    "+base/numerics/ostream_operators.h",
     "+base/numerics/ranges.h",
     "+base/numerics/safe_conversions.h",
     "+base/rand_util.h",
diff --git a/third_party/blink/renderer/bindings/core/v8/scheduled_action.h b/third_party/blink/renderer/bindings/core/v8/scheduled_action.h
index 2efadf8c..648bd6f 100644
--- a/third_party/blink/renderer/bindings/core/v8/scheduled_action.h
+++ b/third_party/blink/renderer/bindings/core/v8/scheduled_action.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCHEDULED_ACTION_H_
 
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc b/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc
index fc02996..c0a89ad 100644
--- a/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc
@@ -7,6 +7,7 @@
 #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/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
index 5b184afe..ed4beb19 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -750,30 +750,6 @@
   return V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot;
 }
 
-void AddHistogramSample(void* hist, int sample) {
-  base::Histogram* histogram = static_cast<base::Histogram*>(hist);
-  histogram->Add(sample);
-}
-
-void* CreateHistogram(const char* name, int min, int max, size_t buckets) {
-  // Each histogram has an implicit '0' bucket (for underflow), so we can always
-  // bump the minimum to 1.
-  DCHECK_LE(0, min);
-  min = std::max(1, min);
-
-  // For boolean histograms, always include an overflow bucket [2, infinity).
-  if (max == 1 && buckets == 2) {
-    max = 2;
-    buckets = 3;
-  }
-
-  const std::string histogram_name =
-      Platform::Current()->GetNameForHistogram(name);
-  return base::Histogram::FactoryGet(
-      histogram_name, min, max, static_cast<uint32_t>(buckets),
-      base::Histogram::kUmaTargetedHistogramFlag);
-}
-
 }  // namespace
 
 void V8Initializer::InitializeMainThread(
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h b/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h
index 9a4430e2..42c43cd 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h"
 #include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
 #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index ea26c44..5301f82 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1292,6 +1292,7 @@
     "fetch/readable_stream_bytes_consumer_test.cc",
     "fetch/request_test.cc",
     "fetch/response_test.cc",
+    "fragment_directive/css_selector_fragment_anchor_test.cc",
     "fragment_directive/text_fragment_anchor_metrics_test.cc",
     "fragment_directive/text_fragment_anchor_test.cc",
     "fragment_directive/text_fragment_finder_test.cc",
diff --git a/third_party/blink/renderer/core/css/active_style_sheets.h b/third_party/blink/renderer/core/css/active_style_sheets.h
index 5735d06..3123684 100644
--- a/third_party/blink/renderer/core/css/active_style_sheets.h
+++ b/third_party/blink/renderer/core/css/active_style_sheets.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/media_value_change.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/css/css_rule_list.h b/third_party/blink/renderer/core/css/css_rule_list.h
index 8f815cf..9a34352 100644
--- a/third_party/blink/renderer/core/css/css_rule_list.h
+++ b/third_party/blink/renderer/core/css/css_rule_list.h
@@ -24,6 +24,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
diff --git a/third_party/blink/renderer/core/css/css_segmented_font_face.h b/third_party/blink/renderer/core/css/css_segmented_font_face.h
index dc106d1..30251272 100644
--- a/third_party/blink/renderer/core/css/css_segmented_font_face.h
+++ b/third_party/blink/renderer/core/css/css_segmented_font_face.h
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/platform/fonts/font_selection_types.h"
 #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/lru_cache.h"
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.h b/third_party/blink/renderer/core/css/css_style_sheet.h
index efd86ef..bfd0a2c 100644
--- a/third_party/blink/renderer/core/css/css_style_sheet.h
+++ b/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/css/style_sheet.h"
 #include "third_party/blink/renderer/core/dom/tree_scope.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collector.h b/third_party/blink/renderer/core/css/document_style_sheet_collector.h
index 4a9d1fe..55a3d8c 100644
--- a/third_party/blink/renderer/core/css/document_style_sheet_collector.h
+++ b/third_party/blink/renderer/core/css/document_style_sheet_collector.h
@@ -28,6 +28,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_DOCUMENT_STYLE_SHEET_COLLECTOR_H_
 
 #include "third_party/blink/renderer/core/css/active_style_sheets.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc
index d43d913a..9b9d070 100644
--- a/third_party/blink/renderer/core/css/element_rule_collector.cc
+++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -539,10 +539,12 @@
          dynamic_pseudo == kPseudoIdAfter) &&
         !rule_data->Rule()->Properties().HasProperty(CSSPropertyID::kContent))
       return;
-    if (!rule_data->Rule()->Properties().IsEmpty())
+    if (!rule_data->Rule()->Properties().IsEmpty()) {
       style_->SetHasPseudoElementStyle(dynamic_pseudo);
-    if (result.custom_highlight_name) {
-      style_->SetHasCustomHighlightName(result.custom_highlight_name);
+      if (dynamic_pseudo == kPseudoIdHighlight) {
+        DCHECK(result.custom_highlight_name);
+        style_->SetHasCustomHighlightName(result.custom_highlight_name);
+      }
     }
   } else {
     matched_rules_.push_back(MatchedRule(rule_data, layer_order,
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.cc b/third_party/blink/renderer/core/css/media_query_evaluator.cc
index 29e0810..4eb22b2 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -387,14 +387,12 @@
   if (!value.IsId())
     return false;
 
-  bool const supports_hdr = media_values.DeviceSupportsHDR();
-
   switch (value.Id()) {
     case CSSValueID::kStandard:
-      return !supports_hdr;
+      return true;
 
     case CSSValueID::kHigh:
-      return supports_hdr;
+      return media_values.DeviceSupportsHDR();
 
     default:
       NOTREACHED();
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
index 02341cf..b917657 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
@@ -319,7 +319,7 @@
 };
 
 MediaQueryEvaluatorTestCase g_dynamic_range_high_cases[] = {
-    {"(dynamic-range: standard)", false},
+    {"(dynamic-range: standard)", true},
     {"(dynamic-range: high)", true},
     {"(dynamic-range: invalid)", false},
     {nullptr, false}  // Do not remove the terminator line.
@@ -340,7 +340,7 @@
 };
 
 MediaQueryEvaluatorTestCase g_video_dynamic_range_high_cases[] = {
-    {"(video-dynamic-range: standard)", false},
+    {"(video-dynamic-range: standard)", true},
     {"(video-dynamic-range: high)", true},
     {"(video-dynamic-range: invalid)", false},
     {nullptr, false}  // Do not remove the terminator line.
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc
index fecc67d..54b096d 100644
--- a/third_party/blink/renderer/core/css/rule_feature_set.cc
+++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -404,6 +404,11 @@
   pseudo_invalidation_sets_.clear();
   universal_sibling_invalidation_set_ = nullptr;
   nth_invalidation_set_ = nullptr;
+  classes_in_has_argument_.clear();
+  attributes_in_has_argument_.clear();
+  ids_in_has_argument_.clear();
+  tag_names_in_has_argument_.clear();
+  universal_in_has_argument_ = false;
 
   is_alive_ = false;
 }
@@ -430,6 +435,11 @@
              other.viewport_dependent_media_query_results_ &&
          device_dependent_media_query_results_ ==
              other.device_dependent_media_query_results_ &&
+         classes_in_has_argument_ == other.classes_in_has_argument_ &&
+         attributes_in_has_argument_ == other.attributes_in_has_argument_ &&
+         ids_in_has_argument_ == other.ids_in_has_argument_ &&
+         tag_names_in_has_argument_ == other.tag_names_in_has_argument_ &&
+         universal_in_has_argument_ == other.universal_in_has_argument_ &&
          is_alive_ == other.is_alive_;
 }
 
@@ -827,6 +837,9 @@
     if (features.invalidation_flags.InvalidatesParts())
       metadata_.invalidates_parts = true;
 
+    if (simple_selector->GetPseudoType() == CSSSelector::kPseudoHas)
+      CollectValuesInHasArgument(*simple_selector);
+
     if (!simple_selector->TagHistory() ||
         simple_selector->Relation() != CSSSelector::kSubSelector) {
       return simple_selector;
@@ -834,6 +847,56 @@
   }
 }
 
+void RuleFeatureSet::CollectValuesInHasArgument(
+    const CSSSelector& has_pseudo_class) {
+  DCHECK_EQ(has_pseudo_class.GetPseudoType(), CSSSelector::kPseudoHas);
+  const CSSSelectorList* selector_list = has_pseudo_class.SelectorList();
+  DCHECK(selector_list);
+
+  for (const CSSSelector* relative_selector = selector_list->First();
+       relative_selector;
+       relative_selector = CSSSelectorList::Next(*relative_selector)) {
+    DCHECK(relative_selector);
+
+    bool value_added = false;
+    const CSSSelector* simple = relative_selector;
+    while (simple->GetPseudoType() != CSSSelector::kPseudoRelativeLeftmost) {
+      value_added |= AddValueOfSimpleSelectorInHasArgument(*simple);
+
+      if (simple->Relation() != CSSSelector::kSubSelector) {
+        if (!value_added)
+          universal_in_has_argument_ = true;
+        value_added = false;
+      }
+
+      simple = simple->TagHistory();
+      DCHECK(simple);
+    }
+  }
+}
+
+bool RuleFeatureSet::AddValueOfSimpleSelectorInHasArgument(
+    const CSSSelector& selector) {
+  if (selector.Match() == CSSSelector::kClass) {
+    classes_in_has_argument_.insert(selector.Value());
+    return true;
+  }
+  if (selector.IsAttributeSelector()) {
+    attributes_in_has_argument_.insert(selector.Attribute().LocalName());
+    return true;
+  }
+  if (selector.Match() == CSSSelector::kId) {
+    ids_in_has_argument_.insert(selector.Value());
+    return true;
+  }
+  if (selector.Match() == CSSSelector::kTag &&
+      selector.TagQName().LocalName() != CSSSelector::UniversalSelectorAtom()) {
+    tag_names_in_has_argument_.insert(selector.TagQName().LocalName());
+    return true;
+  }
+  return false;
+}
+
 // Add features extracted from the rightmost compound selector to descendant
 // invalidation sets for features found in other compound selectors.
 //
@@ -1166,6 +1229,16 @@
       other.viewport_dependent_media_query_results_);
   device_dependent_media_query_results_.AppendVector(
       other.device_dependent_media_query_results_);
+
+  for (const auto& class_name : other.classes_in_has_argument_)
+    classes_in_has_argument_.insert(class_name);
+  for (const auto& attribute_name : other.attributes_in_has_argument_)
+    attributes_in_has_argument_.insert(attribute_name);
+  for (const auto& id : other.ids_in_has_argument_)
+    ids_in_has_argument_.insert(id);
+  for (const auto& tag_name : other.tag_names_in_has_argument_)
+    tag_names_in_has_argument_.insert(tag_name);
+  universal_in_has_argument_ |= other.universal_in_has_argument_;
 }
 
 void RuleFeatureSet::Clear() {
@@ -1180,6 +1253,11 @@
   type_rule_invalidation_set_ = nullptr;
   viewport_dependent_media_query_results_.clear();
   device_dependent_media_query_results_.clear();
+  classes_in_has_argument_.clear();
+  attributes_in_has_argument_.clear();
+  ids_in_has_argument_.clear();
+  tag_names_in_has_argument_.clear();
+  universal_in_has_argument_ = false;
 }
 
 void RuleFeatureSet::CollectInvalidationSetsForClass(
@@ -1417,6 +1495,48 @@
   }
 }
 
+bool RuleFeatureSet::NeedsHasInvalidationForClass(
+    const AtomicString& class_name) const {
+  return classes_in_has_argument_.Contains(class_name);
+}
+
+bool RuleFeatureSet::NeedsHasInvalidationForAttribute(
+    const QualifiedName& attribute_name) const {
+  return attributes_in_has_argument_.Contains(attribute_name.LocalName());
+}
+
+bool RuleFeatureSet::NeedsHasInvalidationForId(const AtomicString& id) const {
+  return ids_in_has_argument_.Contains(id);
+}
+
+bool RuleFeatureSet::NeedsHasInvalidationForTagName(
+    const AtomicString& tag_name) const {
+  return universal_in_has_argument_ ||
+         tag_names_in_has_argument_.Contains(tag_name);
+}
+
+bool RuleFeatureSet::NeedsHasInvalidationForElement(Element& element) const {
+  if (element.HasID()) {
+    if (NeedsHasInvalidationForId(element.IdForStyleResolution()))
+      return true;
+  }
+
+  if (element.HasClass()) {
+    const SpaceSplitString& class_names = element.ClassNames();
+    for (wtf_size_t i = 0; i < class_names.size(); i++) {
+      if (NeedsHasInvalidationForClass(class_names[i]))
+        return true;
+    }
+  }
+
+  for (const Attribute& attribute : element.Attributes()) {
+    if (NeedsHasInvalidationForAttribute(attribute.GetName()))
+      return true;
+  }
+
+  return NeedsHasInvalidationForTagName(element.LocalNameForSelectorMatching());
+}
+
 void RuleFeatureSet::InvalidationSetFeatures::Add(
     const InvalidationSetFeatures& other) {
   classes.AppendVector(other.classes);
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.h b/third_party/blink/renderer/core/css/rule_feature_set.h
index 5c3bf76..a280ffb 100644
--- a/third_party/blink/renderer/core/css/rule_feature_set.h
+++ b/third_party/blink/renderer/core/css/rule_feature_set.h
@@ -145,6 +145,13 @@
   void CollectPartInvalidationSet(InvalidationLists&) const;
   void CollectTypeRuleInvalidationSet(InvalidationLists&, ContainerNode&) const;
 
+  bool NeedsHasInvalidationForClass(const AtomicString& class_name) const;
+  bool NeedsHasInvalidationForAttribute(
+      const QualifiedName& attribute_name) const;
+  bool NeedsHasInvalidationForId(const AtomicString& id) const;
+  bool NeedsHasInvalidationForTagName(const AtomicString& tag_name) const;
+  bool NeedsHasInvalidationForElement(Element&) const;
+
   bool HasIdsInSelectors() const { return id_invalidation_sets_.size() > 0; }
   bool InvalidatesParts() const { return metadata_.invalidates_parts; }
 
@@ -196,6 +203,7 @@
               scoped_refptr<InvalidationSet>,
               WTF::IntHash<unsigned>,
               WTF::UnsignedWithZeroKeyHashTraits<unsigned>>;
+  using ValuesInHasArgument = HashSet<AtomicString>;
 
   struct FeatureMetadata {
     DISALLOW_NEW();
@@ -433,8 +441,11 @@
   void AddFeaturesToUniversalSiblingInvalidationSet(
       const InvalidationSetFeatures& sibling_features,
       const InvalidationSetFeatures& descendant_features);
+  bool AddValueOfSimpleSelectorInHasArgument(
+      const CSSSelector& has_pseudo_class);
 
   void UpdateRuleSetInvalidation(const InvalidationSetFeatures&);
+  void CollectValuesInHasArgument(const CSSSelector& has_pseudo_class);
 
   static InvalidationSet& EnsureMutableInvalidationSet(
       scoped_refptr<InvalidationSet>&,
@@ -474,6 +485,11 @@
   scoped_refptr<DescendantInvalidationSet> type_rule_invalidation_set_;
   MediaQueryResultList viewport_dependent_media_query_results_;
   MediaQueryResultList device_dependent_media_query_results_;
+  ValuesInHasArgument classes_in_has_argument_;
+  ValuesInHasArgument attributes_in_has_argument_;
+  ValuesInHasArgument ids_in_has_argument_;
+  ValuesInHasArgument tag_names_in_has_argument_;
+  bool universal_in_has_argument_{false};
 
   // If true, the RuleFeatureSet is alive and can be used.
   unsigned is_alive_ : 1;
diff --git a/third_party/blink/renderer/core/css/selector_checker.h b/third_party/blink/renderer/core/css/selector_checker.h
index ef39ccd..1b9deca 100644
--- a/third_party/blink/renderer/core/css/selector_checker.h
+++ b/third_party/blink/renderer/core/css/selector_checker.h
@@ -129,7 +129,7 @@
 
    public:
     PseudoId dynamic_pseudo{kPseudoIdNone};
-    AtomicString custom_highlight_name = g_null_atom;
+    AtomicString custom_highlight_name;
 
     // From the shortest argument selector match, we need to get the element
     // that matches the leftmost compound selector to mark the correct scope
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index 9b1a7c2f..8146431 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -956,10 +956,17 @@
   if (ShouldSkipInvalidationFor(element))
     return;
 
+  const RuleFeatureSet& features = GetRuleFeatureSet();
+
   if (RuntimeEnabledFeatures::CSSPseudoHasEnabled() &&
       PossiblyAffectingHasState(element)) {
-    // TODO(blee@igalia.com) Need filtering for irrelevant mutations
-    InvalidateAncestorsAffectedByHas(element.parentElement());
+    unsigned changed_size = changed_classes.size();
+    for (unsigned i = 0; i < changed_size; ++i) {
+      if (features.NeedsHasInvalidationForClass(changed_classes[i])) {
+        InvalidateAncestorsAffectedByHas(element.parentElement());
+        break;
+      }
+    }
   }
 
   if (IsSubtreeAndSiblingsStyleDirty(element))
@@ -967,7 +974,6 @@
 
   InvalidationLists invalidation_lists;
   unsigned changed_size = changed_classes.size();
-  const RuleFeatureSet& features = GetRuleFeatureSet();
   for (unsigned i = 0; i < changed_size; ++i) {
     features.CollectInvalidationSetsForClass(invalidation_lists, element,
                                              changed_classes[i]);
@@ -987,13 +993,11 @@
     return;
   }
 
-  if (RuntimeEnabledFeatures::CSSPseudoHasEnabled() &&
-      PossiblyAffectingHasState(element)) {
-    // TODO(blee@igalia.com) Need filtering for irrelevant mutations
-    InvalidateAncestorsAffectedByHas(element.parentElement());
-  }
-
-  if (IsSubtreeAndSiblingsStyleDirty(element))
+  bool needs_schedule_invalidation = !IsSubtreeAndSiblingsStyleDirty(element);
+  bool possibly_affecting_has_state =
+      RuntimeEnabledFeatures::CSSPseudoHasEnabled() &&
+      PossiblyAffectingHasState(element);
+  if (!needs_schedule_invalidation && !possibly_affecting_has_state)
     return;
 
   // Class vectors tend to be very short. This is faster than using a hash
@@ -1001,6 +1005,7 @@
   WTF::Vector<bool> remaining_class_bits(old_classes.size());
 
   InvalidationLists invalidation_lists;
+  bool affecting_has_state = false;
   const RuleFeatureSet& features = GetRuleFeatureSet();
 
   for (unsigned i = 0; i < new_classes.size(); ++i) {
@@ -1016,8 +1021,16 @@
     }
     // Class was added.
     if (!found) {
-      features.CollectInvalidationSetsForClass(invalidation_lists, element,
-                                               new_classes[i]);
+      if (LIKELY(needs_schedule_invalidation)) {
+        features.CollectInvalidationSetsForClass(invalidation_lists, element,
+                                                 new_classes[i]);
+      }
+      if (UNLIKELY(possibly_affecting_has_state)) {
+        if (features.NeedsHasInvalidationForClass(new_classes[i])) {
+          affecting_has_state = true;
+          possibly_affecting_has_state = false;  // Clear to skip check
+        }
+      }
     }
   }
 
@@ -1025,11 +1038,24 @@
     if (remaining_class_bits[i])
       continue;
     // Class was removed.
-    features.CollectInvalidationSetsForClass(invalidation_lists, element,
-                                             old_classes[i]);
+    if (LIKELY(needs_schedule_invalidation)) {
+      features.CollectInvalidationSetsForClass(invalidation_lists, element,
+                                               old_classes[i]);
+    }
+    if (UNLIKELY(possibly_affecting_has_state)) {
+      if (features.NeedsHasInvalidationForClass(old_classes[i])) {
+        affecting_has_state = true;
+        possibly_affecting_has_state = false;  // Clear to skip check
+      }
+    }
   }
-  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
-                                                         element);
+  if (needs_schedule_invalidation) {
+    pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
+                                                           element);
+  }
+  if (affecting_has_state) {
+    InvalidateAncestorsAffectedByHas(element.parentElement());
+  }
 }
 
 namespace {
@@ -1058,8 +1084,8 @@
 
   if (RuntimeEnabledFeatures::CSSPseudoHasEnabled() &&
       PossiblyAffectingHasState(element)) {
-    // TODO(blee@igalia.com) Need filtering for irrelevant mutations
-    InvalidateAncestorsAffectedByHas(element.parentElement());
+    if (GetRuleFeatureSet().NeedsHasInvalidationForAttribute(attribute_name))
+      InvalidateAncestorsAffectedByHas(element.parentElement());
   }
 
   if (IsSubtreeAndSiblingsStyleDirty(element))
@@ -1085,17 +1111,20 @@
   if (ShouldSkipInvalidationFor(element))
     return;
 
+  const RuleFeatureSet& features = GetRuleFeatureSet();
+
   if (RuntimeEnabledFeatures::CSSPseudoHasEnabled() &&
       PossiblyAffectingHasState(element)) {
-    // TODO(blee@igalia.com) Need filtering for irrelevant mutations
-    InvalidateAncestorsAffectedByHas(element.parentElement());
+    if ((!old_id.IsEmpty() && features.NeedsHasInvalidationForId(old_id)) ||
+        (!new_id.IsEmpty() && features.NeedsHasInvalidationForId(new_id))) {
+      InvalidateAncestorsAffectedByHas(element.parentElement());
+    }
   }
 
   if (IsSubtreeAndSiblingsStyleDirty(element))
     return;
 
   InvalidationLists invalidation_lists;
-  const RuleFeatureSet& features = GetRuleFeatureSet();
   if (!old_id.IsEmpty())
     features.CollectInvalidationSetsForId(invalidation_lists, element, old_id);
   if (!new_id.IsEmpty())
@@ -1315,11 +1344,33 @@
                                                          *document_);
 }
 
-void StyleEngine::ChildElementInsertedOrRemoved(Element* parent) {
-  if (!RuntimeEnabledFeatures::CSSPseudoHasEnabled())
+void StyleEngine::ElementInsertedOrRemoved(Element* parent, Element& element) {
+  if (!RuntimeEnabledFeatures::CSSPseudoHasEnabled() || !parent)
     return;
-  // TODO(blee@igalia.com) Need filtering for irrelevant insertion or removal
-  InvalidateAncestorsAffectedByHas(parent);
+
+  if (ShouldSkipInvalidationFor(*parent))
+    return;
+
+  if (GetRuleFeatureSet().NeedsHasInvalidationForElement(element))
+    InvalidateAncestorsAffectedByHas(parent);
+}
+
+void StyleEngine::SubtreeInsertedOrRemoved(Element* parent,
+                                           Element& subtree_root) {
+  if (!RuntimeEnabledFeatures::CSSPseudoHasEnabled() || !parent)
+    return;
+
+  if (ShouldSkipInvalidationFor(*parent))
+    return;
+
+  const RuleFeatureSet& features = GetRuleFeatureSet();
+  for (Element& element :
+       ElementTraversal::InclusiveDescendantsOf(subtree_root)) {
+    if (features.NeedsHasInvalidationForElement(element)) {
+      InvalidateAncestorsAffectedByHas(parent);
+      return;
+    }
+  }
 }
 
 void StyleEngine::InvalidateStyle() {
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index d919de3..30319d7f 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -385,7 +385,8 @@
                                         InvalidationScope =
                                             kInvalidateCurrentScope);
   void ScheduleCustomElementInvalidations(HashSet<AtomicString> tag_names);
-  void ChildElementInsertedOrRemoved(Element* parent);
+  void ElementInsertedOrRemoved(Element* parent, Element& element);
+  void SubtreeInsertedOrRemoved(Element* parent, Element& subtree_root);
 
   void NodeWillBeRemoved(Node&);
   void ChildrenRemoved(ContainerNode& parent);
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index 30a1f59..1aa4d713 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -4858,4 +4858,169 @@
                            .Serialized());
 }
 
+TEST_F(StyleEngineTest, HasPseudoClassInvalidationSkipIrrelevantClassChange) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>.a:has(.b) { background-color: lime; }</style>
+    <div id=div1>
+      <div id=div2 class='a'>
+        <div id=div3>
+          <div id=div4></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+
+  unsigned start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div4")->setAttribute(html_names::kClassAttr,
+                                                     "c");
+  UpdateAllLifecyclePhases();
+  unsigned element_count =
+      GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(0U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div4")->setAttribute(html_names::kClassAttr,
+                                                     "b");
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+}
+
+TEST_F(StyleEngineTest, HasPseudoClassInvalidationSkipIrrelevantIdChange) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>.a:has(#b) { background-color: lime; }</style>
+    <div id=div1>
+      <div id=div2 class='a'>
+        <div id=div3>
+          <div id=div4></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+
+  unsigned start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div4")->setAttribute(html_names::kIdAttr, "c");
+  UpdateAllLifecyclePhases();
+  unsigned element_count =
+      GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(0U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("c")->setAttribute(html_names::kIdAttr, "b");
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+}
+
+TEST_F(StyleEngineTest,
+       HasPseudoClassInvalidationSkipIrrelevantAttributeChange) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>.a:has([b]) { background-color: lime; }</style>
+    <div id=div1>
+      <div id=div2 class='a'>
+        <div id=div3>
+          <div id=div4></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+
+  unsigned start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div4")->setAttribute(QualifiedName("", "c", ""),
+                                                     "C");
+  UpdateAllLifecyclePhases();
+  unsigned element_count =
+      GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(0U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div4")->setAttribute(QualifiedName("", "b", ""),
+                                                     "B");
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+}
+
+TEST_F(StyleEngineTest,
+       HasPseudoClassInvalidationSkipIrrelevantInsertionRemoval) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>.a:has(.b) { background-color: lime; }</style>
+    <div id=div1>
+      <div id=div2 class='a'>
+        <div id=div3></div>
+        <div id=div4></div>
+      </div>
+    </div>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+
+  unsigned start_count = GetStyleEngine().StyleForElementCount();
+  auto* div5 = MakeGarbageCollected<HTMLDivElement>(GetDocument());
+  div5->setAttribute(html_names::kIdAttr, "div5");
+  div5->setInnerHTML(R"HTML(<div class='c'></div>)HTML");
+  GetDocument().getElementById("div3")->AppendChild(div5);
+  UpdateAllLifecyclePhases();
+  unsigned element_count =
+      GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(2U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  auto* div6 = MakeGarbageCollected<HTMLDivElement>(GetDocument());
+  div6->setAttribute(html_names::kIdAttr, "div6");
+  div6->setInnerHTML(R"HTML(<div class='b'></div>)HTML");
+  GetDocument().getElementById("div4")->AppendChild(div6);
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(3U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div3")->RemoveChild(
+      GetDocument().getElementById("div5"));
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(0U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div4")->RemoveChild(
+      GetDocument().getElementById("div6"));
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+}
+
+TEST_F(StyleEngineTest, HasPseudoClassInvalidationUniversalInArgument) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>.a:has(*) { background-color: lime; }</style>
+    <div id=div1>
+      <div id=div2 class='a'>
+      </div>
+    </div>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+
+  unsigned start_count = GetStyleEngine().StyleForElementCount();
+  auto* div3 = MakeGarbageCollected<HTMLDivElement>(GetDocument());
+  div3->setAttribute(html_names::kIdAttr, "div3");
+  GetDocument().getElementById("div2")->AppendChild(div3);
+  UpdateAllLifecyclePhases();
+  unsigned element_count =
+      GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(2U, element_count);
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetDocument().getElementById("div2")->RemoveChild(
+      GetDocument().getElementById("div3"));
+  UpdateAllLifecyclePhases();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/style_sheet_collection.h b/third_party/blink/renderer/core/css/style_sheet_collection.h
index 142e6bf..4c93d73 100644
--- a/third_party/blink/renderer/core/css/style_sheet_collection.h
+++ b/third_party/blink/renderer/core/css/style_sheet_collection.h
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/active_style_sheets.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/css/style_sheet_list.h b/third_party/blink/renderer/core/css/style_sheet_list.h
index cf1e7cc..a3abbb5 100644
--- a/third_party/blink/renderer/core/css/style_sheet_list.h
+++ b/third_party/blink/renderer/core/css/style_sheet_list.h
@@ -23,6 +23,7 @@
 
 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
 #include "third_party/blink/renderer/core/dom/tree_scope.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/dom/child_frame_disconnector.h b/third_party/blink/renderer/core/dom/child_frame_disconnector.h
index 02155cd2..42c8831 100644
--- a/third_party/blink/renderer/core/dom/child_frame_disconnector.h
+++ b/third_party/blink/renderer/core/dom/child_frame_disconnector.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CHILD_FRAME_DISCONNECTOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CHILD_FRAME_DISCONNECTOR_H_
 
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 79bd91b..a1e4f88 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4018,13 +4018,15 @@
                            change.sibling_after_change);
 
   if (!change.ByParser() && change.IsChildElementChange()) {
+    Element* changed_element = To<Element>(change.sibling_changed);
     CheckForSiblingStyleChanges(
         change.type == ChildrenChangeType::kElementRemoved
             ? kSiblingElementRemoved
             : kSiblingElementInserted,
-        To<Element>(change.sibling_changed), change.sibling_before_change,
+        changed_element, change.sibling_before_change,
         change.sibling_after_change);
-    GetDocument().GetStyleEngine().ChildElementInsertedOrRemoved(this);
+    GetDocument().GetStyleEngine().SubtreeInsertedOrRemoved(this,
+                                                            *changed_element);
   }
 
   if (ShadowRoot* shadow_root = GetShadowRoot())
@@ -4036,7 +4038,8 @@
   CheckForEmptyStyleChange(this, this);
   CheckForSiblingStyleChanges(kFinishedParsingChildren, nullptr, lastChild(),
                               nullptr);
-  GetDocument().GetStyleEngine().ChildElementInsertedOrRemoved(parentElement());
+  GetDocument().GetStyleEngine().ElementInsertedOrRemoved(parentElement(),
+                                                          *this);
 }
 
 AttrNodeList* Element::GetAttrNodeList() {
diff --git a/third_party/blink/renderer/core/dom/frame_request_callback_collection.h b/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
index 8577e44..ccd9e53 100644
--- a/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
+++ b/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
 #include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/dom/id_target_observer_registry.cc b/third_party/blink/renderer/core/dom/id_target_observer_registry.cc
index 39e18c6..f8b477a 100644
--- a/third_party/blink/renderer/core/dom/id_target_observer_registry.cc
+++ b/third_party/blink/renderer/core/dom/id_target_observer_registry.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/core/dom/id_target_observer_registry.h"
 
 #include "third_party/blink/renderer/core/dom/id_target_observer.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/dom/mutation_observer.h b/third_party/blink/renderer/core/dom/mutation_observer.h
index a201ccac..7e5bce6 100644
--- a/third_party/blink/renderer/core/dom/mutation_observer.h
+++ b/third_party/blink/renderer/core/dom/mutation_observer.h
@@ -39,6 +39,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/prefinalizer.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller.h b/third_party/blink/renderer/core/dom/scripted_animation_controller.h
index 98d9d2c..961adcfc 100644
--- a/third_party/blink/renderer/core/dom/scripted_animation_controller.h
+++ b/third_party/blink/renderer/core/dom/scripted_animation_controller.h
@@ -32,6 +32,7 @@
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
diff --git a/third_party/blink/renderer/core/dom/slot_assignment.h b/third_party/blink/renderer/core/dom/slot_assignment.h
index 78a0ffb..a6b38ddf 100644
--- a/third_party/blink/renderer/core/dom/slot_assignment.h
+++ b/third_party/blink/renderer/core/dom/slot_assignment.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/dom/tree_ordered_map.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
diff --git a/third_party/blink/renderer/core/dom/static_node_list.h b/third_party/blink/renderer/core/dom/static_node_list.h
index f0df16b..4525c35c 100644
--- a/third_party/blink/renderer/core/dom/static_node_list.h
+++ b/third_party/blink/renderer/core/dom/static_node_list.h
@@ -30,6 +30,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_STATIC_NODE_LIST_H_
 
 #include "third_party/blink/renderer/core/dom/node_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/dom/tree_ordered_map.h b/third_party/blink/renderer/core/dom/tree_ordered_map.h
index e3132a3..f152257 100644
--- a/third_party/blink/renderer/core/dom/tree_ordered_map.h
+++ b/third_party/blink/renderer/core/dom/tree_ordered_map.h
@@ -35,6 +35,7 @@
 #include "base/dcheck_is_on.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/dom/tree_scope.h b/third_party/blink/renderer/core/dom/tree_scope.h
index 3d63306..b5d94fe 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.h
+++ b/third_party/blink/renderer/core/dom/tree_scope.h
@@ -32,6 +32,7 @@
 #include "third_party/blink/renderer/core/html/forms/radio_button_group_scope.h"
 #include "third_party/blink/renderer/core/layout/hit_test_request.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
diff --git a/third_party/blink/renderer/core/editing/commands/undo_stack.h b/third_party/blink/renderer/core/editing/commands/undo_stack.h
index 1f685215..111f62c9 100644
--- a/third_party/blink/renderer/core/editing/commands/undo_stack.h
+++ b/third_party/blink/renderer/core/editing/commands/undo_stack.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_UNDO_STACK_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.h b/third_party/blink/renderer/core/editing/finder/text_finder.h
index b55165a6..4f5ae91 100644
--- a/third_party/blink/renderer/core/editing/finder/text_finder.h
+++ b/third_party/blink/renderer/core/editing/finder/text_finder.h
@@ -36,6 +36,7 @@
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h b/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h
index 438a636..1a14047 100644
--- a/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h
+++ b/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_ACTIVE_SUGGESTION_MARKER_LIST_IMPL_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h b/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h
index 155ee0e0..4ca766f8 100644
--- a/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h
+++ b/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_COMPOSITION_MARKER_LIST_IMPL_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker.h b/third_party/blink/renderer/core/editing/markers/document_marker.h
index a0523366..d2c65f4 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker.h
+++ b/third_party/blink/renderer/core/editing/markers/document_marker.h
@@ -25,6 +25,7 @@
 
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_list.h b/third_party/blink/renderer/core/editing/markers/document_marker_list.h
index 81da5a7..6e0678f 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_list.h
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_list.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h b/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h
index 9c9c40d..fd8765e 100644
--- a/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h
+++ b/third_party/blink/renderer/core/editing/markers/highlight_marker_list_impl.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_HIGHLIGHT_MARKER_LIST_IMPL_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h b/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h
index 7a43078..ba88c1fc 100644
--- a/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h
+++ b/third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_SORTED_DOCUMENT_MARKER_LIST_EDITOR_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h b/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h
index eb31ae9..a753484 100644
--- a/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h
+++ b/third_party/blink/renderer/core/editing/markers/spell_check_marker_list_impl.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_SPELL_CHECK_MARKER_LIST_IMPL_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h b/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h
index f08badf..5b5289e 100644
--- a/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h
+++ b/third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
 #include "third_party/blink/renderer/core/editing/markers/suggestion_marker.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h b/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
index 6e3a4d4b..cc30897 100644
--- a/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
+++ b/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_LIST_IMPL_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor.h b/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor.h
index 0c3471ef..86297b2 100644
--- a/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor.h
+++ b/third_party/blink/renderer/core/editing/markers/unsorted_document_marker_list_editor.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_UNSORTED_DOCUMENT_MARKER_LIST_EDITOR_H_
 
 #include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h b/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h
index 323a150..9e17c50f 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h
+++ b/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_HOT_MODE_SPELL_CHECK_REQUESTER_H_
 
 #include "third_party/blink/renderer/core/editing/forward.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/events/application_cache_error_event_init.idl b/third_party/blink/renderer/core/events/application_cache_error_event_init.idl
deleted file mode 100644
index 8a82332..0000000
--- a/third_party/blink/renderer/core/events/application_cache_error_event_init.idl
+++ /dev/null
@@ -1,10 +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.
-
-dictionary ApplicationCacheErrorEventInit : EventInit {
-    DOMString reason;
-    DOMString url;
-    unsigned short status;
-    DOMString message;
-};
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h
index 48c53db..8c6143e 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.h
+++ b/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -47,6 +47,7 @@
 #include "third_party/blink/renderer/core/execution_context/security_context.h"
 #include "third_party/blink/renderer/core/frame/dom_timer_coordinator.h"
 #include "third_party/blink/renderer/core/frame/web_feature_forward.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap_observer_set.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
diff --git a/third_party/blink/renderer/core/execution_context/security_context_init.cc b/third_party/blink/renderer/core/execution_context/security_context_init.cc
index ff853b2..27493d8 100644
--- a/third_party/blink/renderer/core/execution_context/security_context_init.cc
+++ b/third_party/blink/renderer/core/execution_context/security_context_init.cc
@@ -124,13 +124,13 @@
     const ResourceResponse& response,
     const absl::optional<WebOriginPolicy>& origin_policy,
     const FramePolicy& frame_policy) {
+  const url::Origin origin =
+      execution_context_->GetSecurityOrigin()->ToUrlOrigin();
   // If we are a HTMLViewSourceDocument we use container, header or
   // inherited policies. https://crbug.com/898688.
   if (frame.InViewSourceMode()) {
     execution_context_->GetSecurityContext().SetPermissionsPolicy(
-        PermissionsPolicy::CreateFromParentPolicy(
-            nullptr, {},
-            execution_context_->GetSecurityOrigin()->ToUrlOrigin()));
+        PermissionsPolicy::CreateFromParentPolicy(nullptr, {}, origin));
     return;
   }
 
@@ -214,13 +214,20 @@
   }
 
   std::unique_ptr<PermissionsPolicy> permissions_policy;
-  auto* parent_permissions_policy =
-      frame.Tree().Parent()
-          ? frame.Tree().Parent()->GetSecurityContext()->GetPermissionsPolicy()
-          : nullptr;
-  permissions_policy = PermissionsPolicy::CreateFromParentPolicy(
-      parent_permissions_policy, container_policy,
-      execution_context_->GetSecurityOrigin()->ToUrlOrigin());
+  if (frame.IsInFencedFrameTree()) {
+    // In Fenced Frames, all permission policy gated features must be disabled
+    // for privacy reasons.
+    permissions_policy = PermissionsPolicy::CreateForFencedFrame(origin);
+  } else {
+    auto* parent_permissions_policy = frame.Tree().Parent()
+                                          ? frame.Tree()
+                                                .Parent()
+                                                ->GetSecurityContext()
+                                                ->GetPermissionsPolicy()
+                                          : nullptr;
+    permissions_policy = PermissionsPolicy::CreateFromParentPolicy(
+        parent_permissions_policy, container_policy, origin);
+  }
   permissions_policy->SetHeaderPolicy(permissions_policy_header_);
   execution_context_->GetSecurityContext().SetPermissionsPolicy(
       std::move(permissions_policy));
diff --git a/third_party/blink/renderer/core/fragment_directive/build.gni b/third_party/blink/renderer/core/fragment_directive/build.gni
index 8e89625..9c4ba7a 100644
--- a/third_party/blink/renderer/core/fragment_directive/build.gni
+++ b/third_party/blink/renderer/core/fragment_directive/build.gni
@@ -3,8 +3,16 @@
 # found in the LICENSE file.
 
 blink_core_sources_fragment_directive = [
+  "css_selector_directive.cc",
+  "css_selector_directive.h",
+  "css_selector_fragment_anchor.cc",
+  "css_selector_fragment_anchor.h",
   "fragment_directive.cc",
   "fragment_directive.h",
+  "fragment_directive_utils.cc",
+  "fragment_directive_utils.h",
+  "selector_fragment_anchor.cc",
+  "selector_fragment_anchor.h",
   "text_directive.cc",
   "text_directive.h",
   "text_fragment_anchor.cc",
diff --git a/third_party/blink/renderer/core/fragment_directive/css_selector_directive.cc b/third_party/blink/renderer/core/fragment_directive/css_selector_directive.cc
new file mode 100644
index 0000000..0793a8e4
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/css_selector_directive.cc
@@ -0,0 +1,76 @@
+// 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 "third_party/blink/renderer/core/fragment_directive/css_selector_directive.h"
+
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+namespace {
+// TODO(crbug/1253707) Reject the directive string if it uses anything not
+// allowed by the spec
+bool ParseCssSelectorDirective(const String& directive_string, String& value) {
+  if (!directive_string.StartsWith(
+          shared_highlighting::kSelectorDirectiveParameterName) ||
+      !directive_string.EndsWith(shared_highlighting::kSelectorDirectiveSuffix))
+    return false;
+
+  Vector<String> parts;
+  // get rid of "selector(" and ")" and split the rest by ","
+  directive_string
+      .Substring(
+          shared_highlighting::kSelectorDirectiveParameterNameLength,
+          directive_string.length() -
+              shared_highlighting::kSelectorDirectiveParameterNameLength -
+              shared_highlighting::kSelectorDirectiveSuffixLength)
+      .Split(",", /*allow_empty_entries=*/false, parts);
+
+  bool parsed_value = false;
+  bool parsed_type = false;
+  String type;
+  for (auto& part : parts) {
+    if (part.StartsWith(shared_highlighting::kSelectorDirectiveValuePrefix)) {
+      // ambiguous case, can't have two value= parts
+      if (parsed_value)
+        return false;
+      value = DecodeURLEscapeSequences(
+          part.Substring(
+              shared_highlighting::kSelectorDirectiveValuePrefixLength),
+          DecodeURLMode::kUTF8);
+      parsed_value = true;
+    } else if (part.StartsWith(
+                   shared_highlighting::kSelectorDirectiveTypePrefix)) {
+      // ambiguous case, can't have two type= parts
+      if (parsed_type)
+        return false;
+      type = part.Substring(
+          shared_highlighting::kSelectorDirectiveTypePrefixLength);
+      parsed_type = true;
+    }
+  }
+  return type == shared_highlighting::kTypeCssSelector && parsed_value;
+}
+
+}  // namespace
+
+CssSelectorDirective* CssSelectorDirective::TryParse(
+    const String& directive_string) {
+  String value;
+  if (ParseCssSelectorDirective(directive_string, value)) {
+    return MakeGarbageCollected<CssSelectorDirective>(value);
+  }
+
+  return nullptr;
+}
+
+CssSelectorDirective::CssSelectorDirective(const String& value)
+    : Directive(Directive::kSelector), value_(value) {}
+
+String CssSelectorDirective::ToStringImpl() const {
+  return "selector(type=CssSelector,value=" +
+         EncodeWithURLEscapeSequences(value_) + ")";
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/css_selector_directive.h b/third_party/blink/renderer/core/fragment_directive/css_selector_directive.h
new file mode 100644
index 0000000..39b54d60
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/css_selector_directive.h
@@ -0,0 +1,36 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_CSS_SELECTOR_DIRECTIVE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_CSS_SELECTOR_DIRECTIVE_H_
+
+#include "third_party/blink/renderer/core/frame/directive.h"
+
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+// Parses directive string and extracts value part of CssSelectorDirective
+// to be used with QuerySelector() for finding the element
+// https://github.com/WICG/scroll-to-text-fragment/blob/main/EXTENSIONS.md#proposed-solution
+// TODO(crbug/1265423): Rename to SelectorDirective
+class CssSelectorDirective : public Directive {
+ public:
+  static CssSelectorDirective* TryParse(const String& directive_string);
+  static Type ClassType() { return kSelector; }
+  explicit CssSelectorDirective(const String& value);
+
+  const AtomicString value() const { return value_; }
+
+ protected:
+  String ToStringImpl() const override;
+
+ private:
+  // an accepted CSS selector string specified in the directive's value field,
+  AtomicString value_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_CSS_SELECTOR_DIRECTIVE_H_
diff --git a/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.cc b/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.cc
new file mode 100644
index 0000000..c24279f
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.cc
@@ -0,0 +1,89 @@
+// 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 "third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.h"
+
+#include "base/feature_list.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fragment_directive/css_selector_directive.h"
+#include "third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+
+namespace blink {
+
+CssSelectorFragmentAnchor* CssSelectorFragmentAnchor::TryCreate(
+    const KURL& url,
+    LocalFrame& frame,
+    bool should_scroll) {
+  DCHECK(RuntimeEnabledFeatures::CSSSelectorFragmentAnchorEnabled());
+
+  Document& doc = *frame.GetDocument();
+  HeapVector<Member<CssSelectorDirective>> css_selector_directives =
+      frame.GetDocument()
+          ->fragmentDirective()
+          .GetDirectives<CssSelectorDirective>();
+
+  if (css_selector_directives.IsEmpty())
+    return nullptr;
+
+  Element* anchor_node = nullptr;
+  for (CssSelectorDirective* directive : css_selector_directives) {
+    if (!directive->value().IsEmpty())
+      anchor_node = doc.RootNode().QuerySelector(directive->value());
+    // TODO(crbug.com/1265721): this will ignore directives after the first
+    // successful match, for now we are just scrolling the element into view,
+    // later when we add highlighting, it's good considering highlighting all
+    // matching elements.
+    if (anchor_node)
+      break;
+  }
+
+  doc.SetCSSTarget(anchor_node);
+
+  if (!anchor_node)
+    return nullptr;
+
+  return MakeGarbageCollected<CssSelectorFragmentAnchor>(*anchor_node, frame,
+                                                         should_scroll);
+}
+
+CssSelectorFragmentAnchor::CssSelectorFragmentAnchor(Element& anchor_node,
+                                                     LocalFrame& frame,
+                                                     bool should_scroll)
+    : SelectorFragmentAnchor(frame, should_scroll),
+      anchor_node_(&anchor_node) {}
+
+bool CssSelectorFragmentAnchor::InvokeSelector() {
+  DCHECK(anchor_node_);
+
+  // if user has not scrolled yet, do the necessary work to scroll anchor_node_
+  // into view, otherwise we are done scrolling.
+  if (!user_scrolled_ && should_scroll_ &&
+      frame_->GetDocument()->IsLoadCompleted()) {
+    ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
+    options->setBlock("center");
+    options->setInlinePosition("nearest");
+    ScrollElementIntoViewWithOptions(anchor_node_, options);
+    should_scroll_ = false;
+  }
+
+  return true;
+}
+
+void CssSelectorFragmentAnchor::PerformPreRafActions() {}
+
+void CssSelectorFragmentAnchor::Installed() {}
+
+void CssSelectorFragmentAnchor::Trace(Visitor* visitor) const {
+  visitor->Trace(anchor_node_);
+  SelectorFragmentAnchor::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.h b/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.h
new file mode 100644
index 0000000..f3da0bb
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.h
@@ -0,0 +1,53 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_CSS_SELECTOR_FRAGMENT_ANCHOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_CSS_SELECTOR_FRAGMENT_ANCHOR_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h"
+#include "third_party/blink/renderer/core/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class LocalFrame;
+class KURL;
+class Element;
+
+// This class is responsible for finding the selector directive part of the
+// directive string in fragment if there are any, and scrolling it into the
+// middle of the viewport.
+// https://github.com/WICG/scroll-to-text-fragment/blob/main/EXTENSIONS.md#proposed-solution
+class CORE_EXPORT CssSelectorFragmentAnchor final
+    : public SelectorFragmentAnchor {
+ public:
+  static CssSelectorFragmentAnchor* TryCreate(const KURL& url,
+                                              LocalFrame& frame,
+                                              bool should_scroll);
+
+  CssSelectorFragmentAnchor(Element& anchor_node,
+                            LocalFrame& frame,
+                            bool should_scroll);
+  CssSelectorFragmentAnchor(const CssSelectorFragmentAnchor&) = delete;
+  CssSelectorFragmentAnchor& operator=(const CssSelectorFragmentAnchor&) =
+      delete;
+  ~CssSelectorFragmentAnchor() override = default;
+
+  void Installed() override;
+
+  bool InvokeSelector() override;
+
+  void PerformPreRafActions() override;
+
+  void Trace(Visitor*) const override;
+
+ private:
+  Member<Element> anchor_node_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_CSS_SELECTOR_FRAGMENT_ANCHOR_H_
diff --git a/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor_test.cc b/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor_test.cc
new file mode 100644
index 0000000..0cfb665e
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor_test.cc
@@ -0,0 +1,480 @@
+// 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 "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/web/web_script_source.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/css/css_style_declaration.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/html_anchor_element.h"
+#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
+#include "third_party/blink/renderer/core/html/html_image_element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+using test::RunPendingTasks;
+
+class CssSelectorFragmentAnchorTest : public SimTest {
+ public:
+  void SetUp() override {
+    SimTest::SetUp();
+
+    // Focus handlers aren't run unless the page is focused.
+    GetDocument().GetPage()->GetFocusController().SetFocused(true);
+
+    WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
+  }
+
+  ScrollableArea* LayoutViewport() {
+    return GetDocument().View()->LayoutViewport();
+  }
+
+  IntRect ViewportRect() {
+    return IntRect(gfx::Point(), LayoutViewport()->VisibleContentRect().size());
+  }
+
+  IntRect BoundingRectInFrame(Node& node) {
+    return node.GetLayoutObject()->AbsoluteBoundingBoxRect();
+  }
+
+  void SimulateClick(int x, int y) {
+    WebMouseEvent event(WebInputEvent::Type::kMouseDown, gfx::PointF(x, y),
+                        gfx::PointF(x, y), WebPointerProperties::Button::kLeft,
+                        0, WebInputEvent::Modifiers::kLeftButtonDown,
+                        base::TimeTicks::Now());
+    event.SetFrameScale(1);
+    WebView().MainFrameWidget()->ProcessInputEventSynchronouslyForTesting(
+        WebCoalescedInputEvent(event, ui::LatencyInfo()), base::DoNothing());
+  }
+
+  bool IsVisibleInViewport(Element& element) {
+    return ViewportRect().Contains(BoundingRectInFrame(element));
+  }
+};
+
+// Make sure we find the element and scroll it to the middle of viewport.
+TEST_F(CssSelectorFragmentAnchorTest, BasicTest) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/"
+      "test.html#:~:selector(type=CssSelector,value=img[src$=\"image.svg\"])",
+      "text/html");
+  SimRequest image_request("https://example.com/image.svg", "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/"
+      "test.html#:~:selector(type=CssSelector,value=img[src$=\"image.svg\"])");
+
+  // main frame widget size is 800x600
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <body style="margin:0px;">
+      <div style="height:600px;">some text</div>
+      <img id="image" src="image.svg" style="vertical-align:top;">
+      <div style="height:600px;">some other text</div>
+      </body>
+    )HTML");
+
+  image_request.Complete(R"SVG(
+      <svg id="svg" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="100" cy="100" r="100" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  // +-------------------------------+   <-- 0px
+  // | some text (height:600px)
+  // |
+  // |
+  // |
+  // |                                   <-- 400px (scroll offset)  | visible
+  // |                                                              | height
+  // | circle (height:200px)                                        |
+  // |                                                              |
+  // | some other text (height:600px)                               |
+  // |                                                              |
+  // |
+  // |
+  // |
+  // |
+  // +-------------------------------+
+  EXPECT_EQ(ScrollOffset(0, 400), LayoutViewport()->GetScrollOffset())
+      << "<img> was not EXACTLY scrolled into the MIDDLE of the viewport "
+      << "vertically, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+
+  Element& img = *GetDocument().getElementById("image");
+  EXPECT_TRUE(IsVisibleInViewport(img))
+      << "<img> Element wasn't scrolled into view, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+
+  EXPECT_EQ(img, *GetDocument().CssTarget());
+}
+
+// When more than one CssSelector Fragments are present, scroll the first one
+// into view
+TEST_F(CssSelectorFragmentAnchorTest, TwoCssSelectorFragmentsScrollToFirst) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=img[src$=\"second.svg\"])"
+      "&selector(type=CssSelector,value=img[src$=\"first.svg\"])",
+      "text/html");
+  SimRequest first_img_request("https://example.com/first.svg",
+                               "image/svg+xml");
+  SimRequest second_img_request("https://example.com/second.svg",
+                                "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=img[src$=\"second.svg\"])"
+      "&selector(type=CssSelector,value=img[src$=\"first.svg\"])");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <img id="first" src="first.svg">
+      <p style="height:1000px;">some other text</p>
+      <img id="second" src="second.svg">
+      <p style="height:1000px;">yet some more text</p>
+    )HTML");
+
+  first_img_request.Complete(R"SVG(
+      <svg id="svg" width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="25" cy="25" r="25" fill="red"/>
+      </svg>
+    )SVG");
+
+  second_img_request.Complete(R"SVG(
+      <svg id="svg" width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="25" cy="25" r="25" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  Element& second = *GetDocument().getElementById("second");
+
+  EXPECT_EQ(second, *GetDocument().CssTarget());
+  EXPECT_TRUE(IsVisibleInViewport(second))
+      << "second <img> Element wasn't scrolled into view, viewport's scroll "
+         "offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+}
+
+// If the first CssSelector Fragment is not found, look for the second one
+// and scroll it into view
+TEST_F(CssSelectorFragmentAnchorTest, TwoCssSelectorFragmentsFirstNotFound) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=img[src$=\"penguin.svg\"])"
+      "&selector(type=CssSelector,value=img[src$=\"first.svg\"])",
+      "text/html");
+  SimRequest image_request("https://example.com/first.svg", "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=img[src$=\"penguin.svg\"])"
+      "&selector(type=CssSelector,value=img[src$=\"first.svg\"])");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <img id="first" src="first.svg">
+      <p style="height:1000px;">some other text</p>
+    )HTML");
+
+  image_request.Complete(R"SVG(
+      <svg id="svg" width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="25" cy="25" r="25" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  Element& first = *GetDocument().getElementById("first");
+
+  EXPECT_EQ(first, *GetDocument().CssTarget());
+  EXPECT_TRUE(IsVisibleInViewport(first))
+      << "<img> Element wasn't scrolled into view, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+}
+
+// If both CssSelectorFragment and ElementFragment present,
+// prioritize CssSelectorFragment
+TEST_F(CssSelectorFragmentAnchorTest,
+       PrioritizeCssSelectorFragmentOverElementFragment) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html#element"
+      ":~:selector(type=CssSelector,value=img[src$=\"first.svg\"])",
+      "text/html");
+  SimRequest image_request("https://example.com/first.svg", "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/test.html#element"
+      ":~:selector(type=CssSelector,value=img[src$=\"first.svg\"])");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <img id="first" src="first.svg">
+      <p style="height:1000px;">some other text</p>
+      <p id="element" style="height:1000px;">the element!</p>
+    )HTML");
+
+  image_request.Complete(R"SVG(
+      <svg id="svg" width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="25" cy="25" r="25" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  Element& first = *GetDocument().getElementById("first");
+
+  EXPECT_EQ(first, *GetDocument().CssTarget());
+  EXPECT_TRUE(IsVisibleInViewport(first))
+      << "<img> Element wasn't scrolled into view, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+}
+
+// TODO(crbug/1253707): Enable after fixing!
+// Don't scroll into view if attribute selector is not allowed according to spec
+// https://github.com/WICG/scroll-to-text-fragment/blob/main/EXTENSIONS.md#proposed-solution
+TEST_F(CssSelectorFragmentAnchorTest, DISABLED_CheckCssSelectorRestrictions) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=div[id$=\"first\"])",
+      "text/html");
+
+  LoadURL(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=div[id$=\"first\"])");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <div id="first" style="height:50px;">some other text</p>
+      <p style="height:1000px;">another paragraph</p>
+    )HTML");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  EXPECT_EQ(ScrollOffset(0, 0), LayoutViewport()->GetScrollOffset())
+      << "No scroll should happen, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+  EXPECT_EQ(nullptr, *GetDocument().CssTarget());
+
+  EXPECT_FALSE(GetDocument().View()->GetFragmentAnchor());
+
+  EXPECT_EQ(GetDocument().Url(), "https://example.com/test.html");
+}
+
+// Make sure fragment is dismissed after user clicks
+TEST_F(CssSelectorFragmentAnchorTest, DismissFragmentAfterUserClicks) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/"
+      "test.html#:~:selector(type=CssSelector,value=img[src$=\"image.svg\"])",
+      "text/html");
+  SimRequest image_request("https://example.com/image.svg", "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/"
+      "test.html#:~:selector(type=CssSelector,value=img[src$=\"image.svg\"])");
+
+  // main frame widget size is 800x600
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <body style="margin:0px;">
+      <div style="height:600px;">some text</div>
+      <img id="image" src="image.svg" style="vertical-align:top;">
+      <div style="height:600px;">some other text</div>
+      </body>
+    )HTML");
+
+  image_request.Complete(R"SVG(
+      <svg id="svg" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="100" cy="100" r="100" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  Element& img = *GetDocument().getElementById("image");
+  EXPECT_TRUE(IsVisibleInViewport(img))
+      << "<img> Element wasn't scrolled into view, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+  EXPECT_EQ(img, *GetDocument().CssTarget());
+
+  SimulateClick(100, 100);
+
+  EXPECT_FALSE(GetDocument().View()->GetFragmentAnchor());
+
+  KURL url = GetDocument()
+                 .GetFrame()
+                 ->Loader()
+                 .GetDocumentLoader()
+                 ->GetHistoryItem()
+                 ->Url();
+  EXPECT_EQ("https://example.com/test.html", url);
+}
+
+// Although parsed correctly, the element is not found, hence no scroll happens
+// and scroll offset should be zero
+TEST_F(CssSelectorFragmentAnchorTest, ParsedCorrectlyButElementNotFound) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=img[src$=\"lorem.svg\"])",
+      "text/html");
+
+  LoadURL(
+      "https://example.com/test.html"
+      "#:~:selector(type=CssSelector,value=img[src$=\"lorem.svg\"])");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <p style="height:1000px;">another paragraph</p>
+    )HTML");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  EXPECT_EQ(ScrollOffset(0, 0), LayoutViewport()->GetScrollOffset())
+      << "No scroll should happen, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+  EXPECT_EQ(nullptr, *GetDocument().CssTarget());
+
+  EXPECT_FALSE(GetDocument().View()->GetFragmentAnchor());
+}
+
+// value= part should be encoded/decoded
+TEST_F(CssSelectorFragmentAnchorTest, ValuePartHasCommaAndIsEncoded) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html"
+      //      "#:~:selector(value=img[src$="cat,dog"],type=CssSelector)",
+      "#:~:selector(value=img%5Bsrc%24%3D%22cat%2Cdog%22%5D,type=CssSelector)",
+      "text/html");
+  SimRequest img_request("https://example.com/cat,dog", "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/test.html"
+      "#:~:selector(value=img%5Bsrc%24%3D%22cat%2Cdog%22%5D,type=CssSelector)");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <img id="first" src="cat,dog">
+      <p style="height:1000px;">some other text</p>
+    )HTML");
+
+  img_request.Complete(R"SVG(
+      <svg id="svg" width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="25" cy="25" r="25" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  Element& first = *GetDocument().getElementById("first");
+
+  EXPECT_EQ(first, *GetDocument().CssTarget());
+  EXPECT_TRUE(IsVisibleInViewport(first))
+      << "second <img> Element wasn't scrolled into view, viewport's scroll "
+         "offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+}
+
+// What if value= part is not encoded, and it contains a comma,
+// Should not crash, and should not scroll to anywhere and no fragment anchor
+TEST_F(CssSelectorFragmentAnchorTest, ValuePartHasCommaButIsNotEncoded) {
+  base::test::ScopedFeatureList feature_list_;
+  feature_list_.InitAndEnableFeature(
+      blink::features::kCssSelectorFragmentAnchor);
+
+  SimRequest main_request(
+      "https://example.com/test.html"
+      "#:~:selector(value=img[src$=\"cat,dog\"],type=CssSelector)",
+      "text/html");
+  SimRequest img_request("https://example.com/cat,dog", "image/svg+xml");
+
+  LoadURL(
+      "https://example.com/test.html"
+      "#:~:selector(value=img[src$=\"cat,dog\"],type=CssSelector)");
+
+  main_request.Complete(R"HTML(
+      <!DOCTYPE html>
+      <p style="height:1000px;">some text</p>
+      <img id="first" src="cat,dog">
+      <p style="height:1000px;">some other text</p>
+    )HTML");
+
+  img_request.Complete(R"SVG(
+      <svg id="svg" width="50" height="50" xmlns="http://www.w3.org/2000/svg">
+         <circle class="path" cx="25" cy="25" r="25" fill="red"/>
+      </svg>
+    )SVG");
+
+  test::RunPendingTasks();
+  Compositor().BeginFrame();
+
+  EXPECT_FALSE(GetDocument().View()->GetFragmentAnchor());
+  EXPECT_EQ(nullptr, *GetDocument().CssTarget());
+  EXPECT_EQ(ScrollOffset(0, 0), LayoutViewport()->GetScrollOffset())
+      << "No scroll should happen, viewport's scroll offset: "
+      << LayoutViewport()->GetScrollOffset().ToString();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/fragment_directive.cc b/third_party/blink/renderer/core/fragment_directive/fragment_directive.cc
index 532793d..b5ddbe6 100644
--- a/third_party/blink/renderer/core/fragment_directive/fragment_directive.cc
+++ b/third_party/blink/renderer/core/fragment_directive/fragment_directive.cc
@@ -4,12 +4,14 @@
 
 #include "third_party/blink/renderer/core/fragment_directive/fragment_directive.h"
 
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_union_range_selection.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/range.h"
 #include "third_party/blink/renderer/core/editing/dom_selection.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/fragment_directive/css_selector_directive.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_directive.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_selector_generator.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -19,15 +21,6 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
-namespace {
-
-constexpr char kFragmentDirectivePrefix[] = ":~:";
-// Subtract 1 because base::size includes the \0 string terminator.
-constexpr size_t kFragmentDirectivePrefixStringLength =
-    base::size(kFragmentDirectivePrefix) - 1;
-
-}  // namespace
-
 namespace blink {
 
 FragmentDirective::FragmentDirective(Document& owner_document)
@@ -38,7 +31,8 @@
   // Strip the fragment directive from the URL fragment. E.g. "#id:~:text=a"
   // --> "#id". See https://github.com/WICG/scroll-to-text-fragment.
   String fragment = url.FragmentIdentifier();
-  wtf_size_t start_pos = fragment.Find(kFragmentDirectivePrefix);
+  wtf_size_t start_pos =
+      fragment.Find(shared_highlighting::kFragmentsUrlDelimiter);
 
   last_navigation_had_fragment_directive_ = start_pos != kNotFound;
   fragment_directive_string_length_ = 0;
@@ -46,8 +40,8 @@
     return url;
 
   KURL new_url = url;
-  String fragment_directive =
-      fragment.Substring(start_pos + kFragmentDirectivePrefixStringLength);
+  String fragment_directive = fragment.Substring(
+      start_pos + shared_highlighting::kFragmentsUrlDelimiterLength);
 
   if (start_pos == 0)
     new_url.RemoveFragmentIdentifier();
@@ -177,6 +171,9 @@
 
       if (TextDirective* text_directive = TextDirective::Create(value))
         new_directives.push_back(text_directive);
+    } else if (auto* selector_directive =
+                   CssSelectorDirective::TryParse(directive_string)) {
+      new_directives.push_back(selector_directive);
     }
   }
 
diff --git a/third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.cc b/third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.cc
new file mode 100644
index 0000000..2db4bb9
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.cc
@@ -0,0 +1,28 @@
+// 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 "third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h"
+
+#include "components/shared_highlighting/core/common/fragment_directives_utils.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/loader/document_loader.h"
+
+namespace blink {
+
+// static
+void FragmentDirectiveUtils::RemoveSelectorsFromUrl(LocalFrame* frame) {
+  KURL url(shared_highlighting::RemoveFragmentSelectorDirectives(
+      frame->Loader().GetDocumentLoader()->GetHistoryItem()->Url()));
+
+  // Replace the current history entry with the new url, so that the text
+  // fragment shown in the URL matches the state of the highlight on the page.
+  // This is equivalent to history.replaceState in javascript.
+  frame->DomWindow()->document()->Loader()->RunURLAndHistoryUpdateSteps(
+      url, mojom::blink::SameDocumentNavigationType::kFragment,
+      /*data=*/nullptr, WebFrameLoadType::kReplaceCurrentItem,
+      mojom::blink::ScrollRestorationType::kAuto);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h b/third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h
new file mode 100644
index 0000000..dd90f21
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h
@@ -0,0 +1,20 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_FRAGMENT_DIRECTIVE_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_FRAGMENT_DIRECTIVE_UTILS_H_
+
+namespace blink {
+
+class LocalFrame;
+
+class FragmentDirectiveUtils {
+ public:
+  // Updates the URL by removing the text fragment selector.
+  static void RemoveSelectorsFromUrl(LocalFrame* frame);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_FRAGMENT_DIRECTIVE_UTILS_H_
diff --git a/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc
new file mode 100644
index 0000000..c1f42c3
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.cc
@@ -0,0 +1,56 @@
+// 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 "third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h"
+
+#include "base/feature_list.h"
+#include "components/shared_highlighting/core/common/shared_highlighting_features.h"
+#include "third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h"
+#include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/page/page.h"
+
+namespace blink {
+
+void SelectorFragmentAnchor::DidScroll(mojom::blink::ScrollType type) {
+  if (type != mojom::blink::ScrollType::kUser &&
+      type != mojom::blink::ScrollType::kCompositor) {
+    return;
+  }
+
+  if (ShouldDismissOnScrollOrClick() && Dismiss())
+    FragmentDirectiveUtils::RemoveSelectorsFromUrl(frame_);
+
+  user_scrolled_ = true;
+}
+
+void SelectorFragmentAnchor::Trace(Visitor* visitor) const {
+  FragmentAnchor::Trace(visitor);
+}
+
+bool SelectorFragmentAnchor::Invoke() {
+  // Wait until the page has been made visible before searching.
+  if (!frame_->GetPage()->IsPageVisible() && !page_has_been_visible_) {
+    return true;
+  }
+  page_has_been_visible_ = true;
+
+  if (dismissed_)
+    return false;
+  return InvokeSelector();
+}
+
+bool SelectorFragmentAnchor::Dismiss() {
+  if (dismissed_)
+    return true;
+
+  return dismissed_ = true;
+}
+
+bool SelectorFragmentAnchor::ShouldDismissOnScrollOrClick() {
+  return !base::FeatureList::IsEnabled(
+      shared_highlighting::kSharedHighlightingV2);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h
new file mode 100644
index 0000000..0d0be32
--- /dev/null
+++ b/third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h
@@ -0,0 +1,54 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_SELECTOR_FRAGMENT_ANCHOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_SELECTOR_FRAGMENT_ANCHOR_H_
+
+#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
+#include "third_party/blink/renderer/core/scroll/scroll_types.h"
+
+namespace blink {
+class LocalFrame;
+
+class CORE_EXPORT SelectorFragmentAnchor : public FragmentAnchor {
+ public:
+  explicit SelectorFragmentAnchor(LocalFrame& frame, bool should_scroll)
+      : FragmentAnchor(frame), should_scroll_(should_scroll) {}
+  SelectorFragmentAnchor(const SelectorFragmentAnchor&) = delete;
+  SelectorFragmentAnchor& operator=(const SelectorFragmentAnchor&) = delete;
+  ~SelectorFragmentAnchor() override = default;
+
+  void DidScroll(mojom::blink::ScrollType type) override;
+
+  bool Invoke() override;
+
+  void Trace(Visitor*) const override;
+
+  bool Dismiss() override;
+
+  static bool ShouldDismissOnScrollOrClick();
+
+ protected:
+  // This will be invoked by Invoke() when the page is visible until the
+  // fragment has been dismissed. See FragmentAnchor::Invoke for details about
+  // usage.
+  virtual bool InvokeSelector() = 0;
+
+  // Whether we should scroll the anchor into view. This will be false for
+  // history navigations and reloads, where we want to restore the highlight but
+  // not scroll into view again.
+  bool should_scroll_ = false;
+  // Whether the user has scrolled the page
+  bool user_scrolled_ = false;
+  // Whether the fragment anchor has been dismissed yet. This should be
+  // kept alive until dismissed so we can remove highlightings.
+  bool dismissed_ = false;
+  // Whether the page has been made visible. Used to ensure we wait until the
+  // page has been made visible to start matching, to help prevent brute force
+  // search attacks.
+  bool page_has_been_visible_ = false;
+};
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAGMENT_DIRECTIVE_SELECTOR_FRAGMENT_ANCHOR_H_
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.cc
index 8c6d2e2..74116e6 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.cc
@@ -4,8 +4,7 @@
 
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h"
 
-#include "components/shared_highlighting/core/common/shared_highlighting_features.h"
-#include "components/shared_highlighting/core/common/text_fragments_utils.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #include "third_party/blink/renderer/core/display_lock/display_lock_document_state.h"
 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -15,6 +14,7 @@
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
 #include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_directive.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_handler.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_selector.h"
@@ -158,8 +158,7 @@
     HeapVector<Member<TextDirective>>& text_directives,
     LocalFrame& frame,
     bool should_scroll)
-    : frame_(&frame),
-      should_scroll_(should_scroll),
+    : SelectorFragmentAnchor(frame, should_scroll),
       metrics_(MakeGarbageCollected<TextFragmentAnchorMetrics>(
           frame_->GetDocument())) {
   DCHECK(!text_directives.IsEmpty());
@@ -179,13 +178,7 @@
   }
 }
 
-bool TextFragmentAnchor::Invoke() {
-  // Wait until the page has been made visible before searching.
-  if (!frame_->GetPage()->IsPageVisible() && !page_has_been_visible_)
-    return true;
-  else
-    page_has_been_visible_ = true;
-
+bool TextFragmentAnchor::InvokeSelector() {
   // We need to keep this TextFragmentAnchor alive if we're proxying an
   // element fragment anchor.
   if (element_fragment_anchor_) {
@@ -262,17 +255,11 @@
 void TextFragmentAnchor::Installed() {}
 
 void TextFragmentAnchor::DidScroll(mojom::blink::ScrollType type) {
-  if (type != mojom::blink::ScrollType::kUser &&
-      type != mojom::blink::ScrollType::kCompositor) {
-    return;
-  }
+  SelectorFragmentAnchor::DidScroll(type);
 
-  if (ShouldDismissOnScrollOrClick() && Dismiss())
-    TextFragmentHandler::RemoveSelectorsFromUrl(frame_);
-
-  user_scrolled_ = true;
-
-  if (did_non_zero_scroll_ &&
+  if ((type == mojom::blink::ScrollType::kUser ||
+       type == mojom::blink::ScrollType::kCompositor) &&
+      did_non_zero_scroll_ &&
       frame_->View()->GetScrollableArea()->GetScrollOffset().IsZero()) {
     metrics_->DidScrollToTop();
   }
@@ -301,11 +288,10 @@
 }
 
 void TextFragmentAnchor::Trace(Visitor* visitor) const {
-  visitor->Trace(frame_);
   visitor->Trace(element_fragment_anchor_);
   visitor->Trace(metrics_);
   visitor->Trace(directive_finder_pairs_);
-  FragmentAnchor::Trace(visitor);
+  SelectorFragmentAnchor::Trace(visitor);
 }
 
 void TextFragmentAnchor::DidFindMatch(
@@ -487,10 +473,9 @@
 
   frame_->GetDocument()->Markers().RemoveMarkersOfTypes(
       DocumentMarker::MarkerTypes::TextFragment());
-  dismissed_ = true;
   metrics_->Dismissed();
 
-  return dismissed_;
+  return SelectorFragmentAnchor::Dismiss();
 }
 
 void TextFragmentAnchor::ApplyTargetToCommonAncestor(
@@ -539,9 +524,4 @@
       frame_->GetDocument()->Loader()->GetRequestorOrigin()->ToString());
 }
 
-bool TextFragmentAnchor::ShouldDismissOnScrollOrClick() {
-  return !base::FeatureList::IsEnabled(
-      shared_highlighting::kSharedHighlightingV2);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h
index 726d021..fb66530d 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h
@@ -9,10 +9,10 @@
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/editing/forward.h"
+#include "third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor_metrics.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_finder.h"
 #include "third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h"
-#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
 #include "third_party/blink/renderer/core/scroll/scroll_types.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -24,7 +24,7 @@
 class KURL;
 class TextDirective;
 
-class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
+class CORE_EXPORT TextFragmentAnchor final : public SelectorFragmentAnchor,
                                              public TextFragmentFinder::Client {
  public:
   // When a document is loaded, this method will be called to see if it meets
@@ -54,7 +54,7 @@
   TextFragmentAnchor& operator=(const TextFragmentAnchor&) = delete;
   ~TextFragmentAnchor() override = default;
 
-  bool Invoke() override;
+  bool InvokeSelector() override;
 
   void Installed() override;
 
@@ -76,8 +76,6 @@
 
   void NoMatchFound() override {}
 
-  static bool ShouldDismissOnScrollOrClick();
-
   using DirectiveFinderPair =
       std::pair<Member<TextDirective>, Member<TextFragmentFinder>>;
   const HeapVector<DirectiveFinderPair>& DirectiveFinderPairs() const {
@@ -103,11 +101,7 @@
   // performing the search for the specified text in the Document.
   HeapVector<DirectiveFinderPair> directive_finder_pairs_;
 
-  Member<LocalFrame> frame_;
-
   bool search_finished_ = false;
-  // Whether the user has scrolled the page.
-  bool user_scrolled_ = false;
   // Indicates that we should scroll into view the first match that we find, set
   // to true each time the anchor is invoked if the user hasn't scrolled.
   bool first_match_needs_scroll_ = false;
@@ -120,17 +114,6 @@
   // If the text fragment anchor is defined as a fragment directive and we don't
   // find a match, we fall back to the element anchor if it is present.
   Member<ElementFragmentAnchor> element_fragment_anchor_;
-  // Whether the text fragment anchor has been dismissed yet. This should be
-  // kept alive until dismissed so we can remove text highlighting.
-  bool dismissed_ = false;
-  // Whether we should scroll the anchor into view. This will be false for
-  // history navigations and reloads, where we want to restore the highlight but
-  // not scroll into view again.
-  bool should_scroll_ = false;
-  // Whether the page has been made visible. Used to ensure we wait until the
-  // page has been made visible to start matching, to help prevent brute force
-  // search attacks.
-  bool page_has_been_visible_ = false;
   // Whether we performed a non-zero scroll to scroll a match into view. Used
   // to determine whether the user subsequently scrolls back to the top.
   bool did_non_zero_scroll_ = false;
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
index bc2ad21..1b5f370 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.cc
@@ -7,8 +7,8 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/strcat.h"
 #include "components/shared_highlighting/core/common/disabled_sites.h"
+#include "components/shared_highlighting/core/common/fragment_directives_utils.h"
 #include "components/shared_highlighting/core/common/shared_highlighting_features.h"
-#include "components/shared_highlighting/core/common/text_fragments_utils.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/core/editing/range_in_flat_tree.h"
 #include "third_party/blink/renderer/core/editing/selection_editor.h"
 #include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -95,7 +96,7 @@
     // text fragment anchor, the selectors still need to be removed from the
     // URL. This is because dismissing the text fragment anchors is a page-wide
     // operation, and the URL might have selectors for a subframe.
-    RemoveSelectorsFromUrl(frame);
+    FragmentDirectiveUtils::RemoveSelectorsFromUrl(frame);
   }
 }
 
@@ -279,17 +280,4 @@
   return static_cast<TextFragmentAnchor*>(fragmentAnchor);
 }
 
-// static
-void TextFragmentHandler::RemoveSelectorsFromUrl(LocalFrame* frame) {
-  KURL url(
-      shared_highlighting::RemoveTextFragments(frame->GetDocument()->Url()));
-  // Replace the current history entry with the new url, so that the text
-  // fragment shown in the URL matches the state of the highlight on the page.
-  // This is equivalent to history.replaceState in javascript.
-  frame->DomWindow()->document()->Loader()->RunURLAndHistoryUpdateSteps(
-      url, mojom::blink::SameDocumentNavigationType::kFragment,
-      /*data=*/nullptr, WebFrameLoadType::kReplaceCurrentItem,
-      mojom::blink::ScrollRestorationType::kAuto);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.h b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.h
index 65a88f1..a0d3868 100644
--- a/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.h
+++ b/third_party/blink/renderer/core/fragment_directive/text_fragment_handler.h
@@ -31,9 +31,6 @@
   // Determine if |result| represents a click on an existing highlight.
   static bool IsOverTextFragment(HitTestResult result);
 
-  // Updates the URL by removing the text fragment selector.
-  static void RemoveSelectorsFromUrl(LocalFrame* frame);
-
   // mojom::blink::TextFragmentReceiver interface
   void Cancel() override;
   void RequestSelector(RequestSelectorCallback callback) override;
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 be158cc..2f81a6b 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
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy_violation_type.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
diff --git a/third_party/blink/renderer/core/frame/directive.cc b/third_party/blink/renderer/core/frame/directive.cc
index d2cf21c..71f1664 100644
--- a/third_party/blink/renderer/core/frame/directive.cc
+++ b/third_party/blink/renderer/core/frame/directive.cc
@@ -17,13 +17,16 @@
 
 String Directive::type() const {
   DEFINE_STATIC_LOCAL(const String, text, ("text"));
+  DEFINE_STATIC_LOCAL(const String, selector, ("selector"));
 
   switch (type_) {
-    case kText:
-      return text;
     case kUnknown:
       NOTREACHED();
       return String();
+    case kText:
+      return text;
+    case kSelector:
+      return selector;
   }
 
   NOTREACHED();
diff --git a/third_party/blink/renderer/core/frame/directive.h b/third_party/blink/renderer/core/frame/directive.h
index c94b875a..bf45d74 100644
--- a/third_party/blink/renderer/core/frame/directive.h
+++ b/third_party/blink/renderer/core/frame/directive.h
@@ -19,7 +19,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  enum Type { kText, kUnknown };
+  enum Type { kUnknown, kText, kSelector };
 
   explicit Directive(Type type);
   ~Directive() override;
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h
index 56ce3ac..35dcc00 100644
--- a/third_party/blink/renderer/core/frame/frame.h
+++ b/third_party/blink/renderer/core/frame/frame.h
@@ -382,6 +382,14 @@
     provisional_frame_ = provisional_frame;
   }
 
+  // Returns false if fenced frames are disabled. Returns true if the
+  // feature is enabled and if |this| or any of its ancestor nodes is a
+  // fenced frame. For MPArch based fenced frames returns the value of
+  // Page::IsMainFrameFencedFrameRoot and for shadowDOM based fenced frames
+  // returns true, if the FrameTree that this frame is in is not the outermost
+  // FrameTree.
+  bool IsInFencedFrameTree() const;
+
  protected:
   // |inheriting_agent_factory| should basically be set to the parent frame or
   // opener's WindowAgentFactory. Pass nullptr if the frame is isolated from
@@ -426,13 +434,6 @@
       mojom::blink::ResourceTimingInfoPtr timing,
       const String& server_timing_values);
 
-  // Returns false if fenced frames are disabled. Returns true if the
-  // feature is enabled and if |this| or any of its ancestor nodes is a
-  // fenced frame. For MPArch returns the value of
-  // Page::IsMainFrameFencedFrameRoot and for shadowDOM returns true, if
-  // the FrameTree that this frame is in is not the outermost FrameTree.
-  bool IsInFencedFrameTree() const;
-
   mutable FrameTree tree_node_;
 
   Member<Page> page_;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 80c016d4..2bda4cdd 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -62,6 +62,7 @@
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
 #include "third_party/blink/renderer/core/events/error_event.h"
 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
+#include "third_party/blink/renderer/core/fragment_directive/fragment_directive_utils.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_handler.h"
 #include "third_party/blink/renderer/core/frame/browser_controls.h"
 #include "third_party/blink/renderer/core/frame/find_in_page.h"
@@ -1824,7 +1825,7 @@
     return;
 
   if (fragment_anchor_->Dismiss()) {
-    TextFragmentHandler::RemoveSelectorsFromUrl(frame_);
+    FragmentDirectiveUtils::RemoveSelectorsFromUrl(frame_);
     fragment_anchor_ = nullptr;
   }
 }
diff --git a/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc b/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc
index b97c181..6dd8bef 100644
--- a/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc
+++ b/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc
@@ -6,6 +6,7 @@
 
 #include "base/auto_reset.h"
 #include "third_party/blink/renderer/core/frame/platform_event_controller.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 123ad36..365711b 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -2856,8 +2856,10 @@
         presentation_time_callback_(std::move(presentation_time_callback)),
         task_runner_(std::move(task_runner)),
         widget_(widget) {}
+
   ReportTimeSwapPromise(const ReportTimeSwapPromise&) = delete;
   ReportTimeSwapPromise& operator=(const ReportTimeSwapPromise&) = delete;
+
   ~ReportTimeSwapPromise() override = default;
 
   void DidActivate() override {}
@@ -2879,26 +2881,14 @@
             std::move(presentation_time_callback_), frame_token_));
   }
 
-  cc::SwapPromise::DidNotSwapAction DidNotSwap(
-      DidNotSwapReason reason) override {
-    // During a failed swap, return the current time regardless of whether we're
-    // using presentation or swap timestamps.
-    PostCrossThreadTask(
-        *task_runner_, FROM_HERE,
-        CrossThreadBindOnce(
-            [](base::TimeTicks swap_time,
-               base::OnceCallback<void(base::TimeTicks)> swap_time_callback,
-               base::OnceCallback<void(base::TimeTicks)>
-                   presentation_time_callback) {
-              ReportTime(std::move(swap_time_callback), swap_time);
-              ReportTime(std::move(presentation_time_callback), swap_time);
-            },
-            base::TimeTicks::Now(), std::move(swap_time_callback_),
-            std::move(presentation_time_callback_)));
+  DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override {
+    ReportSwapAndPresentationFailureOnTaskRunner(
+        task_runner_, std::move(swap_time_callback_),
+        std::move(presentation_time_callback_), base::TimeTicks::Now());
     return DidNotSwapAction::BREAK_PROMISE;
   }
 
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 
  private:
   static void RunCallbackAfterSwap(
@@ -2946,6 +2936,25 @@
       std::move(callback).Run(time);
   }
 
+  static void ReportSwapAndPresentationFailureOnTaskRunner(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      base::OnceCallback<void(base::TimeTicks)> swap_time_callback,
+      base::OnceCallback<void(base::TimeTicks)> presentation_time_callback,
+      base::TimeTicks failure_time) {
+    if (!task_runner->BelongsToCurrentThread()) {
+      PostCrossThreadTask(
+          *task_runner, FROM_HERE,
+          CrossThreadBindOnce(&ReportSwapAndPresentationFailureOnTaskRunner,
+                              task_runner, std::move(swap_time_callback),
+                              std::move(presentation_time_callback),
+                              failure_time));
+      return;
+    }
+
+    ReportTime(std::move(swap_time_callback), failure_time);
+    ReportTime(std::move(presentation_time_callback), failure_time);
+  }
+
   base::OnceCallback<void(base::TimeTicks)> swap_time_callback_;
   base::OnceCallback<void(base::TimeTicks)> presentation_time_callback_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/third_party/blink/renderer/core/geometry/dom_rect_list.h b/third_party/blink/renderer/core/geometry/dom_rect_list.h
index 737b4878..0a43da1 100644
--- a/third_party/blink/renderer/core/geometry/dom_rect_list.h
+++ b/third_party/blink/renderer/core/geometry/dom_rect_list.h
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/core/geometry/dom_rect.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/geometry/float_quad.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h b/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h
index cc3e4ef..0c5cde5f 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h
+++ b/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_REACTION_QUEUE_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h b/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h
index 2b8cc343..9eccdfb 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h
+++ b/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h b/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h
index cb9935c..0a6a664b 100644
--- a/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h
+++ b/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FENCED_FRAME_DOCUMENT_FENCED_FRAMES_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FENCED_FRAME_DOCUMENT_FENCED_FRAMES_H_
 
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 
diff --git a/third_party/blink/renderer/core/html/forms/form_controller.h b/third_party/blink/renderer/core/html/forms/form_controller.h
index abe14c3a..bdbcd4b 100644
--- a/third_party/blink/renderer/core/html/forms/form_controller.h
+++ b/third_party/blink/renderer/core/html/forms/form_controller.h
@@ -25,6 +25,7 @@
 
 #include <memory>
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/html/forms/listed_element.h b/third_party/blink/renderer/core/html/forms/listed_element.h
index bd6071b..f77d472 100644
--- a/third_party/blink/renderer/core/html/forms/listed_element.h
+++ b/third_party/blink/renderer/core/html/forms/listed_element.h
@@ -26,6 +26,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_LISTED_ELEMENT_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/text/text_direction.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc
index ca16b66f..6261192 100644
--- a/third_party/blink/renderer/core/html/forms/select_type.cc
+++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -443,6 +443,10 @@
   if (change.ReattachLayoutTree())
     return;
   UpdateTextStyle();
+  if (auto* layout_object = select_->GetLayoutObject()) {
+    // Invalidate paint to ensure that the focus ring is updated.
+    layout_object->SetShouldDoFullPaintInvalidation();
+  }
   if (PopupIsVisible())
     popup_->UpdateFromElement(PopupMenu::kByStyleChange);
 }
diff --git a/third_party/blink/renderer/core/html/html_meta_element.cc b/third_party/blink/renderer/core/html/html_meta_element.cc
index 7a89571..acad9be 100644
--- a/third_party/blink/renderer/core/html/html_meta_element.cc
+++ b/third_party/blink/renderer/core/html/html_meta_element.cc
@@ -34,10 +34,13 @@
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h"
+#include "third_party/blink/renderer/core/loader/frame_fetch_context.h"
 #include "third_party/blink/renderer/core/loader/http_equiv.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
 
@@ -612,6 +615,8 @@
       UseCounter::Count(&GetDocument(),
                         WebFeature::kHTMLMetaElementMonetization);
     }
+  } else if (EqualIgnoringASCIICase(name_value, http_names::kAcceptCH)) {
+    ProcessMetaAcceptCH(GetDocument(), content_value, /*is_http_equiv*/ false);
   }
 }
 
@@ -638,4 +643,38 @@
 const AtomicString& HTMLMetaElement::GetName() const {
   return FastGetAttribute(html_names::kNameAttr);
 }
+
+// static
+void HTMLMetaElement::ProcessMetaAcceptCH(Document& document,
+                                          const AtomicString& content,
+                                          bool is_http_equiv) {
+  if (is_http_equiv
+          ? !RuntimeEnabledFeatures::ClientHintsMetaHTTPEquivAcceptCHEnabled()
+          : !RuntimeEnabledFeatures::ClientHintsMetaNameAcceptCHEnabled()) {
+    return;
+  }
+
+  LocalFrame* frame = document.GetFrame();
+  if (!frame)
+    return;
+
+  if (!frame->IsMainFrame()) {
+    return;
+  }
+
+  if (!FrameFetchContext::AllowScriptFromSourceWithoutNotifying(
+          document.Url(), frame->GetContentSettingsClient(),
+          frame->GetSettings())) {
+    // Do not allow configuring client hints if JavaScript is disabled.
+    return;
+  }
+
+  UseCounter::Count(
+      document, is_http_equiv ? WebFeature::kClientHintsMetaHTTPEquivAcceptCH
+                              : WebFeature::kClientHintsMetaNameAcceptCH);
+  FrameClientHintsPreferencesContext hints_context(frame);
+  frame->GetClientHintsPreferences().UpdateFromMetaTagAcceptCH(
+      content, document.Url(), &hints_context);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_meta_element.h b/third_party/blink/renderer/core/html/html_meta_element.h
index eeb87ad8..319f19d3 100644
--- a/third_party/blink/renderer/core/html/html_meta_element.h
+++ b/third_party/blink/renderer/core/html/html_meta_element.h
@@ -49,6 +49,10 @@
       Document*,
       bool viewport_meta_zero_values_quirk);
 
+  static void ProcessMetaAcceptCH(Document&,
+                                  const AtomicString& content,
+                                  bool is_http_equiv);
+
   explicit HTMLMetaElement(Document&);
 
   // Encoding computed from processing the http-equiv, charset and content
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.h b/third_party/blink/renderer/core/html/media/autoplay_policy.h
index 2d8dc56..762edc82 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.h
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.h
@@ -8,6 +8,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
index fc0d9918..811b8bf 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
+++ b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.h b/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.h
index 570ce9c..52de56d 100644
--- a/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.h
+++ b/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/timer.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/html/media/video_wake_lock.h b/third_party/blink/renderer/core/html/media/video_wake_lock.h
index 89af446..4343fb72 100644
--- a/third_party/blink/renderer/core/html/media/video_wake_lock.h
+++ b/third_party/blink/renderer/core/html/media/video_wake_lock.h
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/html/media/remote_playback_observer.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
 #include "third_party/blink/renderer/core/page/page_visibility_observer.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
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 5dcab34f..29b8ba5 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
@@ -994,11 +994,8 @@
 }
 
 template <typename Token>
-static void HandleMetaNameAttribute(
+void TokenPreloadScanner::HandleMetaNameAttribute(
     const Token& token,
-    CachedDocumentParameters* document_parameters,
-    MediaValuesCached* media_values,
-    CSSPreloadScanner* css_scanner,
     absl::optional<ViewportDescription>* viewport) {
   const typename Token::Attribute* name_attribute =
       token.GetAttributeItem(html_names::kNameAttr);
@@ -1013,14 +1010,20 @@
 
   String content_attribute_value(content_attribute->Value());
   if (EqualIgnoringASCIICase(name_attribute_value, "viewport")) {
-    HandleMetaViewport(content_attribute_value, document_parameters,
-                       media_values, viewport);
+    HandleMetaViewport(content_attribute_value, document_parameters_.get(),
+                       media_values_.Get(), viewport);
     return;
   }
 
   if (EqualIgnoringASCIICase(name_attribute_value, "referrer")) {
-    HandleMetaReferrer(content_attribute_value, document_parameters,
-                       css_scanner);
+    HandleMetaReferrer(content_attribute_value, document_parameters_.get(),
+                       &css_scanner_);
+  }
+
+  if (EqualIgnoringASCIICase(name_attribute_value, http_names::kAcceptCH) &&
+      RuntimeEnabledFeatures::ClientHintsMetaNameAcceptCHEnabled()) {
+    client_hints_preferences_.UpdateFromMetaTagAcceptCH(
+        content_attribute->Value(), document_url_, nullptr);
   }
 }
 
@@ -1117,19 +1120,20 @@
                                      "content-security-policy")) {
             *is_csp_meta_tag = true;
           } else if (EqualIgnoringASCIICase(equiv_attribute_value,
-                                            "accept-ch")) {
+                                            http_names::kAcceptCH) &&
+                     RuntimeEnabledFeatures::
+                         ClientHintsMetaHTTPEquivAcceptCHEnabled()) {
             const typename Token::Attribute* content_attribute =
                 token.GetAttributeItem(html_names::kContentAttr);
             if (content_attribute) {
-              client_hints_preferences_.UpdateFromHttpEquivAcceptCH(
+              client_hints_preferences_.UpdateFromMetaTagAcceptCH(
                   content_attribute->Value(), document_url_, nullptr);
             }
           }
           return;
         }
 
-        HandleMetaNameAttribute(token, document_parameters_.get(),
-                                media_values_.Get(), &css_scanner_, viewport);
+        HandleMetaNameAttribute(token, viewport);
       }
 
       if (Match(tag_impl, html_names::kBodyTag)) {
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 3a79a55..fa1ba7e 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
@@ -113,6 +113,10 @@
   class StartTagScanner;
 
   template <typename Token>
+  void HandleMetaNameAttribute(const Token& token,
+                               absl::optional<ViewportDescription>* viewport);
+
+  template <typename Token>
   inline void ScanCommon(const Token&,
                          const SegmentedString&,
                          PreloadRequestStream& requests,
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc
index d8b6f3d..29da01ab 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -26,7 +26,7 @@
 #include "third_party/blink/renderer/core/events/mouse_event.h"
 #include "third_party/blink/renderer/core/events/pointer_event_factory.h"
 #include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
-#include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.h"
+#include "third_party/blink/renderer/core/fragment_directive/selector_fragment_anchor.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/local_frame_view.h"
@@ -677,7 +677,7 @@
 
   mouse_down_ = event.Event();
 
-  if (frame_->View() && TextFragmentAnchor::ShouldDismissOnScrollOrClick())
+  if (frame_->View() && SelectorFragmentAnchor::ShouldDismissOnScrollOrClick())
     frame_->View()->DismissFragmentAnchor();
 
   if (frame_->GetDocument()->IsSVGDocument() &&
diff --git a/third_party/blink/renderer/core/inspector/devtools_session.h b/third_party/blink/renderer/core/inspector/devtools_session.h
index e73b2e8c..79c695f 100644
--- a/third_party/blink/renderer/core/inspector/devtools_session.h
+++ b/third_party/blink/renderer/core/inspector/devtools_session.h
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/inspector/inspector_session_state.h"
 #include "third_party/blink/renderer/core/inspector/protocol/forward.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h"
diff --git a/third_party/blink/renderer/core/inspector/dom_patch_support.h b/third_party/blink/renderer/core/inspector/dom_patch_support.h
index 785abae..0f03d44 100644
--- a/third_party/blink/renderer/core/inspector/dom_patch_support.h
+++ b/third_party/blink/renderer/core/inspector/dom_patch_support.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_PATCH_SUPPORT_H_
 
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_history.h b/third_party/blink/renderer/core/inspector/inspector_history.h
index 11dcb08..a0fa2903 100644
--- a/third_party/blink/renderer/core/inspector/inspector_history.h
+++ b/third_party/blink/renderer/core/inspector/inspector_history.h
@@ -33,6 +33,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h b/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h
index d5a0ced..8f9c887 100644
--- a/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h
+++ b/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_RESOURCE_CONTENT_LOADER_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.h b/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
index 8ab358e..374ce372 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_geometry.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
index d7561bb..35e978f 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/platform/geometry/length.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/forward.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
index 890c4b2..aff01ce 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.h b/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.h
index 5fa3c69..fd96aef 100644
--- a/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.h
+++ b/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_DEPTH_ORDERED_LAYOUT_OBJECT_LIST_H_
 
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/third_party/blink/renderer/core/layout/hit_test_cache.h b/third_party/blink/renderer/core/layout/hit_test_cache.h
index 4cfb050..49571e4e 100644
--- a/third_party/blink/renderer/core/layout/hit_test_cache.h
+++ b/third_party/blink/renderer/core/layout/hit_test_cache.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
diff --git a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_scope.h b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_scope.h
index fbdb3db1..6f60fe8 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_scope.h
+++ b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_scope.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_CUSTOM_CUSTOM_LAYOUT_SCOPE_H_
 
 #include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h
index 17a17dd..c1c468a 100644
--- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h
+++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
index 8c0da37..a27ce57 100644
--- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
+++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
@@ -6,6 +6,7 @@
 
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
index a10d6cf2..a770f76 100644
--- a/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
+++ b/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 07f84c0..46e16b94 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -435,7 +435,11 @@
   MinMaxSizes sizes{ComputeTotalColumnSize(SizingConstraint::kMinContent),
                     ComputeTotalColumnSize(SizingConstraint::kMaxContent)};
   sizes += BorderScrollbarPadding().InlineSum();
-  return MinMaxSizesResult(sizes, depends_on_block_constraints);
+
+  // TODO(crbug.com/1272533): This should be |depends_on_block_constraints|
+  // (rather than false). However we need more cache slots to handle the
+  // performance degredation we currently experience. See bug for more details.
+  return MinMaxSizesResult(sizes, /* depends_on_block_constraints */ false);
 }
 
 const TrackSpanProperties& GridItemData::GetTrackSpanProperties(
diff --git a/third_party/blink/renderer/core/layout/svg/svg_text_chunk_builder.h b/third_party/blink/renderer/core/layout/svg/svg_text_chunk_builder.h
index 6df8dba0..4c8c959 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_text_chunk_builder.h
+++ b/third_party/blink/renderer/core/layout/svg/svg_text_chunk_builder.h
@@ -20,6 +20,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_TEXT_CHUNK_BUILDER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_TEXT_CHUNK_BUILDER_H_
 
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/layout/svg/svg_text_layout_attributes_builder.h b/third_party/blink/renderer/core/layout/svg/svg_text_layout_attributes_builder.h
index b71f9694..a0fbd974 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_text_layout_attributes_builder.h
+++ b/third_party/blink/renderer/core/layout/svg/svg_text_layout_attributes_builder.h
@@ -21,6 +21,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_SVG_TEXT_LAYOUT_ATTRIBUTES_BUILDER_H_
 
 #include "third_party/blink/renderer/core/layout/svg/svg_character_data.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/layout/table_grid_cell.h b/third_party/blink/renderer/core/layout/table_grid_cell.h
index 75169ac..f33829d 100644
--- a/third_party/blink/renderer/core/layout/table_grid_cell.h
+++ b/third_party/blink/renderer/core/layout/table_grid_cell.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_GRID_CELL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_TABLE_GRID_CELL_H_
 
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h b/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h
index 5a02e50..fe10674 100644
--- a/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h
+++ b/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.h
@@ -24,6 +24,7 @@
 #include "third_party/blink/renderer/core/layout/table_layout_algorithm.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 #include "third_party/blink/renderer/platform/geometry/length.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 1eca187..5fcb19d 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -34,6 +34,7 @@
 
 #include "base/auto_reset.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "base/time/default_tick_clock.h"
 #include "build/chromeos_buildflags.h"
 #include "services/network/public/cpp/client_hints.h"
@@ -2158,11 +2159,11 @@
 
   // TODO(https://crbug.com/888079): Just use the storage key sent by the
   // browser once the browser will be able to compute the origin in all cases.
+  // TODO(https://crbug.com/1271402): Make sure we have the intended behavior
+  // for initial about:blank navigations, where storage_key_ might be unset.
   frame_->DomWindow()->SetStorageKey(
-      storage_key_.GetNonce().has_value()
-          ? BlinkStorageKey::CreateWithNonce(security_origin,
-                                             storage_key_.GetNonce().value())
-          : BlinkStorageKey(security_origin));
+      BlinkStorageKey(security_origin, storage_key_.GetTopLevelSite(),
+                      base::OptionalOrNullptr(storage_key_.GetNonce())));
 
   // Conceptually, SecurityOrigin doesn't have to be initialized after sandbox
   // flags are applied, but there's a UseCounter in SetSecurityOrigin() that
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 3c443c0..a69f2ad 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -449,8 +449,10 @@
 
   // Check if |url| is allowed to run JavaScript. If not, client hints are not
   // attached to the requests that initiate on the render side.
-  if (!AllowScriptFromSourceWithoutNotifying(request.Url()))
+  if (!AllowScriptFromSourceWithoutNotifying(
+          request.Url(), GetContentSettingsClient(), GetSettings())) {
     return;
+  }
 
   // When the runtime flag "FeaturePolicyForClientHints" is enabled, permissions
   // policy is used to enable hints for all subresources, based on the policy of
@@ -526,19 +528,23 @@
 }
 
 bool FrameFetchContext::AllowScriptFromSource(const KURL& url) const {
-  if (AllowScriptFromSourceWithoutNotifying(url))
+  if (AllowScriptFromSourceWithoutNotifying(url, GetContentSettingsClient(),
+                                            GetSettings())) {
     return true;
+  }
   WebContentSettingsClient* settings_client = GetContentSettingsClient();
   if (settings_client)
     settings_client->DidNotAllowScript();
   return false;
 }
 
+// static
 bool FrameFetchContext::AllowScriptFromSourceWithoutNotifying(
-    const KURL& url) const {
-  Settings* settings = GetSettings();
+    const KURL& url,
+    WebContentSettingsClient* settings_client,
+    Settings* settings) {
   bool allow_script = !settings || settings->GetScriptEnabled();
-  if (auto* settings_client = GetContentSettingsClient())
+  if (settings_client)
     allow_script = settings_client->AllowScriptFromSource(allow_script, url);
   return allow_script;
 }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 868c11b..29d45f66 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -66,6 +66,17 @@
 class CORE_EXPORT FrameFetchContext final : public BaseFetchContext,
                                             public LoadingBehaviorObserver {
  public:
+  // Returns true if execution of scripts from the url are allowed. Compared to
+  // AllowScriptFromSource(), this method does not generate any
+  // notification to the `WebContentSettingsClient` that the execution of the
+  // script was blocked. This method should be called only when there is a need
+  // to check the settings, and where blocked setting doesn't really imply that
+  // JavaScript was blocked from being executed.
+  static bool AllowScriptFromSourceWithoutNotifying(
+      const KURL& url,
+      WebContentSettingsClient* settings_client,
+      Settings* settings);
+
   static ResourceFetcher* CreateFetcherForCommittedDocument(DocumentLoader&,
                                                             Document&);
   FrameFetchContext(DocumentLoader& document_loader,
@@ -199,14 +210,6 @@
                             const ClientHintsPreferences&) const;
   void SetFirstPartyCookie(ResourceRequest&);
 
-  // Returns true if execution of scripts from the url are allowed. Compared to
-  // AllowScriptFromSource(), this method does not generate any
-  // notification to the |WebContentSettingsClient| that the execution of the
-  // script was blocked. This method should be called only when there is a need
-  // to check the settings, and where blocked setting doesn't really imply that
-  // JavaScript was blocked from being executed.
-  bool AllowScriptFromSourceWithoutNotifying(const KURL&) const;
-
   // Returns true if the origin of |url| is same as the origin of the top level
   // frame's main resource.
   bool IsFirstPartyOrigin(const KURL& url) const;
diff --git a/third_party/blink/renderer/core/loader/http_equiv.cc b/third_party/blink/renderer/core/loader/http_equiv.cc
index ea87912..c333025 100644
--- a/third_party/blink/renderer/core/loader/http_equiv.cc
+++ b/third_party/blink/renderer/core/loader/http_equiv.cc
@@ -14,14 +14,13 @@
 #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/settings.h"
+#include "third_party/blink/renderer/core/html/html_meta_element.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
 #include "third_party/blink/renderer/platform/bindings/v8_binding.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/loader/fetch/client_hints_preferences.h"
 #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/runtime_enabled_features.h"
@@ -30,26 +29,6 @@
 
 namespace blink {
 
-namespace {
-
-// Returns true if execution of scripts from the url are allowed. Compared to
-// AllowScriptFromSource(), this method does not generate any
-// notification to the |ContentSettingsClient| that the execution of the
-// script was blocked. This method should be called only when there is a need
-// to check the settings, and where blocked setting doesn't really imply that
-// JavaScript was blocked from being executed.
-bool AllowScriptFromSourceWithoutNotifying(
-    const KURL& url,
-    WebContentSettingsClient* settings_client,
-    Settings* settings) {
-  bool allow_script = !settings || settings->GetScriptEnabled();
-  if (settings_client)
-    allow_script = settings_client->AllowScriptFromSource(allow_script, url);
-  return allow_script;
-}
-
-}  // namespace
-
 void HttpEquiv::Process(Document& document,
                         const AtomicString& equiv,
                         const AtomicString& content,
@@ -75,7 +54,8 @@
         "X-Frame-Options may only be set via an HTTP header sent along with a "
         "document. It may not be set inside <meta>."));
   } else if (EqualIgnoringASCIICase(equiv, http_names::kAcceptCH)) {
-    ProcessHttpEquivAcceptCH(document, content);
+    HTMLMetaElement::ProcessMetaAcceptCH(document, content,
+                                         /*is_http_equiv*/ true);
   } else if (EqualIgnoringASCIICase(equiv, "content-security-policy") ||
              EqualIgnoringASCIICase(equiv,
                                     "content-security-policy-report-only")) {
@@ -116,29 +96,6 @@
   }
 }
 
-void HttpEquiv::ProcessHttpEquivAcceptCH(Document& document,
-                                         const AtomicString& content) {
-  LocalFrame* frame = document.GetFrame();
-  if (!frame)
-    return;
-
-  if (!document.GetFrame()->IsMainFrame()) {
-    return;
-  }
-
-  if (!AllowScriptFromSourceWithoutNotifying(
-          document.Url(), document.GetFrame()->GetContentSettingsClient(),
-          document.GetFrame()->GetSettings())) {
-    // Do not allow configuring client hints if JavaScript is disabled.
-    return;
-  }
-
-  UseCounter::Count(document, WebFeature::kClientHintsMetaAcceptCH);
-  FrameClientHintsPreferencesContext hints_context(frame);
-  frame->GetClientHintsPreferences().UpdateFromHttpEquivAcceptCH(
-      content, document.Url(), &hints_context);
-}
-
 void HttpEquiv::ProcessHttpEquivDefaultStyle(Document& document,
                                              const AtomicString& content) {
   document.GetStyleEngine().SetHttpDefaultStyle(content);
diff --git a/third_party/blink/renderer/core/loader/http_equiv.h b/third_party/blink/renderer/core/loader/http_equiv.h
index 869f5c0..38da4a1 100644
--- a/third_party/blink/renderer/core/loader/http_equiv.h
+++ b/third_party/blink/renderer/core/loader/http_equiv.h
@@ -47,7 +47,6 @@
       LocalDOMWindow*,
       const AtomicString& equiv,
       const AtomicString& content);
-  static void ProcessHttpEquivAcceptCH(Document&, const AtomicString& content);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/long_task_detector.h b/third_party/blink/renderer/core/loader/long_task_detector.h
index 666b9ca..54238a9 100644
--- a/third_party/blink/renderer/core/loader/long_task_detector.h
+++ b/third_party/blink/renderer/core/loader/long_task_detector.h
@@ -8,6 +8,7 @@
 #include "base/task/sequence_manager/task_time_observer.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
 
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
index 6662e685..c2675d66 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
 #include "third_party/blink/renderer/platform/geometry/int_size.h"
 #include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/network/http_parsers.h"
 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
diff --git a/third_party/blink/renderer/core/mojo/mojo_handle.h b/third_party/blink/renderer/core/mojo/mojo_handle.h
index 696fe14c..beab5b2c 100644
--- a/third_party/blink/renderer/core/mojo/mojo_handle.h
+++ b/third_party/blink/renderer/core/mojo/mojo_handle.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h
index d360c5d..ccb9a0e 100644
--- a/third_party/blink/renderer/core/page/chrome_client.h
+++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -517,8 +517,10 @@
     std::move(callback).Run(false);
   }
 
-  // The |callback| will be fired when the corresponding renderer frame for the
-  // |frame| is presented in the display compositor.
+  // The `callback` will be fired when the corresponding renderer frame for the
+  // `frame` is presented in the display compositor. If there is no update in
+  // the frame to be presented, the `callback` will run with the time of the
+  // failure.
   using ReportTimeCallback =
       WTF::CrossThreadOnceFunction<void(base::TimeTicks)>;
   virtual void NotifyPresentationTime(LocalFrame& frame,
diff --git a/third_party/blink/renderer/core/page/plugin_data.h b/third_party/blink/renderer/core/page/plugin_data.h
index 0d5439e..783a7cd2 100644
--- a/third_party/blink/renderer/core/page/plugin_data.h
+++ b/third_party/blink/renderer/core/page/plugin_data.h
@@ -23,6 +23,7 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc b/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
index fc03c53..fb4b9a8 100644
--- a/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
+++ b/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
@@ -7,7 +7,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
-#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
@@ -15,7 +14,6 @@
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/html/html_details_element.h"
 #include "third_party/blink/renderer/core/svg/svg_svg_element.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -32,6 +30,7 @@
 
   return url_fragment.Substring(0, directive_delimiter_ix);
 }
+
 }  // namespace
 
 ElementFragmentAnchor* ElementFragmentAnchor::TryCreate(const KURL& url,
@@ -89,8 +88,8 @@
 
 ElementFragmentAnchor::ElementFragmentAnchor(Node& anchor_node,
                                              LocalFrame& frame)
-    : anchor_node_(&anchor_node),
-      frame_(&frame),
+    : FragmentAnchor(frame),
+      anchor_node_(&anchor_node),
       needs_focus_(!anchor_node.IsDocumentNode()) {
   DCHECK(frame_->View());
 }
@@ -121,32 +120,10 @@
     element_to_scroll = doc.documentElement();
 
   if (element_to_scroll) {
-    // Expand <details> elements so we can make |element_to_scroll| visible.
-    bool needs_style_and_layout =
-        RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled() &&
-        HTMLDetailsElement::ExpandDetailsAncestors(*element_to_scroll);
-
-    // Reveal hidden=until-found ancestors so we can make |element_to_scroll|
-    // visible.
-    needs_style_and_layout |=
-        RuntimeEnabledFeatures::BeforeMatchEventEnabled(
-            element_to_scroll->GetExecutionContext()) &&
-        DisplayLockUtilities::RevealHiddenUntilFoundAncestors(
-            *element_to_scroll);
-
-    if (needs_style_and_layout) {
-      // If we opened any details elements, we need to update style and layout
-      // to account for the new content to render inside the now-expanded
-      // details element before we scroll to it. The added open attribute may
-      // also affect style.
-      doc.UpdateStyleAndLayoutForNode(element_to_scroll,
-                                      DocumentUpdateReason::kFindInPage);
-    }
-
     ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create();
     options->setBlock("start");
     options->setInlinePosition("nearest");
-    element_to_scroll->ScrollIntoViewNoVisualUpdate(options);
+    ScrollElementIntoViewWithOptions(element_to_scroll, options);
   }
 
   if (boundary_local_frame) {
diff --git a/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h b/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
index 4347b43..214bd8b 100644
--- a/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
+++ b/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h
@@ -61,8 +61,6 @@
 
   void Trace(Visitor*) const override;
 
-  bool IsTextFragmentAnchor() override { return false; }
-
  private:
   FRIEND_TEST_ALL_PREFIXES(ElementFragmentAnchorTest,
                            AnchorRemovedBeforeBeginFrameCrash);
@@ -70,7 +68,6 @@
   void ApplyFocusIfNeeded();
 
   WeakMember<Node> anchor_node_;
-  Member<LocalFrame> frame_;
   bool needs_focus_;
 
   // While this is true, the fragment is still "active" in the sense that we
diff --git a/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc b/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc
index e908ddf..fc28a80 100644
--- a/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc
+++ b/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc
@@ -5,10 +5,14 @@
 #include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
 
 #include "base/metrics/histogram_macros.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
+#include "third_party/blink/renderer/core/fragment_directive/css_selector_fragment_anchor.h"
 #include "third_party/blink/renderer/core/fragment_directive/text_fragment_anchor.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/web_feature.h"
+#include "third_party/blink/renderer/core/html/html_details_element.h"
 #include "third_party/blink/renderer/core/html/html_document.h"
 #include "third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -26,10 +30,17 @@
 
   // The text fragment anchor will be created if we successfully parsed the
   // text directive but we only do the text matching later on.
-  bool text_fragment_anchor_created = false;
+  bool selector_fragment_anchor_created = false;
   if (text_fragment_identifiers_enabled) {
     anchor = TextFragmentAnchor::TryCreate(url, frame, should_scroll);
-    text_fragment_anchor_created = anchor;
+    selector_fragment_anchor_created = anchor;
+  }
+
+  // TODO(crbug.com/1265726): Do highlighting related to all fragment
+  // directives and scroll the first one into view
+  if (!anchor && RuntimeEnabledFeatures::CSSSelectorFragmentAnchorEnabled()) {
+    anchor = CssSelectorFragmentAnchor::TryCreate(url, frame, should_scroll);
+    selector_fragment_anchor_created = anchor;
   }
 
   bool element_id_anchor_found = false;
@@ -38,11 +49,11 @@
     element_id_anchor_found = anchor;
   }
 
-  // Track how often we have a element fragment that we can't find. Only track
-  // if we didn't match a text fragment since we expect those would inflate the
-  // "failed" case.
+  // Track how often we have an element fragment that we can't find. Only track
+  // if we didn't match a selector fragment since we expect those would inflate
+  // the "failed" case.
   if (IsA<HTMLDocument>(frame.GetDocument()) && url.HasFragmentIdentifier() &&
-      !text_fragment_anchor_created) {
+      !selector_fragment_anchor_created) {
     UMA_HISTOGRAM_BOOLEAN("TextFragmentAnchor.ElementIdFragmentFound",
                           element_id_anchor_found);
   }
@@ -50,4 +61,35 @@
   return anchor;
 }
 
+void FragmentAnchor::ScrollElementIntoViewWithOptions(
+    Element* element_to_scroll,
+    ScrollIntoViewOptions* options) {
+  // Expand <details> elements so we can make |element_to_scroll| visible.
+  bool needs_style_and_layout =
+      RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled() &&
+      HTMLDetailsElement::ExpandDetailsAncestors(*element_to_scroll);
+
+  // Reveal hidden=until-found ancestors so we can make |element_to_scroll|
+  // visible.
+  needs_style_and_layout |=
+      RuntimeEnabledFeatures::BeforeMatchEventEnabled(
+          element_to_scroll->GetExecutionContext()) &&
+      DisplayLockUtilities::RevealHiddenUntilFoundAncestors(*element_to_scroll);
+
+  if (needs_style_and_layout) {
+    // If we opened any details elements, we need to update style and layout
+    // to account for the new content to render inside the now-expanded
+    // details element before we scroll to it. The added open attribute may
+    // also affect style.
+    frame_->GetDocument()->UpdateStyleAndLayoutForNode(
+        element_to_scroll, DocumentUpdateReason::kFindInPage);
+  }
+
+  element_to_scroll->ScrollIntoViewNoVisualUpdate(options);
+}
+
+void FragmentAnchor::Trace(Visitor* visitor) const {
+  visitor->Trace(frame_);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h b/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
index 6681171..49ef021 100644
--- a/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
+++ b/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
@@ -10,9 +10,10 @@
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
-
-class LocalFrame;
+class Element;
 class KURL;
+class LocalFrame;
+class ScrollIntoViewOptions;
 
 // This class is an interface for the concept of a "fragment anchor". A
 // fragment anchor allows a page to link to a specific part of a page by using
@@ -34,6 +35,7 @@
                                    LocalFrame& frame,
                                    bool should_scroll);
 
+  explicit FragmentAnchor(LocalFrame& frame) : frame_(frame) {}
   FragmentAnchor() = default;
   virtual ~FragmentAnchor() = default;
 
@@ -56,9 +58,14 @@
   // dismissed and can be disposed.
   virtual bool Dismiss() = 0;
 
-  virtual void Trace(Visitor*) const {}
+  virtual void Trace(Visitor*) const;
 
-  virtual bool IsTextFragmentAnchor() = 0;
+  virtual bool IsTextFragmentAnchor() { return false; }
+
+  virtual void ScrollElementIntoViewWithOptions(Element* element_to_scroll,
+                                                ScrollIntoViewOptions* options);
+
+  Member<LocalFrame> frame_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.h b/third_party/blink/renderer/core/page/touch_adjustment.h
index 5802b474..3eb0bb1 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.h
+++ b/third_party/blink/renderer/core/page/touch_adjustment.h
@@ -24,6 +24,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
 #include "third_party/blink/renderer/platform/geometry/layout_size.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "ui/gfx/geometry/point.h"
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.h b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.h
index 8134157..2997294f 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.h
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.h
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
 #include "third_party/blink/renderer/platform/geometry/layout_point.h"
 #include "third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index f914f20d..2f6a219 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -1789,8 +1789,7 @@
 
   // A main frame is needed to call UpdateLayers which updates property trees,
   // re-calculating cached to/from-screen transforms.
-  EXPECT_TRUE(
-      Compositor().LayerTreeHost()->RequestedMainFramePendingForTesting());
+  EXPECT_TRUE(Compositor().LayerTreeHost()->RequestedMainFramePending());
 
   // A full commit is not needed.
   EXPECT_FALSE(Compositor().LayerTreeHost()->CommitRequested());
diff --git a/third_party/blink/renderer/core/paint/highlight_painting_utils.cc b/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
index 3f77979d..217220fa 100644
--- a/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
+++ b/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/core/paint/highlight_painting_utils.h"
 
-#include "components/shared_highlighting/core/common/text_fragments_constants.h"
+#include "components/shared_highlighting/core/common/fragment_directives_constants.h"
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/css/style_request.h"
 #include "third_party/blink/renderer/core/dom/element.h"
diff --git a/third_party/blink/renderer/core/paint/paint_layer_fragment.h b/third_party/blink/renderer/core/paint/paint_layer_fragment.h
index d27a27e..fcec7bdd 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_fragment.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_fragment.h
@@ -27,6 +27,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_FRAGMENT_H_
 
 #include "third_party/blink/renderer/core/paint/clip_rect.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index 0fe910a..7ba0b4a3 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -51,6 +51,7 @@
 #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 
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 d9f5212..2bc0f53d 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
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
 #include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
diff --git a/third_party/blink/renderer/core/resize_observer/resize_observer.h b/third_party/blink/renderer/core/resize_observer/resize_observer.h
index cc3ba76..d0cb181 100644
--- a/third_party/blink/renderer/core/resize_observer/resize_observer.h
+++ b/third_party/blink/renderer/core/resize_observer/resize_observer.h
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h b/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h
index 11afbf6..2b70c7e 100644
--- a/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h
+++ b/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/resize_observer/resize_observer_size.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h b/third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h
index c654121d..5687376 100644
--- a/third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h
+++ b/third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h
@@ -6,6 +6,7 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
index 97eab0f..72276615 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
+++ b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
@@ -27,6 +27,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_ANIMATION_SANDWICH_H_
 
 #include "third_party/blink/renderer/core/svg/animation/smil_time.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
diff --git a/third_party/blink/renderer/core/svg/properties/svg_list_property.h b/third_party/blink/renderer/core/svg/properties/svg_list_property.h
index 31d78f6..9c5eca5 100644
--- a/third_party/blink/renderer/core/svg/properties/svg_list_property.h
+++ b/third_party/blink/renderer/core/svg/properties/svg_list_property.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_PROPERTIES_SVG_LIST_PROPERTY_H_
 
 #include "third_party/blink/renderer/core/svg/properties/svg_listable_property.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h b/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h
index 944fede..49182d8 100644
--- a/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h
+++ b/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h
@@ -8,6 +8,7 @@
 #include <signal.h>
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h b/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h
index 392c328..82e068ba 100644
--- a/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h
+++ b/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h
@@ -32,6 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_HIT_TEST_LAYER_RECT_LIST_H_
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
index 843b7f4..2cb5611 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_compositor.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -57,7 +57,7 @@
   // Returns true if a main frame has been requested from blink, until the
   // BeginFrame() step occurs.
   bool NeedsBeginFrame() const {
-    return LayerTreeHost()->RequestedMainFramePendingForTesting();
+    return LayerTreeHost()->RequestedMainFramePending();
   }
   // Returns true if commits are deferred in the compositor. Since these tests
   // use synchronous compositing through BeginFrame(), the deferred state has no
diff --git a/third_party/blink/renderer/core/testing/union_types_test.h b/third_party/blink/renderer/core/testing/union_types_test.h
index dcd53f5..d510bb9 100644
--- a/third_party/blink/renderer/core/testing/union_types_test.h
+++ b/third_party/blink/renderer/core/testing/union_types_test.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_UNION_TYPES_TEST_H_
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/timing/layout_shift.h b/third_party/blink/renderer/core/timing/layout_shift.h
index fcf9987..912b018 100644
--- a/third_party/blink/renderer/core/timing/layout_shift.h
+++ b/third_party/blink/renderer/core/timing/layout_shift.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
 #include "third_party/blink/renderer/core/timing/layout_shift_attribution.h"
 #include "third_party/blink/renderer/core/timing/performance_entry.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/timing/performance_long_task_timing.h b/third_party/blink/renderer/core/timing/performance_long_task_timing.h
index fb00065..3bdb3fed 100644
--- a/third_party/blink/renderer/core/timing/performance_long_task_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_long_task_timing.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_LONG_TASK_TIMING_H_
 
 #include "third_party/blink/renderer/core/timing/performance_entry.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/timing/performance_observer.h b/third_party/blink/renderer/core/timing/performance_observer.h
index b2b86e4..c79da407 100644
--- a/third_party/blink/renderer/core/timing/performance_observer.h
+++ b/third_party/blink/renderer/core/timing/performance_observer.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
 #include "third_party/blink/renderer/core/timing/performance_entry.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
diff --git a/third_party/blink/renderer/core/timing/performance_observer_entry_list.h b/third_party/blink/renderer/core/timing/performance_observer_entry_list.h
index 864e220..e4461f0 100644
--- a/third_party/blink/renderer/core/timing/performance_observer_entry_list.h
+++ b/third_party/blink/renderer/core/timing/performance_observer_entry_list.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_OBSERVER_ENTRY_LIST_H_
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
index 5677fe37..eafa22fd 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_trusted_type_policy_options.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "v8/include/v8.h"
 
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc b/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc
index 692b9074..9e1eeb20 100644
--- a/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc
+++ b/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
 
 #include "base/numerics/checked_math.h"
+#include "base/numerics/ostream_operators.h"
 #include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
 #include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
 
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
index af9b7c00..9f2714ed 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/loader/threaded_icon_loader.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h b/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h
index 62b2748b..84a6c350 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h
+++ b/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
 
diff --git a/third_party/blink/renderer/modules/compression/inflate_transformer.h b/third_party/blink/renderer/modules/compression/inflate_transformer.h
index d450f85..f83b7702 100644
--- a/third_party/blink/renderer/modules/compression/inflate_transformer.h
+++ b/third_party/blink/renderer/modules/compression/inflate_transformer.h
@@ -8,6 +8,7 @@
 #include "base/types/strong_alias.h"
 #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 #include "third_party/zlib/zlib.h"
 
diff --git a/third_party/blink/renderer/modules/filesystem/directory_reader_sync.h b/third_party/blink/renderer/modules/filesystem/directory_reader_sync.h
index dc42fa62..f2d4dd02 100644
--- a/third_party/blink/renderer/modules/filesystem/directory_reader_sync.h
+++ b/third_party/blink/renderer/modules/filesystem/directory_reader_sync.h
@@ -33,6 +33,7 @@
 
 #include "third_party/blink/renderer/core/fileapi/file_error.h"
 #include "third_party/blink/renderer/modules/filesystem/directory_reader_base.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
diff --git a/third_party/blink/renderer/modules/filesystem/entry_heap_vector.h b/third_party/blink/renderer/modules/filesystem/entry_heap_vector.h
index 43a2d66..bf0df05 100644
--- a/third_party/blink/renderer/modules/filesystem/entry_heap_vector.h
+++ b/third_party/blink/renderer/modules/filesystem/entry_heap_vector.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_ENTRY_HEAP_VECTOR_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_ENTRY_HEAP_VECTOR_H_
 
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
index 94312f7..40f935a4 100644
--- a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
+++ b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
@@ -9,6 +9,7 @@
 #include "device/gamepad/public/mojom/gamepad.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h b/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
index f8337e2..6942a18 100644
--- a/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
+++ b/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.h b/third_party/blink/renderer/modules/manifest/manifest_parser.h
index 97b4c86..ddad029 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.h
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.h
@@ -436,7 +436,7 @@
       const JSONObject* object);
 
   // Parses the 'translations' field of the manifest as defined in:
-  // https://github.com/w3c/manifest/issues/676#issuecomment-810628993
+  // https://github.com/WICG/manifest-incubations/blob/gh-pages/translations-explainer.md
   // Returns empty map if parsing fails.
   HashMap<String, mojom::blink::ManifestTranslationItemPtr> ParseTranslations(
       const JSONObject* object);
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.h b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.h
index da2eef19..a56f8cd 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.h
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.h
@@ -8,6 +8,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
index 402ac9cc..4b775fa5 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h"
 #include "third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/thread_state.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/modules/mediasession/media_metadata.h b/third_party/blink/renderer/modules/mediasession/media_metadata.h
index 925d6bc..3417597 100644
--- a/third_party/blink/renderer/modules/mediasession/media_metadata.h
+++ b/third_party/blink/renderer/modules/mediasession/media_metadata.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_media_image.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_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/modules/mediasource/track_default_list.h b/third_party/blink/renderer/modules/mediasource/track_default_list.h
index e558f6d..c14c3124 100644
--- a/third_party/blink/renderer/modules/mediasource/track_default_list.h
+++ b/third_party/blink/renderer/modules/mediasource/track_default_list.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/modules/mediasource/track_default.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.h b/third_party/blink/renderer/modules/mediastream/user_media_processor.h
index d6b6eda..d6f5b17 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_processor.h
+++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.h
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h"
 #include "third_party/blink/renderer/modules/mediastream/user_media_request.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 5150b21..81481a9 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -52,6 +52,7 @@
 #include "third_party/blink/renderer/modules/mediastream/media_stream.h"
 #include "third_party/blink/renderer/modules/mediastream/overconstrained_error.h"
 #include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
+#include "third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
@@ -566,6 +567,9 @@
 
   RecordIdentifiabilityMetric(surface_, GetExecutionContext(),
                               IdentifiabilityBenignStringToken(g_empty_string));
+  if (auto* window = GetWindow()) {
+    PeerConnectionTracker::From(*window).TrackGetUserMediaSuccess(this, stream);
+  }
   // After this call, the execution context may be invalid.
   callbacks_->OnSuccess(stream);
   is_resolved_ = true;
diff --git a/third_party/blink/renderer/modules/nfc/ndef_record.h b/third_party/blink/renderer/modules/nfc/ndef_record.h
index e309c4d2..ebbe5b3 100644
--- a/third_party/blink/renderer/modules/nfc/ndef_record.h
+++ b/third_party/blink/renderer/modules/nfc/ndef_record.h
@@ -11,6 +11,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.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_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
index 45f24af6..5fd2004 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -1253,6 +1253,29 @@
       SerializeMediaConstraints(user_media_request->VideoConstraints()));
 }
 
+void PeerConnectionTracker::TrackGetUserMediaSuccess(
+    UserMediaRequest* user_media_request,
+    MediaStream* stream) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_);
+
+  // Serialize audio and video track information (id and label) or an
+  // empty string when there is no such track.
+  String audio_track_info =
+      stream->getAudioTracks().IsEmpty()
+          ? String("")
+          : String("id:") + stream->getAudioTracks()[0]->id() +
+                String(" label:") + stream->getAudioTracks()[0]->label();
+  String video_track_info =
+      stream->getVideoTracks().IsEmpty()
+          ? String("")
+          : String("id:") + stream->getVideoTracks()[0]->id() +
+                String(" label:") + stream->getVideoTracks()[0]->label();
+
+  peer_connection_tracker_host_->GetUserMediaSuccess(
+      user_media_request->request_id(), stream->id(), audio_track_info,
+      video_track_info);
+}
+
 void PeerConnectionTracker::TrackRtcEventLogWrite(
     RTCPeerConnectionHandler* pc_handler,
     const WTF::Vector<uint8_t>& output) {
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
index 580f5209..cfdf1002 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
@@ -12,6 +12,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/peerconnection/peer_connection_tracker.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h"
@@ -243,6 +244,9 @@
 
   // Sends an update when getUserMedia is called.
   virtual void TrackGetUserMedia(UserMediaRequest* user_media_request);
+  // Sends an update when getUserMedia resolveѕ with a stream.
+  virtual void TrackGetUserMediaSuccess(UserMediaRequest* user_media_request,
+                                        MediaStream* stream);
 
   // Sends a new fragment on an RtcEventLog.
   virtual void TrackRtcEventLogWrite(RTCPeerConnectionHandler* pc_handler,
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
index 54e0e6dc..9ca8800 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
@@ -67,6 +67,8 @@
   MOCK_METHOD6(
       GetUserMedia,
       void(const String&, int, bool, bool, const String&, const String&));
+  MOCK_METHOD4(GetUserMediaSuccess,
+               void(int, const String&, const String&, const String&));
   MOCK_METHOD2(WebRtcEventLogWrite, void(int, const Vector<uint8_t>&));
   MOCK_METHOD2(AddStandardStats, void(int, base::Value));
   MOCK_METHOD2(AddLegacyStats, void(int, base::Value));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h b/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h
index d6a906ff..9f1e147 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/core/dom/dom_time_stamp.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_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_stats_response.h b/third_party/blink/renderer/modules/peerconnection/rtc_stats_response.h
index c701da7..6ee2e98 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_stats_response.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_stats_response.h
@@ -27,6 +27,7 @@
 
 #include "third_party/blink/renderer/modules/peerconnection/rtc_legacy_stats_report.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_stats_response_base.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
diff --git a/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h b/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h
index 7657e4e..601aeec 100644
--- a/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h
+++ b/third_party/blink/renderer/modules/plugins/dom_mime_type_array.h
@@ -25,6 +25,7 @@
 #include "third_party/blink/renderer/core/page/plugins_changed_observer.h"
 #include "third_party/blink/renderer/modules/plugins/dom_mime_type.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
diff --git a/third_party/blink/renderer/modules/plugins/dom_plugin_array.h b/third_party/blink/renderer/modules/plugins/dom_plugin_array.h
index dbfac2d6..36657de 100644
--- a/third_party/blink/renderer/modules/plugins/dom_plugin_array.h
+++ b/third_party/blink/renderer/modules/plugins/dom_plugin_array.h
@@ -25,6 +25,7 @@
 #include "third_party/blink/renderer/core/page/plugins_changed_observer.h"
 #include "third_party/blink/renderer/modules/plugins/dom_plugin.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/modules/speech/speech_grammar_list.h b/third_party/blink/renderer/modules/speech/speech_grammar_list.h
index 120e18b..b580523 100644
--- a/third_party/blink/renderer/modules/speech/speech_grammar_list.h
+++ b/third_party/blink/renderer/modules/speech/speech_grammar_list.h
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/modules/speech/speech_grammar.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/speech/speech_recognition_result.h b/third_party/blink/renderer/modules/speech/speech_recognition_result.h
index 9cf099f0..a129767 100644
--- a/third_party/blink/renderer/modules/speech/speech_recognition_result.h
+++ b/third_party/blink/renderer/modules/speech/speech_recognition_result.h
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/modules/speech/speech_recognition_alternative.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/speech/speech_recognition_result_list.h b/third_party/blink/renderer/modules/speech/speech_recognition_result_list.h
index 5a1f243..665faee 100644
--- a/third_party/blink/renderer/modules/speech/speech_recognition_result_list.h
+++ b/third_party/blink/renderer/modules/speech/speech_recognition_result_list.h
@@ -28,6 +28,7 @@
 
 #include "third_party/blink/renderer/modules/speech/speech_recognition_result.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h b/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h
index d66cf107..013a63d5 100644
--- a/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h
+++ b/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.h b/third_party/blink/renderer/modules/webaudio/audio_buffer.h
index 43ef43a..09e2f49f 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_buffer.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.h
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.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_vector.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h
index 6124e98..ea08d51 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/platform/audio/audio_array.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "v8/include/v8.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h
index 925e4cff..47f1418 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_param_descriptor.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "v8/include/v8.h"
diff --git a/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h b/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
index ab3b8b5..a2673fe 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/modules/webgl/webgl_shared_object.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace gpu {
 namespace gles2 {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h b/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h
index a6b5697..1c554ae 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/modules/webgl/webgl_context_object.h"
 #include "third_party/blink/renderer/modules/webgl/webgl_program.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h b/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h
index b7908791..35cd529 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/modules/webgl/webgl_buffer.h"
 #include "third_party/blink/renderer/modules/webgl/webgl_context_object.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compilation_info.h b/third_party/blink/renderer/modules/webgpu/gpu_compilation_info.h
index 5ae8d07..82c09eb 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_compilation_info.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_compilation_info.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_COMPILATION_INFO_H_
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc b/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc
index 0442008..538ca601 100644
--- a/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc
+++ b/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/renderer/modules/webusb/usb_endpoint.h"
 #include "third_party/blink/renderer/modules/webusb/usb_interface.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/webusb/usb_alternate_interface.h b/third_party/blink/renderer/modules/webusb/usb_alternate_interface.h
index 25a3b5d..e6fa976b 100644
--- a/third_party/blink/renderer/modules/webusb/usb_alternate_interface.h
+++ b/third_party/blink/renderer/modules/webusb/usb_alternate_interface.h
@@ -7,6 +7,7 @@
 
 #include "services/device/public/mojom/usb_device.mojom-blink.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/webusb/usb_configuration.h b/third_party/blink/renderer/modules/webusb/usb_configuration.h
index 233c34fb..f066e11 100644
--- a/third_party/blink/renderer/modules/webusb/usb_configuration.h
+++ b/third_party/blink/renderer/modules/webusb/usb_configuration.h
@@ -7,6 +7,7 @@
 
 #include "services/device/public/mojom/usb_device.mojom-blink.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/webusb/usb_interface.h b/third_party/blink/renderer/modules/webusb/usb_interface.h
index a726f20..f91e2f3 100644
--- a/third_party/blink/renderer/modules/webusb/usb_interface.h
+++ b/third_party/blink/renderer/modules/webusb/usb_interface.h
@@ -7,6 +7,7 @@
 
 #include "services/device/public/mojom/usb_device.mojom-blink.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
index 09219d5..d2188e1 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
+++ b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/modules/xr/xr_frame.h"
 #include "third_party/blink/renderer/modules/xr/xr_session.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
index aaaf78d..12b4b07 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
+++ b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/xr/xr_hit_test_source.h b/third_party/blink/renderer/modules/xr/xr_hit_test_source.h
index 56bf221..3f5e573 100644
--- a/third_party/blink/renderer/modules/xr/xr_hit_test_source.h
+++ b/third_party/blink/renderer/modules/xr/xr_hit_test_source.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_HIT_TEST_SOURCE_H_
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 #include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
 
diff --git a/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_result.h b/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_result.h
index df60444a..56d6ce6 100644
--- a/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_result.h
+++ b/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_result.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_TRANSIENT_INPUT_HIT_TEST_RESULT_H_
 
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 #include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
 
diff --git a/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_source.h b/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_source.h
index 6a797e30..e422d6b 100644
--- a/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_source.h
+++ b/third_party/blink/renderer/modules/xr/xr_transient_input_hit_test_source.h
@@ -8,6 +8,7 @@
 #include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/xr/xr_viewer_pose.h b/third_party/blink/renderer/modules/xr/xr_viewer_pose.h
index 7cc207d5..09a7e012 100644
--- a/third_party/blink/renderer/modules/xr/xr_viewer_pose.h
+++ b/third_party/blink/renderer/modules/xr/xr_viewer_pose.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_VIEWER_POSE_H_
 
 #include "third_party/blink/renderer/modules/xr/xr_pose.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
 
diff --git a/third_party/blink/renderer/platform/DEPS b/third_party/blink/renderer/platform/DEPS
index e5c6de8..f4f8c49 100644
--- a/third_party/blink/renderer/platform/DEPS
+++ b/third_party/blink/renderer/platform/DEPS
@@ -46,6 +46,7 @@
     "+base/synchronization/waitable_event.h",
     "+base/android/sys_utils.h",
     "+base/system/sys_info.h",
+    "+base/task/delayed_task_handle.h",
     "+base/task/sequence_manager/task_time_observer.h",
     "+base/test",
     "+base/test/fuzzed_data_provider.h",
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
index 0230137..2b3e25c 100644
--- a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
+++ b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -28,6 +28,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/metrics/histogram_macros.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
@@ -384,4 +385,28 @@
   return canvas_resource_tracker_;
 }
 
+void* CreateHistogram(const char* name, int min, int max, size_t buckets) {
+  // Each histogram has an implicit '0' bucket (for underflow), so we can always
+  // bump the minimum to 1.
+  DCHECK_LE(0, min);
+  min = std::max(1, min);
+
+  // For boolean histograms, always include an overflow bucket [2, infinity).
+  if (max == 1 && buckets == 2) {
+    max = 2;
+    buckets = 3;
+  }
+
+  const std::string histogram_name =
+      Platform::Current()->GetNameForHistogram(name);
+  return base::Histogram::FactoryGet(
+      histogram_name, min, max, static_cast<uint32_t>(buckets),
+      base::Histogram::kUmaTargetedHistogramFlag);
+}
+
+void AddHistogramSample(void* hist, int sample) {
+  base::Histogram* histogram = static_cast<base::Histogram*>(hist);
+  histogram->Add(sample);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
index 024b4e3..1851bf42c 100644
--- a/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
+++ b/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
@@ -284,6 +284,17 @@
   size_t gc_callback_depth_ = 0;
 };
 
+// Creates a histogram for V8. The returned value is a base::Histogram, but
+// typed to void* for v8.
+PLATFORM_EXPORT void* CreateHistogram(const char* name,
+                                      int min,
+                                      int max,
+                                      size_t buckets);
+
+// Adds an entry to the supplied histogram. `hist` was previously returned from
+// CreateHistogram().
+PLATFORM_EXPORT void AddHistogramSample(void* hist, int sample);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_PER_ISOLATE_DATA_H_
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 4dfc7c4..a562f5ad 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -383,6 +383,10 @@
   RuntimeEnabledFeatures::SetTextFragmentIdentifiersEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableCSSSelectorFragmentAnchor(bool enable) {
+  RuntimeEnabledFeatures::SetCSSSelectorFragmentAnchorEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnablePreciseMemoryInfo(bool enable) {
   RuntimeEnabledFeatures::SetPreciseMemoryInfoEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h b/third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h
index 7c3ef5d1..18217ba 100644
--- a/third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h
+++ b/third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h
@@ -5,6 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_LINKED_HASH_SET_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_LINKED_HASH_SET_H_
 
+// Needs heap_vector.h for VectorTraits of Member and WeakMember.
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/forward.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator_impl.h"
diff --git a/third_party/blink/renderer/platform/heap/handle.h b/third_party/blink/renderer/platform/heap/handle.h
index d48e5b4b..6b3524c9 100644
--- a/third_party/blink/renderer/platform/heap/handle.h
+++ b/third_party/blink/renderer/platform/heap/handle.h
@@ -34,7 +34,6 @@
 // TODO(chromium:1269227): Clean up the following catch-all includes and require
 // IWYU for users of platform/heap.
 
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/heap/thread_state.h"
diff --git a/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc b/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
index 40b36f9..4dcbfb3 100644
--- a/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
@@ -40,7 +40,7 @@
   }
 }
 
-void ClientHintsPreferences::UpdateFromHttpEquivAcceptCH(
+void ClientHintsPreferences::UpdateFromMetaTagAcceptCH(
     const String& header_value,
     const KURL& url,
     Context* context) {
@@ -62,7 +62,7 @@
   if (!parsed_ch.has_value())
     return;
 
-  // The renderer only handles http-equiv, so this merges.
+  // The renderer only handles meta tags, so this merges.
   for (network::mojom::WebClientHintsType newly_enabled : parsed_ch.value())
     enabled_hints_.SetIsEnabled(newly_enabled, true);
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h b/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
index 66215c9..c45d1c9 100644
--- a/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
+++ b/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
@@ -33,13 +33,13 @@
   void UpdateFrom(const ClientHintsPreferences&);
   void CombineWith(const ClientHintsPreferences&);
 
-  // Parses <meta http-equiv="accept-ch"> value |header_value|, and updates
-  // |this| to enable the requested client hints. |url| is the URL of the page.
-  // |context| may be null. If client hints are not allowed for |url|, then
-  // |this| would not be updated.
-  void UpdateFromHttpEquivAcceptCH(const String& header_value,
-                                   const KURL& url,
-                                   Context* context);
+  // Parses <meta http-equiv="accept-ch"> or <meta name="accept-ch"> value
+  // `header_value`, and updates `this` to enable the requested client hints.
+  // `url` is the URL of the page. `context` may be null. If client hints are
+  // not allowed for `url`, then `this` would not be updated.
+  void UpdateFromMetaTagAcceptCH(const String& header_value,
+                                 const KURL& url,
+                                 Context* context);
 
   bool ShouldSend(network::mojom::WebClientHintsType type) const;
   void SetShouldSend(network::mojom::WebClientHintsType type);
diff --git a/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc b/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
index 5a604b5..0b5b21d 100644
--- a/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
@@ -85,8 +85,8 @@
     SCOPED_TRACE(testing::Message() << test_case.header_value);
     ClientHintsPreferences preferences;
     const KURL kurl(String::FromUTF8("https://www.google.com/"));
-    preferences.UpdateFromHttpEquivAcceptCH(test_case.header_value, kurl,
-                                            nullptr);
+    preferences.UpdateFromMetaTagAcceptCH(test_case.header_value, kurl,
+                                          nullptr);
     EXPECT_EQ(
         test_case.expectation_resource_width_DEPRECATED,
         preferences.ShouldSend(
@@ -130,9 +130,9 @@
               preferences.ShouldSend(
                   network::mojom::WebClientHintsType::kPrefersColorScheme));
 
-    // Calling UpdateFromHttpEquivAcceptCH with an invalid header should
+    // Calling UpdateFromMetaTagAcceptCH with an invalid header should
     // have no impact on client hint preferences.
-    preferences.UpdateFromHttpEquivAcceptCH("1, 42,", kurl, nullptr);
+    preferences.UpdateFromMetaTagAcceptCH("1, 42,", kurl, nullptr);
     EXPECT_EQ(
         test_case.expectation_resource_width_DEPRECATED,
         preferences.ShouldSend(
@@ -153,10 +153,10 @@
               preferences.ShouldSend(
                   network::mojom::WebClientHintsType::kViewportWidth));
 
-    // Calling UpdateFromHttpEquivAcceptCH with empty header is also a
-    // no-op, since ClientHintsPreferences only deals with http-equiv, and
+    // Calling UpdateFromMetaTagAcceptCH with empty header is also a
+    // no-op, since ClientHintsPreferences only deals with meta tags, and
     // hence merge.
-    preferences.UpdateFromHttpEquivAcceptCH("", kurl, nullptr);
+    preferences.UpdateFromMetaTagAcceptCH("", kurl, nullptr);
     EXPECT_EQ(
         test_case.expectation_resource_width_DEPRECATED,
         preferences.ShouldSend(
@@ -184,7 +184,7 @@
 TEST_F(ClientHintsPreferencesTest, SecureEnabledTypesMerge) {
   ClientHintsPreferences preferences;
   const KURL kurl(String::FromUTF8("https://www.google.com/"));
-  preferences.UpdateFromHttpEquivAcceptCH("rtt, downlink", kurl, nullptr);
+  preferences.UpdateFromMetaTagAcceptCH("rtt, downlink", kurl, nullptr);
 
   EXPECT_FALSE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kResourceWidth_DEPRECATED));
@@ -214,9 +214,9 @@
   EXPECT_FALSE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kPrefersColorScheme));
 
-  // Calling UpdateFromHttpEquivAcceptCH with an invalid header should
+  // Calling UpdateFromMetaTagAcceptCH with an invalid header should
   // have no impact on client hint preferences.
-  preferences.UpdateFromHttpEquivAcceptCH("1,,42", kurl, nullptr);
+  preferences.UpdateFromMetaTagAcceptCH("1,,42", kurl, nullptr);
   EXPECT_FALSE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kResourceWidth_DEPRECATED));
   EXPECT_FALSE(preferences.ShouldSend(
@@ -237,9 +237,9 @@
   EXPECT_FALSE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kPrefersColorScheme));
 
-  // Calling UpdateFromHttpEquivAcceptCH with "width" header should
+  // Calling UpdateFromMetaTagAcceptCH with "width" header should
   // replace add width to preferences
-  preferences.UpdateFromHttpEquivAcceptCH("width,sec-ch-width", kurl, nullptr);
+  preferences.UpdateFromMetaTagAcceptCH("width,sec-ch-width", kurl, nullptr);
   EXPECT_TRUE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kResourceWidth_DEPRECATED));
   EXPECT_TRUE(preferences.ShouldSend(
@@ -260,9 +260,9 @@
   EXPECT_FALSE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kPrefersColorScheme));
 
-  // Calling UpdateFromHttpEquivAcceptCH with empty header should not
+  // Calling UpdateFromMetaTagAcceptCH with empty header should not
   // change anything.
-  preferences.UpdateFromHttpEquivAcceptCH("", kurl, nullptr);
+  preferences.UpdateFromMetaTagAcceptCH("", kurl, nullptr);
   EXPECT_TRUE(preferences.ShouldSend(
       network::mojom::WebClientHintsType::kResourceWidth_DEPRECATED));
   EXPECT_TRUE(preferences.ShouldSend(
@@ -290,8 +290,8 @@
     const KURL kurl = use_secure_url
                           ? KURL(String::FromUTF8("https://www.google.com/"))
                           : KURL(String::FromUTF8("http://www.google.com/"));
-    preferences.UpdateFromHttpEquivAcceptCH("dpr", kurl, nullptr);
-    preferences.UpdateFromHttpEquivAcceptCH("sec-ch-dpr", kurl, nullptr);
+    preferences.UpdateFromMetaTagAcceptCH("dpr", kurl, nullptr);
+    preferences.UpdateFromMetaTagAcceptCH("sec-ch-dpr", kurl, nullptr);
     EXPECT_EQ(use_secure_url,
               preferences.ShouldSend(
                   network::mojom::WebClientHintsType::kDpr_DEPRECATED));
@@ -386,8 +386,8 @@
         network::mojom::WebClientHintsType::kPrefersColorScheme));
 
     const KURL kurl(String::FromUTF8("https://www.google.com/"));
-    preferences.UpdateFromHttpEquivAcceptCH(test.accept_ch_header_value, kurl,
-                                            nullptr);
+    preferences.UpdateFromMetaTagAcceptCH(test.accept_ch_header_value, kurl,
+                                          nullptr);
 
     enabled_types = preferences.GetEnabledClientHints();
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache.h b/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
index d741e55..ee12ec9 100644
--- a/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
+++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
@@ -27,6 +27,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_MEMORY_CACHE_H_
 
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/forward.h"
 #include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/memory_cache_dump_provider.h"
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc
index 18d12ca..4ded5ed3 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -37,6 +37,7 @@
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/instrumentation/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h b/third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h
index 9b8df460..a7dabc2 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h
@@ -25,6 +25,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_CLIENT_WALKER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_CLIENT_WALKER_H_
 
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
index 824866fc..b0d96076 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -10,6 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/loading_behavior_observer.h"
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_source.h b/third_party/blink/renderer/platform/mediastream/media_stream_source.h
index a886643..ec6ab34 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_source.h
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_source.h
@@ -41,6 +41,7 @@
 #include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h"
 #include "third_party/blink/renderer/platform/audio/audio_destination_consumer.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/prefinalizer.h"
 #include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_track_platform.h"
diff --git a/third_party/blink/renderer/platform/mhtml/mhtml_parser.h b/third_party/blink/renderer/platform/mhtml/mhtml_parser.h
index 191f5f9f..b1bbb2f 100644
--- a/third_party/blink/renderer/platform/mhtml/mhtml_parser.h
+++ b/third_party/blink/renderer/platform/mhtml/mhtml_parser.h
@@ -32,13 +32,11 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MHTML_MHTML_PARSER_H_
 
 #include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/mhtml/shared_buffer_chunk_reader.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
 namespace WTF {
 class String;
 }
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
index ea867cb..5b29fbc 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
@@ -170,6 +170,16 @@
       supported_formats.profiles.push_back(profile.profile);
       supported_formats.scalability_modes.push_back(profile.scalability_modes);
       supported_formats.sdp_formats.push_back(std::move(*format));
+
+#if defined(OS_WIN)
+      if (profile.profile == media::VideoCodecProfile::H264PROFILE_BASELINE) {
+        supported_formats.profiles.push_back(profile.profile);
+        supported_formats.scalability_modes.push_back(
+            profile.scalability_modes);
+        cricket::AddH264ConstrainedBaselineProfileToSupportedFormats(
+            &supported_formats.sdp_formats);
+      }
+#endif
     }
   }
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index a370bf0b..26dab9d 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -383,6 +383,14 @@
       status: "experimental",
     },
     {
+      name: "ClientHintsMetaHTTPEquivAcceptCH",
+      status: "stable",
+    },
+    {
+      name: "ClientHintsMetaNameAcceptCH",
+      status: "experimental",
+    },
+    {
       name: "ClipboardCustomFormats",
       status: "experimental",
     },
@@ -756,6 +764,10 @@
       status: "experimental",
     },
     {
+      name: "CSSSelectorFragmentAnchor",
+      status: "experimental",
+    },
+    {
       name: "CSSSnapSize",
       status: "experimental",
     },
@@ -2411,8 +2423,6 @@
     },
     {
       name: "WebAppLinkCapturing",
-      origin_trial_feature_name: "WebAppLinkCapturing",
-      origin_trial_os: ["chromeos"],
     },
     {
       // This flag enables the Manifest parser to handle id field.
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 91f1a369..9d61067 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -116,20 +116,15 @@
   event->set_chrome_renderer_scheduler_state()->set_rail_mode(proto_mode);
 }
 
-const char* BackgroundStateToString(bool is_backgrounded) {
-  if (is_backgrounded) {
-    return "renderer_backgrounded";
-  } else {
-    return "renderer_foregrounded";
-  }
+void AddBackgroundedToProto(perfetto::protos::pbzero::TrackEvent* event,
+                            bool is_backgrounded) {
+  event->set_chrome_renderer_scheduler_state()->set_is_backgrounded(
+      is_backgrounded);
 }
 
-const char* HiddenStateToString(bool is_hidden) {
-  if (is_hidden) {
-    return "hidden";
-  } else {
-    return "visible";
-  }
+void AddHiddenToProto(perfetto::protos::pbzero::TrackEvent* event,
+                      bool is_hidden) {
+  event->set_chrome_renderer_scheduler_state()->set_is_hidden(is_hidden);
 }
 
 const char* AudioPlayingStateToString(bool is_audio_playing) {
@@ -305,7 +300,7 @@
   }
 
   internal::ProcessState::Get()->is_process_backgrounded =
-      main_thread_only().renderer_backgrounded;
+      main_thread_only().renderer_backgrounded.get();
 
   if (initial_virtual_time) {
     main_thread_only().initial_virtual_time = *initial_virtual_time;
@@ -384,11 +379,11 @@
       renderer_hidden(false,
                       "RendererVisibility",
                       &main_thread_scheduler_impl->tracing_controller_,
-                      HiddenStateToString),
+                      &AddHiddenToProto),
       renderer_backgrounded(kLaunchingProcessIsBackgrounded,
                             "RendererPriority",
                             &main_thread_scheduler_impl->tracing_controller_,
-                            BackgroundStateToString),
+                            &AddBackgroundedToProto),
       blocking_input_expected_soon(
           false,
           "Scheduler.BlockingInputExpectedSoon",
@@ -440,7 +435,7 @@
           main_thread_scheduler_impl,
           main_thread_scheduler_impl->helper_.HasCPUTimingForEachTask(),
           now,
-          renderer_backgrounded),
+          renderer_backgrounded.get()),
       process_type(WebRendererProcessType::kRenderer,
                    "RendererProcessType",
                    &main_thread_scheduler_impl->tracing_controller_,
@@ -987,8 +982,10 @@
 
   helper_.CheckOnValidThread();
 
-  if (helper_.IsShutdown() || main_thread_only().renderer_hidden == hidden)
+  if (helper_.IsShutdown() ||
+      main_thread_only().renderer_hidden.get() == hidden) {
     return;
+  }
 
   end_renderer_hidden_idle_period_closure_.Cancel();
 
@@ -1051,7 +1048,7 @@
   helper_.SetTimerSlack(timer_slack);
 
   if (helper_.IsShutdown() ||
-      main_thread_only().renderer_backgrounded == backgrounded)
+      main_thread_only().renderer_backgrounded.get() == backgrounded)
     return;
   if (backgrounded) {
     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
@@ -1586,7 +1583,7 @@
   }
 
   // TODO(skyostil): Add an idle state for foreground tabs too.
-  if (main_thread_only().renderer_hidden)
+  if (main_thread_only().renderer_hidden.get())
     new_policy.rail_mode() = RAILMode::kIdle;
 
   if (main_thread_only().renderer_pause_count != 0) {
@@ -2010,7 +2007,7 @@
            main_thread_only().blocking_input_expected_soon);
   dict.Add("idle_period_state", IdleHelper::IdlePeriodStateToString(
                                     idle_helper_.SchedulerIdlePeriodState()));
-  dict.Add("renderer_hidden", main_thread_only().renderer_hidden);
+  dict.Add("renderer_hidden", main_thread_only().renderer_hidden.get());
   dict.Add("waiting_for_any_main_frame_contentful_paint",
            any_thread().waiting_for_any_main_frame_contentful_paint);
   dict.Add("waiting_for_any_main_frame_meaningful_paint",
@@ -2023,7 +2020,8 @@
   dict.Add(
       "have_reported_blocking_intervention_since_navigation",
       main_thread_only().have_reported_blocking_intervention_since_navigation);
-  dict.Add("renderer_backgrounded", main_thread_only().renderer_backgrounded);
+  dict.Add("renderer_backgrounded",
+           main_thread_only().renderer_backgrounded.get());
   dict.Add("now", (optional_now - base::TimeTicks()).InMillisecondsF());
   dict.Add(
       "fling_compositor_escalation_deadline",
@@ -2624,8 +2622,9 @@
   builder.SetVersion(kUkmMetricVersion);
   builder.SetPageSchedulers(main_thread_only().page_schedulers.size());
 
-  builder.SetRendererBackgrounded(main_thread_only().renderer_backgrounded);
-  builder.SetRendererHidden(main_thread_only().renderer_hidden);
+  builder.SetRendererBackgrounded(
+      main_thread_only().renderer_backgrounded.get());
+  builder.SetRendererHidden(main_thread_only().renderer_hidden.get());
   builder.SetRendererAudible(main_thread_only().is_audio_playing);
   builder.SetUseCase(
       static_cast<int>(main_thread_only().current_use_case.get()));
@@ -2637,7 +2636,7 @@
   builder.SetTaskDuration(task_timing.wall_duration().InMicroseconds());
   builder.SetIsOOPIF(!frame_scheduler->GetPageScheduler()->IsMainFrameLocal());
 
-  if (main_thread_only().renderer_backgrounded) {
+  if (main_thread_only().renderer_backgrounded.get()) {
     base::TimeDelta time_since_backgrounded =
         (task_timing.end_time() -
          main_thread_only().background_status_changed_at);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index 112eea0a..41d76f6 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -835,9 +835,10 @@
                          TracingCategoryName::kTopLevel>
         rail_mode_for_tracing;  // Don't use except for tracing.
 
-    TraceableState<bool, TracingCategoryName::kTopLevel> renderer_hidden;
+    TraceableObjectState<bool, TracingCategoryName::kTopLevel> renderer_hidden;
     absl::optional<base::ScopedSampleMetadata> renderer_hidden_metadata;
-    TraceableState<bool, TracingCategoryName::kTopLevel> renderer_backgrounded;
+    TraceableObjectState<bool, TracingCategoryName::kTopLevel>
+        renderer_backgrounded;
     TraceableState<bool, TracingCategoryName::kDefault>
         blocking_input_expected_soon;
     TraceableState<bool, TracingCategoryName::kDebug>
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key.cc b/third_party/blink/renderer/platform/storage/blink_storage_key.cc
index 91dfb1c..af1e92ce 100644
--- a/third_party/blink/renderer/platform/storage/blink_storage_key.cc
+++ b/third_party/blink/renderer/platform/storage/blink_storage_key.cc
@@ -6,6 +6,7 @@
 
 #include <ostream>
 
+#include "base/stl_util.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/blink/renderer/platform/network/blink_schemeful_site.h"
 
@@ -60,11 +61,9 @@
           storage_key.nonce() ? &storage_key.nonce().value() : nullptr) {}
 
 BlinkStorageKey::operator StorageKey() const {
-  return nonce_.has_value()
-             ? StorageKey::CreateWithNonce(origin_->ToUrlOrigin(),
-                                           nonce_.value())
-             : StorageKey(origin_->ToUrlOrigin(),
-                          static_cast<net::SchemefulSite>(top_level_site_));
+  return StorageKey::CreateWithOptionalNonce(
+      origin_->ToUrlOrigin(), static_cast<net::SchemefulSite>(top_level_site_),
+      base::OptionalOrNullptr(nonce_));
 }
 
 String BlinkStorageKey::ToDebugString() const {
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key.h b/third_party/blink/renderer/platform/storage/blink_storage_key.h
index 32ba96d..ad4963dc 100644
--- a/third_party/blink/renderer/platform/storage/blink_storage_key.h
+++ b/third_party/blink/renderer/platform/storage/blink_storage_key.h
@@ -32,6 +32,8 @@
   // Creates a BlinkStorageKey with the given origin. `origin` must not be null.
   // `origin` can be opaque. This implicitly sets `top_level_site_` to the same
   // origin.
+  // TODO(https://crbug.com/1271615): Remove or mark as test-only most of these
+  // constructors and factory methods.
   explicit BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin);
 
   // Creates a BlinkStorageKey with the given origin and top-level site.
@@ -39,6 +41,13 @@
   BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin,
                   const BlinkSchemefulSite& top_level_site);
 
+  // Creates a BlinkStorageKey with the given origin, top-level site and nonce.
+  // `origin` must not be null. `origin` can be opaque.
+  // `nonce` can be null to create a key without a nonce.
+  BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin,
+                  const BlinkSchemefulSite& top_level_site,
+                  const base::UnguessableToken* nonce);
+
   // Creates a BlinkStorageKey converting the given StorageKey `storage_key`.
   BlinkStorageKey(const StorageKey& storage_key);
 
@@ -73,9 +82,6 @@
  private:
   BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin,
                   const base::UnguessableToken* nonce);
-  BlinkStorageKey(scoped_refptr<const SecurityOrigin> origin,
-                  const BlinkSchemefulSite& top_level_site,
-                  const base::UnguessableToken* nonce);
 
   scoped_refptr<const SecurityOrigin> origin_;
   BlinkSchemefulSite top_level_site_;
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc b/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc
index 5eca727..e9bc91f2 100644
--- a/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc
+++ b/third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h"
 
+#include "base/stl_util.h"
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
 #include "third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h"
@@ -29,22 +30,8 @@
   if (!data.ReadNonce(&nonce))
     return false;
 
-  if (nonce.has_value()) {
-    // This call does not need or use the top_level_site. But since the
-    // implementation sets the top_level_site to be same-site with the origin we
-    // should confirm that's still the case.
-    //
-    // TODO(crbug.com/1199077): This should be represented by a union since the
-    // usages of top_level_site and nonce are mutally exclusive.
-    if (top_level_site != blink::BlinkSchemefulSite(origin))
-      return false;
-
-    *out = blink::BlinkStorageKey::CreateWithNonce(std::move(origin),
-                                                   nonce.value());
-  } else {
-    *out = blink::BlinkStorageKey(std::move(origin), top_level_site);
-  }
-
+  *out = blink::BlinkStorageKey(std::move(origin), top_level_site,
+                                base::OptionalOrNullptr(nonce));
   return true;
 }
 
diff --git a/third_party/blink/renderer/platform/testing/test_paint_artifact.h b/third_party/blink/renderer/platform/testing/test_paint_artifact.h
index 024aa92..59e5907 100644
--- a/third_party/blink/renderer/platform/testing/test_paint_artifact.h
+++ b/third_party/blink/renderer/platform/testing/test_paint_artifact.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item_list.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
 #include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/platform/timer.cc b/third_party/blink/renderer/platform/timer.cc
index 2e9a8cbf..d73cfc680 100644
--- a/third_party/blink/renderer/platform/timer.cc
+++ b/third_party/blink/renderer/platform/timer.cc
@@ -67,7 +67,7 @@
 
   repeat_interval_ = base::TimeDelta();
   next_fire_time_ = base::TimeTicks();
-  weak_ptr_factory_.InvalidateWeakPtrs();
+  delayed_task_handle_.CancelTask();
 }
 
 base::TimeDelta TimerBase::NextFireInterval() const {
@@ -90,7 +90,7 @@
   }
 
   bool active = IsActive();
-  weak_ptr_factory_.InvalidateWeakPtrs();
+  delayed_task_handle_.CancelTask();
   web_task_runner_ = std::move(task_runner);
 
   if (!active)
@@ -114,16 +114,16 @@
     next_fire_time_ = new_time;
 
     // Cancel any previously posted task.
-    weak_ptr_factory_.InvalidateWeakPtrs();
+    delayed_task_handle_.CancelTask();
 
-    web_task_runner_->PostDelayedTask(
-        location_, BindTimerClosure(weak_ptr_factory_.GetWeakPtr()), delay);
+    delayed_task_handle_ = web_task_runner_->PostCancelableDelayedTask(
+        location_, BindTimerClosure(), delay);
   }
 }
 
 NO_SANITIZE_ADDRESS
 void TimerBase::RunInternal() {
-  weak_ptr_factory_.InvalidateWeakPtrs();
+  DCHECK(!delayed_task_handle_.IsValid());
 
   TRACE_EVENT0("blink", "TimerBase::run");
 #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/platform/timer.h b/third_party/blink/renderer/platform/timer.h
index 654d411..2fd8049 100644
--- a/third_party/blink/renderer/platform/timer.h
+++ b/third_party/blink/renderer/platform/timer.h
@@ -29,6 +29,7 @@
 #include "base/dcheck_is_on.h"
 #include "base/location.h"
 #include "base/memory/weak_ptr.h"
+#include "base/task/delayed_task_handle.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -87,9 +88,8 @@
  protected:
   virtual void Fired() = 0;
 
-  virtual base::OnceClosure BindTimerClosure(
-      base::WeakPtr<TimerBase> weak_ptr) {
-    return WTF::Bind(&TimerBase::RunInternal, std::move(weak_ptr));
+  virtual base::OnceClosure BindTimerClosure() {
+    return WTF::Bind(&TimerBase::RunInternal, WTF::Unretained(this));
   }
 
   void RunInternal();
@@ -107,9 +107,8 @@
 #if DCHECK_IS_ON()
   base::PlatformThreadId thread_;
 #endif
-  // Used for invalidating tasks at arbitrary times and after the timer has been
-  // destructed.
-  base::WeakPtrFactory<TimerBase> weak_ptr_factory_{this};
+  // The handle to the posted delayed task.
+  base::DelayedTaskHandle delayed_task_handle_;
 };
 
 template <typename TimerFiredClass>
@@ -161,9 +160,9 @@
  protected:
   void Fired() final { (object_->*function_)(this); }
 
-  base::OnceClosure BindTimerClosure(base::WeakPtr<TimerBase> weak_ptr) final {
+  base::OnceClosure BindTimerClosure() final {
     return WTF::Bind(&HeapTaskRunnerTimer::RunInternalTrampoline,
-                     std::move(weak_ptr), WrapWeakPersistent(object_.Get()));
+                     WTF::Unretained(this), WrapWeakPersistent(object_.Get()));
   }
 
  private:
@@ -171,14 +170,12 @@
   // object has been deemed as dead by the GC but not yet reclaimed. Dead
   // objects that have not been reclaimed yet must not be touched (which is
   // enforced by ASAN poisoning).
-  static void RunInternalTrampoline(base::WeakPtr<TimerBase> weak_ptr,
+  static void RunInternalTrampoline(HeapTaskRunnerTimer* timer,
                                     TimerFiredClass* object) {
-    // - {weak_ptr} is invalidated upon request and when the timer is destroyed.
-    // - {object} is null when the garbage collector deemed the timer as
-    //   unreachable.
-    if (weak_ptr && object) {
-      static_cast<HeapTaskRunnerTimer*>(weak_ptr.get())->RunInternal();
-    }
+    // |object| is null when the garbage collector deemed the timer as
+    // unreachable.
+    if (object)
+      timer->RunInternal();
   }
 
   WeakMember<TimerFiredClass> object_;
@@ -190,7 +187,7 @@
 #if DCHECK_IS_ON()
   DCHECK_EQ(thread_, CurrentThread());
 #endif
-  return weak_ptr_factory_.HasWeakPtrs();
+  return delayed_task_handle_.IsValid();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc
index bc762f8..60ce620 100644
--- a/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.cc
@@ -9,6 +9,30 @@
 #endif
 
 namespace blink {
+namespace {
+
+void RunDrainAndSwapCallbacksOnCompositorThread(
+    scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
+    QueueReportTimeSwapPromise::DrainCallback drain_callback,
+    int source_frame_number,
+    base::OnceClosure swap_callback) {
+  if (compositor_task_runner &&
+      !compositor_task_runner->BelongsToCurrentThread()) {
+    compositor_task_runner->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RunDrainAndSwapCallbacksOnCompositorThread, nullptr,
+                       std::move(drain_callback), source_frame_number,
+                       std::move(swap_callback)));
+    return;
+  }
+
+  if (drain_callback)
+    std::move(drain_callback).Run(source_frame_number);
+  if (swap_callback)
+    std::move(swap_callback).Run();
+}
+
+}  // namespace
 
 QueueReportTimeSwapPromise::QueueReportTimeSwapPromise(
     int source_frame_number,
@@ -48,14 +72,16 @@
 
 cc::SwapPromise::DidNotSwapAction QueueReportTimeSwapPromise::DidNotSwap(
     DidNotSwapReason reason) {
+  if (reason == cc::SwapPromise::COMMIT_FAILS)
+    return DidNotSwapAction::KEEP_ACTIVE;
+
   if (reason == cc::SwapPromise::SWAP_FAILS ||
       reason == cc::SwapPromise::COMMIT_NO_UPDATE) {
-    if (drain_callback_)
-      std::move(drain_callback_).Run(source_frame_number_);
-    if (swap_callback_)
-      std::move(swap_callback_).Run();
-  } else if (reason == cc::SwapPromise::COMMIT_FAILS) {
-    return DidNotSwapAction::KEEP_ACTIVE;
+    // Since `DidNotSwap()` can be called on any thread, run drain and swap
+    // callbacks on the compositor thread if there is one.
+    RunDrainAndSwapCallbacksOnCompositorThread(
+        compositor_task_runner_, std::move(drain_callback_),
+        source_frame_number_, std::move(swap_callback_));
   }
   return DidNotSwapAction::BREAK_PROMISE;
 }
diff --git a/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h
index 66db1f02..afc87b73 100644
--- a/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h
+++ b/third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h
@@ -35,7 +35,7 @@
   cc::SwapPromise::DidNotSwapAction DidNotSwap(
       DidNotSwapReason reason) override;
   void DidActivate() override;
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 
  private:
   int source_frame_number_;
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
index 05755f7..84f923cb 100644
--- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
+++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
@@ -495,6 +495,9 @@
   }
 
   PossiblyScheduleMainFrame();
+
+  if (client_)
+    client_->InputEventsDispatched(/*raf_aligned=*/false);
 }
 
 static bool IsAsyncTouchMove(
@@ -562,6 +565,9 @@
   }
 
   PossiblyScheduleMainFrame();
+
+  if (client_)
+    client_->InputEventsDispatched(/*raf_aligned=*/true);
 }
 
 void MainThreadEventQueue::PostTaskToMainThread() {
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
index d07f843a..36d36b8 100644
--- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
+++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
@@ -46,6 +46,12 @@
   virtual bool HandleInputEvent(const WebCoalescedInputEvent& event,
                                 std::unique_ptr<cc::EventMetrics> metrics,
                                 HandledEventCallback handled_callback) = 0;
+
+  // Notify clients that the queued events have been dispatched. `raf_aligned`
+  // determines whether the events were rAF-aligned events or non-rAF-aligned
+  // ones.
+  virtual void InputEventsDispatched(bool raf_aligned) = 0;
+
   // Requests a BeginMainFrame callback from the compositor.
   virtual void SetNeedsMainFrame() = 0;
 };
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
index 56f4ac2..f3ba2da4 100644
--- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
+++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
@@ -238,6 +238,8 @@
     }
   }
 
+  void RunPendingTasksWithoutRaf() { main_task_runner_->RunUntilIdle(); }
+
   // MainThreadEventQueueClient overrides.
   bool HandleInputEvent(const blink::WebCoalescedInputEvent& event,
                         std::unique_ptr<cc::EventMetrics> metrics,
@@ -250,6 +252,12 @@
                             event.latency_info(), nullptr, absl::nullopt);
     return true;
   }
+  void InputEventsDispatched(bool raf_aligned) override {
+    if (raf_aligned)
+      raf_aligned_events_dispatched_ = true;
+    else
+      non_raf_aligned_events_dispatched_ = true;
+  }
   void SetNeedsMainFrame() override { needs_main_frame_ = true; }
 
   std::vector<ReceivedCallback> GetAndResetCallbackResults() {
@@ -270,6 +278,8 @@
 
   bool needs_main_frame_ = false;
   bool handle_input_event_ = true;
+  bool raf_aligned_events_dispatched_ = false;
+  bool non_raf_aligned_events_dispatched_ = false;
   base::TimeTicks frame_time_;
   unsigned closure_count_ = 0;
 };
@@ -1149,6 +1159,7 @@
     return true;
   }
 
+  void InputEventsDispatched(bool raf_aligned) override {}
   void SetNeedsMainFrame() override {}
 
  protected:
@@ -1587,4 +1598,67 @@
   }
 }
 
+// Verifies that after rAF-aligned or non-rAF-aligned events are dispatched,
+// clients are notified that the dispatch is done.
+TEST_F(MainThreadEventQueueTest, InputEventsDispatchedNotified) {
+  WebKeyboardEvent key_down(WebInputEvent::Type::kRawKeyDown, 0,
+                            base::TimeTicks::Now());
+  WebKeyboardEvent key_up(WebInputEvent::Type::kKeyUp, 0,
+                          base::TimeTicks::Now());
+  WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build(
+      WebInputEvent::Type::kMouseMove, 10, 10, 0);
+
+  // Post two non-rAF-aligned events.
+  HandleEvent(key_down, blink::mojom::InputEventResultState::kSetNonBlocking);
+  HandleEvent(key_up, blink::mojom::InputEventResultState::kSetNonBlocking);
+
+  // Post one rAF-aligned event.
+  HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking);
+
+  EXPECT_EQ(3u, event_queue().size());
+
+  // Task runner should have a task queued to dispatch non-rAF-aligned events.
+  EXPECT_TRUE(main_task_runner_->HasPendingTask());
+
+  // A main frame should be needed to dispatch the rAF-aligned event.
+  EXPECT_TRUE(needs_main_frame_);
+
+  // Run pending tasks without invoking a rAF.
+  RunPendingTasksWithoutRaf();
+
+  // The client should be notified that non-rAF-aligned events are dispatched.
+  // No notification for rAF-aligned events, yet.
+  EXPECT_TRUE(non_raf_aligned_events_dispatched_);
+  EXPECT_FALSE(raf_aligned_events_dispatched_);
+
+  // No task should be pending in the task runner.
+  EXPECT_FALSE(main_task_runner_->HasPendingTask());
+
+  // A main frame is still needed.
+  EXPECT_TRUE(needs_main_frame_);
+
+  // The two non-rAF-alinged events should be handled out of the queue.
+  EXPECT_EQ(1u, event_queue().size());
+  EXPECT_EQ(2u, handled_tasks_.size());
+  EXPECT_EQ(key_down.GetType(),
+            handled_tasks_.at(0)->taskAsEvent()->Event().GetType());
+  EXPECT_EQ(key_up.GetType(),
+            handled_tasks_.at(1)->taskAsEvent()->Event().GetType());
+
+  // Run pending tasks with a simulated rAF.
+  RunPendingTasksWithSimulatedRaf();
+
+  // Now, clients should be notified of rAF-aligned events dispatch.
+  EXPECT_TRUE(raf_aligned_events_dispatched_);
+
+  // No main frame should be needed anymore..
+  EXPECT_FALSE(needs_main_frame_);
+
+  // The rAF-alinged event should be handled out of the queue now.
+  EXPECT_EQ(0u, event_queue().size());
+  EXPECT_EQ(3u, handled_tasks_.size());
+  EXPECT_EQ(mouse_move.GetType(),
+            handled_tasks_.at(2)->taskAsEvent()->Event().GetType());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
index a33e07f..7b1f378 100644
--- a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
+++ b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.cc
@@ -299,6 +299,27 @@
   return true;
 }
 
+void WidgetInputHandlerManager::InputEventsDispatched(bool raf_aligned) {
+  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+
+  // Immediately after dispatching rAF-aligned events, a frame is still in
+  // progress. There is no need to check and break swap promises here, because
+  // when the frame is finished, they will be broken if there is no update (see
+  // `LayerTreeHostImpl::BeginMainFrameAborted`). Also, unlike non-rAF-aligned
+  // events, checking `RequestedMainFramePending()` would not work here, because
+  // it is reset before dispatching rAF-aligned events.
+  if (raf_aligned)
+    return;
+
+  // If no main frame request is pending after dispatching non-rAF-aligned
+  // events, there will be no updated frame to submit to Viz; so, break
+  // outstanding swap promises here due to no update.
+  if (widget_ && !widget_->LayerTreeHost()->RequestedMainFramePending()) {
+    widget_->LayerTreeHost()->GetSwapPromiseManager()->BreakSwapPromises(
+        cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE);
+  }
+}
+
 void WidgetInputHandlerManager::SetNeedsMainFrame() {
   widget_->RequestAnimationAfterDelay(base::TimeDelta());
 }
@@ -730,6 +751,7 @@
 
   widget_->input_handler().HandleInputEvent(*event, std::move(metrics),
                                             std::move(send_callback));
+  InputEventsDispatched(/*raf_aligned=*/false);
 }
 
 void WidgetInputHandlerManager::FindScrollTargetReply(
diff --git a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
index 39e8e4d..4a3f326d 100644
--- a/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
+++ b/third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h
@@ -93,6 +93,7 @@
   bool HandleInputEvent(const WebCoalescedInputEvent& event,
                         std::unique_ptr<cc::EventMetrics> metrics,
                         HandledEventCallback handled_callback) override;
+  void InputEventsDispatched(bool raf_aligned) override;
   void SetNeedsMainFrame() override;
 
   // InputHandlerProxyClient overrides.
diff --git a/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py b/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
index bae4308..5ba35e83 100644
--- a/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
+++ b/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
@@ -533,8 +533,7 @@
 
 class ReadableTextFileObject(ReadableBinaryFileObject):
     def __init__(self, fs, path, data):
-        super(ReadableTextFileObject,
-              self).__init__(fs, path, StringIO(data.decode(encoding='utf-8')))
+        super(ReadableTextFileObject, self).__init__(fs, path, StringIO(data))
 
     def close(self):
         self.data.close()
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
index d43b385..b1bc97e3 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
@@ -126,7 +126,7 @@
             pair('web_tests_flag_specific_config_name',
                  self._port.flag_specific_config_name() or ''),
             pair('web_tests_base_timeout',
-                 str(self._port.timeout_ms() / 1000)),
+                 str(int(self._port.timeout_ms() / 1000))),
         ]
 
         for used_file in self._port.used_expectations_files():
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 659be50..f34cca2 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -377,7 +377,6 @@
 crbug.com/874695 http/tests/permissions/chromium/test-request-multiple-sharedworker.html [ Slow ]
 crbug.com/874695 http/tests/permissions/chromium/test-request-multiple-window.html [ Slow ]
 crbug.com/874695 http/tests/permissions/chromium/test-request-multiple-worker.html [ Slow ]
-crbug.com/874695 http/tests/permissions/chromium/test-request-sharedworker.html [ Slow ]
 crbug.com/874695 http/tests/permissions/chromium/test-request-window.html [ Slow ]
 crbug.com/874695 http/tests/permissions/chromium/test-request-worker.html [ Slow ]
 crbug.com/874695 http/tests/permissions/test-query.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 703c4e24..8955b49 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3239,12 +3239,10 @@
 crbug.com/626703 [ Mac11 ] external/wpt/selection/textcontrols/selectionchange-bubble.html [ Timeout ]
 crbug.com/626703 [ Win ] external/wpt/selection/textcontrols/selectionchange-bubble.html [ Timeout ]
 crbug.com/626703 external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio-cross-origin.sub.html [ Failure ]
-crbug.com/1270865 [ Mac ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click.html [ Failure Timeout ]
 crbug.com/626703 [ Win7 ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click.html [ Failure Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click.html [ Failure Timeout ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click.html [ Failure Timeout ]
 crbug.com/626703 [ Mac11 ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-assign-user-click.html [ Failure Timeout ]
-crbug.com/1270842 [ Mac ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup.html [ Failure Timeout ]
 crbug.com/626703 [ Win7 ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup.html [ Failure Timeout ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-user-click-during-pageshow.html [ Timeout ]
@@ -3530,6 +3528,7 @@
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/websockets/stream/tentative/backpressure-send.any.worker.html?wpt_flags=h2 [ Crash Failure ]
 crbug.com/626703 [ Mac11 ] external/wpt/websockets/stream/tentative/backpressure-send.any.html?wpt_flags=h2 [ Failure Skip Timeout ]
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/websockets/stream/tentative/backpressure-send.any.html?wpt_flags=h2 [ Failure Skip Timeout ]
+crbug.com/626703 [ Mac10.15 ] external/wpt/websockets/stream/tentative/backpressure-receive.any.html?wpt_flags=h2 [ Failure Pass ]
 crbug.com/626703 [ Mac ] external/wpt/websockets/bufferedAmount-unchanged-by-sync-xhr.any.worker.html?wpt_flags=h2 [ Failure Pass ]
 crbug.com/626703 [ Mac ] external/wpt/websockets/basic-auth.any.html?wpt_flags=h2 [ Failure Pass ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/worklets/audio-worklet-credentials.https.html [ Crash Failure ]
@@ -4249,6 +4248,9 @@
 crbug.com/759665 external/wpt/css/css-grid/animation/grid-template-rows-interpolation.html [ Failure ]
 crbug.com/1045599 external/wpt/css/css-grid/grid-definition/grid-repeat-max-width-001.html [ Failure ]
 
+# Simple to fix - but blocked on performance regression requiring cache logic change.
+crbug.com/1272533 external/wpt/css/css-grid/layout-algorithm/grid-intrinsic-size-dynamic-block-size.html [ Failure ]
+
 # The 'last baseline' keyword is not implemented yet
 crbug.com/885175 external/wpt/css/css-grid/alignment/grid-item-self-baseline-001.html [ Skip ]
 crbug.com/885175 external/wpt/css/css-grid/alignment/grid-self-alignment-baseline-with-grid-001.html [ Skip ]
@@ -7255,7 +7257,7 @@
 crbug.com/1191846 virtual/prerender/external/wpt/speculation-rules/prerender/local-storage.html [ Failure Pass ]
 
 # Sheriff 2021-11-10
-crbug.com/1268963 [ Linux ] virtual/plz-dedicated-worker/external/wpt/resource-timing/object-not-found-after-TAO-cross-origin-redirect.html [ Failure Pass ]
+crbug.com/1268963 [ Linux ] external/wpt/resource-timing/object-not-found-after-TAO-cross-origin-redirect.html [ Failure Pass ]
 
 # Sheriff 2021-11-12
 crbug.com/1268594 [ Linux ] css3/filters/composited-layer-bounds-after-sw-blur-animation.html [ Failure Pass ]
@@ -7284,7 +7286,14 @@
 crbug.com/1272352 virtual/threaded/http/tests/devtools/isolated-code-cache/stale-revalidation-test.js [ Crash Pass ]
 crbug.com/1272376 virtual/scroll-unification/plugins/plugin-document-back-forward.html [ Failure Pass ]
 crbug.com/1272380 http/tests/devtools/bindings/bindings-multiple-frames.js [ Failure Pass ]
+crbug.com/1272575 [ Mac ] virtual/gpu-rasterization/images/color-profile-svg-fill-text.html [ Failure Pass ]
+
+# Flaky on mac 10.13
+crbug.com/1263709 [ Mac10.13 ] http/tests/devtools/elements/node-xpath.js [ Failure ]
 
 # Flaky on Mac and Windows
 crbug.com/1272199 external/wpt/websockets/stream/tentative/backpressure-receive.any.serviceworker.html?wpt_flags=h2 [ Failure Pass ]
 crbug.com/1272203 external/wpt/websockets/stream/tentative/backpressure-send.any.serviceworker.html?wpt_flags=h2 [ Failure Pass ]
+
+# Times out flakily on all platforms. Previously marked slow, crbug.com/874695.
+crbug.com/1272801 http/tests/permissions/chromium/test-request-sharedworker.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 5bb44a2..d9ff4b0 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -851,6 +851,7 @@
       "external/wpt/service-workers/service-worker/partitioned-service-worker.tentative.https.html",
       "external/wpt/service-workers/service-worker/partitioned-service-worker-getRegistrations.tentative.https.html",
       "external/wpt/service-workers/service-worker/partitioned-service-worker-matchAll.tentative.https.html",
+      "external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https.html",
       "external/wpt/webstorage/localstorage-basic-partitioned.tentative.sub.html"
     ],
     "args": [ "--enable-features=ThirdPartyStoragePartitioning" ]
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 342e445..842c64f 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
@@ -164259,6 +164259,19 @@
        {}
       ]
      ],
+     "text-decoration-lines-001.html": [
+      "a87218a20efb2ea5e95514ccc6b0d0a5b1c5fd4f",
+      [
+       null,
+       [
+        [
+         "/css/css-text-decor/reference/text-decoration-lines-001-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "text-decoration-overline-wavy-covers-whole-line-length-001.html": [
       "4dfd0901733c1730a59ff3c29964938412174526",
       [
@@ -257734,6 +257747,10 @@
        "f14d25a70ba3ccfc80a99e924bb6b6a7d4694b1e",
        []
       ],
+      "text-decoration-lines-001-ref.html": [
+       "a2d0c3dca74a1699e81a0b8afa085caff48f9025",
+       []
+      ],
       "text-decoration-propagation-display-contents-ref.html": [
        "5eecc8c8b4e39c4b940e472e5e0f39e9262e10d9",
        []
@@ -300553,6 +300570,10 @@
       "c6d12e4eb7e735632515bb1894d874417eb39a35",
       []
      ],
+     "partitioned-service-worker-claim.tentative.https-expected.txt": [
+      "ed2f192b6d22edc45948643ea7d16730e56eb07b",
+      []
+     ],
      "partitioned-service-worker-getRegistrations.tentative.https-expected.txt": [
       "318c2cbf9e749e08dc509baf58046f5b9ba33921",
       []
@@ -301546,6 +301567,10 @@
        "835046d472b2b3bb46aa7e4cba2976d367b29894",
        []
       ],
+      "partitioned-service-worker-iframe-claim.html": [
+       "c0f8d76901a2a7a7ef552da13571505af9699c1d",
+       []
+      ],
       "partitioned-service-worker-third-party-iframe-getRegistrations.html": [
        "f7b99cb358a2343758fcb9d359778eb02aaf1f69",
        []
@@ -301563,7 +301588,7 @@
        []
       ],
       "partitioned-storage-sw.js": [
-       "e51cf3142f18e5fe5fa51c02f9a09a0d83e6aecb",
+       "d56b7c84d97fa90f893120091e53fd0ff0ed5477",
        []
       ],
       "partitioned-utils.js": [
@@ -484871,6 +484896,13 @@
        {}
       ]
      ],
+     "partitioned-service-worker-claim.tentative.https.html": [
+      "1f42c528e0b38f11b156f77f144daec6513c1fed",
+      [
+       null,
+       {}
+      ]
+     ],
      "partitioned-service-worker-getRegistrations.tentative.https.html": [
       "81d275194ef61ea9cff192b5d07913c32bdba8af",
       [
@@ -548957,7 +548989,7 @@
      },
      "execute_async_script": {
       "collections.py": [
-       "2dc9b9a009acd06844824f9dd173b03af34cd943",
+       "49657711e28cbc51e7bad7671031e93d73739d60",
        [
         null,
         {}
@@ -548996,7 +549028,7 @@
      },
      "execute_script": {
       "collections.py": [
-       "8291fd71388b8eedd4c1039a52bffa78ffaf7cd5",
+       "4d88d497060480043682df29298387d150bf9055",
        [
         null,
         {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001-ref.html
new file mode 100644
index 0000000..8049ba2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<style>
+  body {
+    font-size: 3em;
+    font-weight: bolder;
+  }
+  #affected2 {
+    color: green;
+  }
+</style>
+<body><span>This should have default style (black).</span><span id="affected2">This should have 'highlight2' style (green).</span>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html
new file mode 100644
index 0000000..25f4e7e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-001.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>CSS Highlight API Test: Overlapping Highlights</title>
+<link rel="help" href="https://drafts.csswg.org/css-highlight-api-1/">
+<link rel="match" href="custom-highlight-painting-overlapping-highlights-001-ref.html">
+<meta name="assert" value="UAs must not define any styles for custom highlight pseudo-elements in the default UA stylesheet.">
+<style>
+  body {
+    font-size: 3em;
+    font-weight: bolder;
+  }
+  #affected1::highlight(highlight1) {
+    color: red;
+  }
+  #affected2::highlight(highlight2) {
+    color: green;
+  }
+</style>
+<body><span id="affected1">This should have default style (black).</span><span id="affected2">This should have 'highlight2' style (green).</span>
+<script>
+  /*
+    This test is meant to verify that:
+      - UAs must not define any styles for custom highlight pseudo-elements in
+      the default UA stylesheet.
+      - A custom highlight pseudo-element inherits the styles of its originating
+      element.
+
+    In this test, highlight2 has higher priority because it was registered
+    later, so it is painted over highlight1. This includes painting for
+    span#affected1, where there is no CSS rule for highlight2. The result is
+    that highlight2 paints on top for span#affected1, using the originating
+    element's color. Thus it appears as if no highlight was painted at all for
+    span#affected1.
+
+    See https://drafts.csswg.org/css-highlight-api-1/#default-styles
+  */
+
+  const node = document.body;
+  let r = new Range();
+  r.setStart(node, 0);
+  r.setEnd(node, 2);
+
+  CSS.highlights.set("highlight1", new Highlight(r));
+  CSS.highlights.set("highlight2", new Highlight(r));
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-002-ref.html
new file mode 100644
index 0000000..efc4f487
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-002-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<style>
+  div {
+      font-size: 3em;
+      font-weight: bolder;
+  }
+  #affected1 {
+    color: green;
+    background-color: rgb(0, 255, 0, 0.5);
+  }
+  #affected2 {
+    background-color: rgba(100, 0, 100, 0.5);
+  }
+</style>
+<body><div><span id="affected1">Green on lime.</span><span id="affected2">Black on maroon.</span></div>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-002.html b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-002.html
new file mode 100644
index 0000000..2e8d782
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-highlight-api/painting/custom-highlight-painting-overlapping-highlights-002.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>CSS Highlight API Test: Overlapping Highlights</title>
+<link rel="help" href="https://drafts.csswg.org/css-highlight-api-1/">
+<link rel="match" href="custom-highlight-painting-overlapping-highlights-002-ref.html">
+<meta name="assert" value="UAs must not define any styles for custom highlight pseudo-elements in the default UA stylesheet.">
+<style>
+  div {
+      font-size: 3em;
+      font-weight: bolder;
+  }
+  #affected1::highlight(highlight1) {
+    color: green;
+    background-color: rgb(0, 255, 0, 0.5);
+  }
+  #affected2::highlight(highlight2) {
+    color: red;
+    background-color: rgba(100, 0, 100, 0.5);
+  }
+</style>
+<body><div><span id="affected1">Green on lime.</span><span id="affected2">Black on maroon.</span></div>
+<script>
+  /*
+    This test is meant to verify that:
+      - UAs must not define any styles for custom highlight pseudo-elements in
+      the default UA stylesheet.
+      - A custom highlight pseudo-element inherits the styles of its originating
+      element.
+
+    In this test, highlight1 has higher priority, so it is painted over
+    highlight2. This includes painting for span#affected2, where there is no CSS
+    rule for highlight1. The result is that highlight1 paints on top for
+    span#affected2, using the originating element's color (black) and background
+    color (transparent). Thus, span#affected2 gets text color black, and the
+    background remains the same color as that applied by highlight2 (maroon).
+
+    See https://drafts.csswg.org/css-highlight-api-1/#default-styles
+  */
+
+  const div = document.querySelector("div");
+
+  let r = new Range();
+  r.setStart(div, 0);
+  r.setEnd(div, 2);
+  let r2 = new Range();
+  r2.setStart(div, 0);
+  r2.setEnd(div, 2);
+
+  let h = new Highlight(r);
+  h.priority = 3;
+  let h2 = new Highlight(r2);
+  h2.priority = 2;
+
+  CSS.highlights.set("highlight1", h);
+  CSS.highlights.set("highlight2", h2);
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/dynamic-range.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/dynamic-range.html
index 261fccf6..f423efbe 100644
--- a/third_party/blink/web_tests/external/wpt/css/mediaqueries/dynamic-range.html
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/dynamic-range.html
@@ -35,15 +35,13 @@
 
 test(() => {
   let match_standard = window.matchMedia("(dynamic-range: standard)");
-  let match_high = window.matchMedia("(dynamic-range: high)");
-  assert_not_equals(match_standard.matches, match_high.matches);
-}, "Check that dynamic-range is 'standard' or 'high', but not both");
+  assert_true(match_standard.matches);
+}, "Check that dynamic-range always matches 'standard'");
 
 test(() => {
   let match_standard = window.matchMedia("(video-dynamic-range: standard)");
-  let match_high = window.matchMedia("(video-dynamic-range: high)");
-  assert_not_equals(match_standard.matches, match_high.matches);
-}, "Check that video-dynamic-range is 'standard' or 'high', but not both");
+  assert_true(match_standard.matches);
+}, "Check that video-dynamic-range always matches 'standard'");
 
 test(() => {
   let match_invalid = window.matchMedia("(video-dynamic-range: invalid)");
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling-ref.html
index 1e7a097..92504a4 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling-ref.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling-ref.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Input type=image with CSS content.</title>
+<title>Stylability of select>option with :checked pseudo</title>
 <link rel="author" href="mailto:masonf@chromium.org">
 
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling.html
index c705b99b..216b03a8 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-checked-styling.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Input type=image with CSS content.</title>
+<title>Stylability of select>option with :checked pseudo</title>
 <link rel="author" href="mailto:masonf@chromium.org">
 <link rel="help"  href="https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element">
 <link rel="match"  href="option-checked-styling-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/select-invalidation-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/select-invalidation-ref.html
new file mode 100644
index 0000000..7a3dd1d5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/select-invalidation-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Select rendering invalidation</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+
+<style>
+  select {
+    color: lime;
+  }
+</style>
+
+<select id=select>
+  <option>The down arrow should be green</option>
+  <option>value B</option>
+</select>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/select-invalidation.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/select-invalidation.html
new file mode 100644
index 0000000..199db0b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/select-invalidation.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Select rendering invalidation</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="help"  href="https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element">
+<link rel="match"  href="select-invalidation-ref.html">
+
+<style>
+  select {
+    color: red;
+  }
+</style>
+
+<select id=select>
+  <option>The down arrow should be green</option>
+  <option>value B</option>
+</select>
+
+<script>
+  requestAnimationFrame(() => {
+    requestAnimationFrame(() => {
+      select.style.color = "lime";
+      requestAnimationFrame(() => {
+        requestAnimationFrame(() => {
+          document.documentElement.classList.remove("reftest-wait");
+        });
+      });
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https-expected.txt
new file mode 100644
index 0000000..ed2f192
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL ServiceWorker's clients.claim() is partitioned assert_equals: 3p iframe was successfully claimed expected "success" but got "failure"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https.html
new file mode 100644
index 0000000..1f42c528
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title>Service Worker: Partitioned Service Workers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/partitioned-utils.js"></script>
+
+<body>
+This test creates a iframe in a first-party context and then registers a
+service worker (such that the iframe client is unclaimed).
+A third-party iframe is then created which has its SW call clients.claim()
+and then the test checks that the 1p iframe was not claimed int he process.
+Finally the test has its SW call clients.claim() and confirms the 1p iframe is
+claimed.
+
+<script>
+promise_test(async t => {
+  const script = './resources/partitioned-storage-sw.js';
+  const scope = './resources/partitioned-';
+
+  // Add a 1p iframe.
+  const wait_frame_url = new URL(
+    './resources/partitioned-service-worker-iframe-claim.html?1p-mode',
+    self.location);
+
+  const frame = await with_iframe(wait_frame_url, false);
+  t.add_cleanup(async () => {
+    frame.remove();
+  });
+
+  // Add service worker to this 1P context.
+  const reg = await service_worker_unregister_and_register(t, script, scope);
+  t.add_cleanup(() => reg.unregister());
+  await wait_for_state(t, reg.installing, 'activated');
+
+  // Register the message listener.
+  self.addEventListener('message', messageEventHandler);
+
+  // Now we need to create a third-party iframe whose SW will claim it and then
+  // the iframe will postMessage that its serviceWorker.controller state has
+  // changed.
+  const third_party_iframe_url = new URL(
+    './resources/partitioned-service-worker-iframe-claim.html?3p-mode',
+    get_host_info().HTTPS_ORIGIN + self.location.pathname);
+
+  // Create the 3p window (which will in turn create the iframe with the SW)
+  // and await on its data.
+  const frame_3p_data = await loadAndReturnSwData(t, third_party_iframe_url,
+    'window');
+  assert_equals(frame_3p_data.status, "success",
+     "3p iframe was successfully claimed");
+
+  // Confirm that the 1p iframe wasn't claimed at the same time.
+  const controller_1p_iframe = makeMessagePromise();
+  frame.contentWindow.postMessage({type: "get-controller"});
+  const controller_1p_iframe_data = await controller_1p_iframe;
+  assert_equals(controller_1p_iframe_data.controller, null,
+     "Test iframe client isn't claimed yet.");
+
+
+  // Tell the SW to claim.
+  const claimed_1p_iframe = makeMessagePromise();
+  reg.active.postMessage({type: "claim"});
+  const claimed_1p_iframe_data = await claimed_1p_iframe;
+
+  assert_equals(claimed_1p_iframe_data.status, "success",
+     "iframe client was successfully claimed.");
+
+}, "ServiceWorker's clients.claim() is partitioned");
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html
index 6c5e85fe..cd11a30 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/form-poster.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+<meta charset="utf-8"/>
 <meta name="referrer" content="origin">
 <form method="POST" id="form"></form>
 <script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html
index ce958f0..f0ced06 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/location-setter.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+<meta charset="utf-8"/>
 <meta name="referrer" content="origin">
 <script>
 function onLoad() {
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-parent.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-parent.html
new file mode 100644
index 0000000..b4832d4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-parent.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8"/>
+<meta name="referrer" content="origin">
+<script>
+async function onLoad() {
+  self.addEventListener('message', evt => {
+    if (self.opener)
+      self.opener.postMessage(evt.data, '*');
+    else
+      self.top.postMessage(evt.data, '*');
+  }, { once: true });
+  const params = new URLSearchParams(self.location.search);
+  const frame = document.createElement('iframe');
+  frame.src = params.get('target');
+  document.body.appendChild(frame);
+}
+self.addEventListener('load', onLoad);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-service-worker-iframe-claim.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-service-worker-iframe-claim.html
new file mode 100644
index 0000000..c0f8d76
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-service-worker-iframe-claim.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>Service Worker: 3P iframe for partitioned service workers</title>
+<script src="/test-helpers.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="./partitioned-utils.js"></script>
+
+<body>
+  <script>
+    // 1p mode will respond to requests for its current controller and
+    // postMessage when its controller changes.
+    async function onLoad1pMode(){
+      self.addEventListener('message', evt => {
+        if(!evt.data)
+          return;
+
+        if (evt.data.type === "get-controller") {
+          window.parent.postMessage({controller: navigator.serviceWorker.controller});
+        }
+      });
+
+      navigator.serviceWorker.addEventListener('controllerchange', evt => {
+        window.parent.postMessage({status: "success", context: "1p"}, '*');
+      });
+    }
+
+    // 3p mode will tell its SW to claim and then postMessage its results
+    // automatically.
+    async function onLoad3pMode() {
+      reg = await setup3pIframe();
+
+      if(navigator.serviceWorker.controller != null){
+        //This iframe is already under control of a service worker, testing for
+        // a controller change will timeout. Return a failure.
+        window.parent.postMessage({status: "failure", context: "3p"}, '*');
+        return;
+      }
+
+      // Once this client is claimed, let the test know.
+      navigator.serviceWorker.addEventListener('controllerchange', evt => {
+        window.parent.postMessage({status: "success", context: "3p"}, '*');
+      });
+
+      // Trigger the SW to claim.
+      reg.active.postMessage({type: "claim"});
+
+    }
+
+    const request_url = new URL(window.location.href);
+    var url_search = request_url.search.substr(1);
+
+    if(url_search == "1p-mode") {
+      self.addEventListener('load', onLoad1pMode);
+    }
+    else if(url_search == "3p-mode") {
+      self.addEventListener('load', onLoad3pMode);
+    }
+    // Else do nothing.
+  </script>
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-storage-sw.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-storage-sw.js
index e51cf31..d56b7c8 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-storage-sw.js
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/partitioned-storage-sw.js
@@ -17,18 +17,23 @@
 })
 
 self.addEventListener('message', (event) => {
-  if(!event.data)
-    return;
+  event.waitUntil(async function() {
+    if(!event.data)
+      return;
 
-  if (event.data.type === "get-id") {
-    event.source.postMessage({ID: ID});
-  }
-  else if(event.data.type === "get-match-all") {
-    clients.matchAll({includeUncontrolled: true}).then(clients_list => {
-      const url_list = clients_list.map(item => item.url);
-      event.source.postMessage({urls_list: url_list});
-    });
-  }
+    if (event.data.type === "get-id") {
+      event.source.postMessage({ID: ID});
+    }
+    else if(event.data.type === "get-match-all") {
+      clients.matchAll({includeUncontrolled: true}).then(clients_list => {
+        const url_list = clients_list.map(item => item.url);
+        event.source.postMessage({urls_list: url_list});
+      });
+    }
+    else if(event.data.type === "claim") {
+      await clients.claim();
+    }
+  }());
 });
 
 async function fetchEventHandler(event){
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html
index 084f0a0..3060fc1 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-register.html
@@ -5,18 +5,27 @@
   const scope = self.origin + '/cookies/resources/postToParent.py?with-sw';
   const script = './fetch-rewrite-worker.js';
   const reg = await navigator.serviceWorker.register(script, { scope: scope });
-  await new Promise(resolve => {
-    const worker = reg.installing;
-    worker.addEventListener('statechange', evt => {
-      if (worker.state === 'activated') {
-        resolve();
-      }
+  // In nested cases we may be impacted by partitioning or not depending on
+  // the browser.  With partitioning we will be installing a new worker here,
+  // but without partitioning the worker will already exist.  Handle both cases.
+  if (reg.installing) {
+    await new Promise(resolve => {
+      const worker = reg.installing;
+      worker.addEventListener('statechange', evt => {
+        if (worker.state === 'activated') {
+          resolve();
+        }
+      });
     });
-  });
-  if (reg.navigationPreload) {
-    await reg.navigationPreload.enable();
+    if (reg.navigationPreload) {
+      await reg.navigationPreload.enable();
+    }
   }
-  window.opener.postMessage({ type: 'SW-REGISTERED' }, '*');
+  if (window.opener) {
+    window.opener.postMessage({ type: 'SW-REGISTERED' }, '*');
+  } else {
+    window.top.postMessage({ type: 'SW-REGISTERED' }, '*');
+  }
 }
 self.addEventListener('load', onLoad);
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html
index cca3620..3a8c04d 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/same-site-cookies-unregister.html
@@ -4,8 +4,14 @@
 async function onLoad() {
   const scope = self.origin + '/cookies/resources/postToParent.py?with-sw';
   const reg = await navigator.serviceWorker.getRegistration(scope);
-  await reg.unregister();
-  window.opener.postMessage({ type: 'SW-UNREGISTERED' }, '*');
+  if (reg) {
+    await reg.unregister();
+  }
+  if (window.opener) {
+    window.opener.postMessage({ type: 'SW-UNREGISTERED' }, '*');
+  } else {
+    window.top.postMessage({ type: 'SW-UNREGISTERED' }, '*');
+  }
 }
 self.addEventListener('load', onLoad);
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/window-opener.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/window-opener.html
new file mode 100644
index 0000000..32d07446
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/window-opener.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8"/>
+<meta name="referrer" content="origin">
+<script>
+function onLoad() {
+  self.onmessage = evt => {
+    if (self.opener)
+      self.opener.postMessage(evt.data, '*');
+    else
+      self.top.postMessage(evt.data, '*');
+  }
+  const params = new URLSearchParams(self.location.search);
+  const w = window.open(params.get('target'));
+  self.addEventListener('unload', evt => w.close());
+}
+self.addEventListener('load', onLoad);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt
index c908d43..3dd2cd7 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 56 tests; 47 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 66 tests; 55 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setup service workers
 PASS same-origin, window.open with no service worker
 PASS same-origin, window.open with fallback
@@ -31,6 +31,16 @@
 PASS same-origin, window.open with passthrough, cross-site redirect, and same-origin redirect
 PASS same-origin, window.open with change-request, cross-site redirect, and same-origin redirect
 PASS same-origin, window.open with navpreload, cross-site redirect, and same-origin redirect
+PASS same-origin, nested window.open with cross-site middle frame and no service worker
+PASS same-origin, nested window.open with cross-site middle frame and fallback service worker
+PASS same-origin, nested window.open with cross-site middle frame and passthrough service worker
+PASS same-origin, nested window.open with cross-site middle frame and change-request service worker
+PASS same-origin, nested window.open with cross-site middle frame and navpreload service worker
+PASS same-origin, nested set location with cross-site middle frame and no service worker
+PASS same-origin, nested set location with cross-site middle frame and fallback service worker
+FAIL same-origin, nested set location with cross-site middle frame and passthrough service worker assert_not_equals: SameSite=Strict cookies are not sent with cross-site requests. got disallowed value "COOKIE_VALUE"
+FAIL same-origin, nested set location with cross-site middle frame and change-request service worker assert_not_equals: SameSite=Strict cookies are not sent with cross-site requests. got disallowed value "COOKIE_VALUE"
+PASS same-origin, nested set location with cross-site middle frame and navpreload service worker
 PASS same-origin, form post with no service worker
 PASS same-origin, form post with fallback
 PASS same-origin, form post with passthrough
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html
index caeadcf..6075dc83e 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html
@@ -10,9 +10,21 @@
 <body>
 <script>
 'use strict';
-async function unregister_service_worker(origin) {
-  const w = window.open(origin +
-      '/service-workers/service-worker/resources/same-site-cookies-unregister.html');
+
+function make_nested_url(nested_origins, target_url) {
+  for (let i = nested_origins.length - 1; i >= 0; --i) {
+    target_url = new URL(
+      `./resources/nested-parent.html?target=${encodeURIComponent(target_url)}`,
+      nested_origins[i] + self.location.pathname);
+  }
+  return target_url;
+}
+
+async function unregister_service_worker(origin, nested_origins=[]) {
+  let target_url = origin +
+      '/service-workers/service-worker/resources/same-site-cookies-unregister.html';
+  target_url = make_nested_url(nested_origins, target_url);
+  const w = window.open(target_url);
   try {
     await wait_for_message('SW-UNREGISTERED');
   } finally {
@@ -20,9 +32,11 @@
   }
 }
 
-async function register_service_worker(origin) {
-  const w = window.open(origin +
-      '/service-workers/service-worker/resources/same-site-cookies-register.html');
+async function register_service_worker(origin, nested_origins=[]) {
+  let target_url = origin +
+      '/service-workers/service-worker/resources/same-site-cookies-register.html';
+  target_url = make_nested_url(nested_origins, target_url);
+  const w = window.open(target_url);
   try {
     await wait_for_message('SW-REGISTERED');
   } finally {
@@ -31,7 +45,7 @@
 }
 
 async function run_test(t, origin, navaction, swaction, expected,
-                        redirect_origins=[]) {
+                        redirect_origins=[], nested_origins=[]) {
   const value = 'COOKIE_VALUE';
   await resetSameSiteCookies(origin, value);
   if (swaction === 'navpreload') {
@@ -59,23 +73,32 @@
   }
 
   if (navaction === 'window.open') {
-    const w = window.open(target_url);
-    t.add_cleanup(() => w.close());
+    target_url = new URL(
+        `./resources/window-opener.html?target=${encodeURIComponent(target_url)}`,
+        self.origin + self.location.pathname);
   } else if (navaction === 'form post') {
-    const poster_url =
-        `./resources/form-poster.html?target=${encodeURIComponent(target_url)}`;
-    const w = window.open(poster_url);
-    t.add_cleanup(() => w.close());
+    target_url = new URL(
+        `./resources/form-poster.html?target=${encodeURIComponent(target_url)}`,
+        self.origin + self.location.pathname);
+  } else if (navaction === 'set location') {
+    target_url = new URL(
+        `./resources/location-setter.html?target=${encodeURIComponent(target_url)}`,
+        self.origin + self.location.pathname);
   }
+
+  const w = window.open(make_nested_url(nested_origins, target_url));
+  t.add_cleanup(() => w.close());
+
   const result = await wait_for_message('COOKIES');
-  verifySameSiteCookieState(expected, value, result.data,
-                            DomSameSiteStatus.SAME_SITE);
+  verifySameSiteCookieState(expected, value, result.data);
 }
 
 promise_test(async t => {
   await register_service_worker(self.origin);
   await register_service_worker(SECURE_SUBDOMAIN_ORIGIN);
   await register_service_worker(SECURE_CROSS_SITE_ORIGIN);
+  await register_service_worker(self.origin,
+      [self.origin, SECURE_CROSS_SITE_ORIGIN]);
 }, 'Setup service workers');
 
 promise_test(t => {
@@ -237,6 +260,82 @@
    'same-origin redirect');
 
 //
+// Double-nested frame calling open.window() tests
+//
+promise_test(t => {
+  return run_test(t, self.origin, 'window.open', 'no-sw',
+                  SameSiteStatus.STRICT, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested window.open with cross-site middle frame and ' +
+   'no service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'window.open', 'fallback',
+                  SameSiteStatus.STRICT, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested window.open with cross-site middle frame and ' +
+   'fallback service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'window.open', 'passthrough',
+                  SameSiteStatus.STRICT, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested window.open with cross-site middle frame and ' +
+   'passthrough service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'window.open', 'change-request',
+                  SameSiteStatus.STRICT, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested window.open with cross-site middle frame and ' +
+   'change-request service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'window.open', 'navpreload',
+                  SameSiteStatus.STRICT, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested window.open with cross-site middle frame and ' +
+   'navpreload service worker');
+
+//
+// Double-nested frame setting location tests
+//
+promise_test(t => {
+  return run_test(t, self.origin, 'set location', 'no-sw',
+                  SameSiteStatus.CROSS_SITE, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested set location with cross-site middle frame and ' +
+   'no service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'set location', 'fallback',
+                  SameSiteStatus.CROSS_SITE, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested set location with cross-site middle frame and ' +
+   'fallback service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'set location', 'passthrough',
+                  SameSiteStatus.CROSS_SITE, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested set location with cross-site middle frame and ' +
+   'passthrough service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'set location', 'change-request',
+                  SameSiteStatus.CROSS_SITE, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested set location with cross-site middle frame and ' +
+   'change-request service worker');
+
+promise_test(t => {
+  return run_test(t, self.origin, 'set location', 'navpreload',
+                  SameSiteStatus.CROSS_SITE, [],
+                  [self.origin, SECURE_CROSS_SITE_ORIGIN]);
+}, 'same-origin, nested set location with cross-site middle frame and ' +
+   'navpreload service worker');
+
+//
 // Form POST tests
 //
 promise_test(t => {
@@ -379,6 +478,8 @@
   await unregister_service_worker(self.origin);
   await unregister_service_worker(SECURE_SUBDOMAIN_ORIGIN);
   await unregister_service_worker(SECURE_CROSS_SITE_ORIGIN);
+  await unregister_service_worker(self.origin,
+      [self.origin, SECURE_CROSS_SITE_ORIGIN]);
 }, 'Cleanup service workers');
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_async_script/collections.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_async_script/collections.py
index 2dc9b9a..4965771 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_async_script/collections.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_async_script/collections.py
@@ -157,3 +157,34 @@
     assert len(value) == 2
     for expected, actual in zip(ps, value):
         assert_same_element(session, expected, actual)
+
+
+def test_shadow_root(session, inline):
+    session.url = inline("""
+        <style>
+            custom-checkbox-element {
+                display:block; width:20px; height:20px;
+            }
+        </style>
+        <custom-checkbox-element></custom-checkbox-element>
+        <script>
+            customElements.define('custom-checkbox-element',
+                class extends HTMLElement {
+                    constructor() {
+                            super();
+                            this.attachShadow({mode: 'open'}).innerHTML = `
+                                <div><input type="checkbox"/></div>
+                            `;
+                        }
+                });
+        </script>""")
+    custom_element = session.find.css("custom-checkbox-element", all=False)
+    expected = custom_element.shadow_root
+    response = execute_async_script(session, """
+        let resolve = arguments[0];
+        resolve(document.querySelector('custom-checkbox-element').shadowRoot);
+        """)
+    value = assert_success(response)
+    assert isinstance(value, dict)
+    assert "shadow-6066-11e4-a52e-4f735466cecf" in value
+    assert value["shadow-6066-11e4-a52e-4f735466cecf"] == expected.id
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_script/collections.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_script/collections.py
index 8291fd7..4d88d497 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_script/collections.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/execute_script/collections.py
@@ -135,3 +135,32 @@
     assert len(value) == 2
     for expected, actual in zip(ps, value):
         assert_same_element(session, expected, actual)
+
+
+def test_shadow_root(session, inline):
+    session.url = inline("""
+        <style>
+            custom-checkbox-element {
+                display:block; width:20px; height:20px;
+            }
+        </style>
+        <custom-checkbox-element></custom-checkbox-element>
+        <script>
+            customElements.define('custom-checkbox-element',
+                class extends HTMLElement {
+                    constructor() {
+                            super();
+                            this.attachShadow({mode: 'open'}).innerHTML = `
+                                <div><input type="checkbox"/></div>
+                            `;
+                        }
+                });
+        </script>""")
+    custom_element = session.find.css("custom-checkbox-element", all=False)
+    expected = custom_element.shadow_root
+    response = execute_script(session,
+        "return document.querySelector('custom-checkbox-element').shadowRoot")
+    value = assert_success(response)
+    assert isinstance(value, dict)
+    assert "shadow-6066-11e4-a52e-4f735466cecf" in value
+    assert value["shadow-6066-11e4-a52e-4f735466cecf"] == expected.id
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/clip/control-clip-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/clip/control-clip-expected.txt
deleted file mode 100644
index fbe3f23..0000000
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/clip/control-clip-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "invalidations": [
-        [76, 117, 64, 16],
-        [9, 87, 63, 16]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt b/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt
deleted file mode 100644
index abdeffb..0000000
--- a/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-CONSOLE ERROR: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match.
-CONSOLE ERROR: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match.
-
-
---------
-Frame: 'childFrame'
---------
-This tests that plugins can access objects in other frames as allowed by the security model enforced in WebCore.
-Error: Error: Failed conversion between PP_Var and V8 value
-Error: Uncaught
-Error: Error: Failed conversion between PP_Var and V8 value
-Error: Uncaught
-SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access.html b/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access.html
deleted file mode 100644
index 2df91ca..0000000
--- a/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<html>
-<head>
-<script>
-if (window.testRunner) {
-    testRunner.dumpAsText();
-    testRunner.dumpChildFrames();
-}
-</script>
-<iframe name="childFrame" src="http://localhost:8000/plugins/resources/cross-frame-object-access.html"></iframe>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/http/tests/plugins/resources/cross-frame-object-access.html b/third_party/blink/web_tests/http/tests/plugins/resources/cross-frame-object-access.html
deleted file mode 100644
index 57debbc7..0000000
--- a/third_party/blink/web_tests/http/tests/plugins/resources/cross-frame-object-access.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<html>
-<head>
-<script>
-function debug(str)
-{
-    var li = document.createElement('li');
-    li.appendChild(document.createTextNode(str));
-    document.getElementById('console').appendChild(li)
-}
-
-function checkLocationObject(l)
-{
-    if (!l) {
-        debug('could not access top.location');
-        return false;
-    }
-
-    try {
-        if (l.href) {
-            debug('could access top.location.href');
-            return false;
-        }
-    } catch (e) {
-        return true;
-    }
-    return true;
-}
-
-function getPlugin()
-{
-    return document.querySelector('embed');
-}
-
-function runTest()
-{
-    var numErrors = 0;
-
-    // Try accessing childFrame.location using NPN_Evaluate
-    var l = getPlugin().testExecuteScript('top.location')
-    if (!checkLocationObject(l))
-        numErrors++;
-
-    // Try getting childFrame.location.href using NPN_Evaluate
-    try {
-        var href = getPlugin().testExecuteScript('top.location.href');
-    } catch (e) {
-        debug(e);
-    }
-    if (href) {
-        debug("could access top.location.href")
-        numErrors++;
-    }
-
-    // Try accessing childFrame.location using NPN_GetProperty
-    var l = getPlugin().testGetProperty('top', 'location');
-    if (!checkLocationObject(l))
-        numErrors++;
-
-    try {
-        var href = getPlugin().testGetProperty('top', 'location', 'href');
-    } catch (e) {
-        debug(e);
-    }
-    if (href) {
-        debug("could access top.location.href")
-        numErrors++;
-    }
-
-    // Try accessing top.document using NPN_EVALUATE
-    try {
-        var documentViaTestEvaluate = getPlugin().testExecuteScript('top.document')
-    } catch (e) {
-        debug(e);
-    };
-    if (documentViaTestEvaluate) {
-        debug('could access top.document');
-        numErrors++;
-    }
-
-    // Try accessing top.document using NPN_GetProperty
-    try {
-        var documentViaTestGetProperty = getPlugin().testGetProperty('top', 'document')
-    } catch (e) {
-        debug(e);
-    };
-    if (documentViaTestGetProperty) {
-        debug('could access top.document');
-        numErrors++;
-    }
-
-    if (numErrors == 0)
-        document.getElementById('result').innerHTML = 'SUCCESS';
-}
-</script>
-</head>
-<body onload="runTest()">
-<embed type="application/x-blink-deprecated-test-plugin"></embed>
-<div>This tests that plugins can access objects in other frames as allowed by the security model enforced in WebCore.</div>
-<ul id="console">
-</ul>
-<div id="result">FAILURE</div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-painting-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-painting-expected.png
index 35639f9..387250e5 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-painting-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-painting-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index 73f2471..c326cb58 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/inline/inline-box-background-repeat-x-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/inline/inline-box-background-repeat-x-expected.png
index 779e1e30..423f172 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/inline/inline-box-background-repeat-x-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/inline/inline-box-background-repeat-x-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/writing-mode/english-lr-text-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/writing-mode/english-lr-text-expected.png
index a83d45d..a035983 100644
--- a/third_party/blink/web_tests/platform/fuchsia/fast/writing-mode/english-lr-text-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/fast/writing-mode/english-lr-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/paint/invalidation/shadow-multiple-expected.png b/third_party/blink/web_tests/platform/fuchsia/paint/invalidation/shadow-multiple-expected.png
index 1d1ad9f..e0d059be 100644
--- a/third_party/blink/web_tests/platform/fuchsia/paint/invalidation/shadow-multiple-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/paint/invalidation/shadow-multiple-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png
index 53c1a2ed..5c14728 100644
--- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug8950-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug8950-expected.png
index 251b9fe..2b0ea0b1 100644
--- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug8950-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug8950-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/transforms/transformed-caret-expected.png b/third_party/blink/web_tests/platform/fuchsia/transforms/transformed-caret-expected.png
index 0f6e33a..5f946565 100644
--- a/third_party/blink/web_tests/platform/fuchsia/transforms/transformed-caret-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/transforms/transformed-caret-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/virtual/text-antialias/stroking-decorations-expected.png b/third_party/blink/web_tests/platform/fuchsia/virtual/text-antialias/stroking-decorations-expected.png
index 8b004ad..f8c4de0f 100644
--- a/third_party/blink/web_tests/platform/fuchsia/virtual/text-antialias/stroking-decorations-expected.png
+++ b/third_party/blink/web_tests/platform/fuchsia/virtual/text-antialias/stroking-decorations-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/plugins/focus-change-1-no-change-expected.txt b/third_party/blink/web_tests/platform/linux/plugins/focus-change-1-no-change-expected.txt
deleted file mode 100644
index 4ba4aed..0000000
--- a/third_party/blink/web_tests/platform/linux/plugins/focus-change-1-no-change-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-CONSOLE MESSAGE: Blink Test Plugin: initializing
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(false)
-i1focus
-i1blur
-pfocus
-pblur
-i2focus
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Test no change of focus inside plugin onfocus and onblur events
-
-  
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/plugins/focus-change-1-no-change-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/plugins/focus-change-1-no-change-expected.txt
deleted file mode 100644
index 4ba4aed..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/plugins/focus-change-1-no-change-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-CONSOLE MESSAGE: Blink Test Plugin: initializing
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(false)
-i1focus
-i1blur
-pfocus
-pblur
-i2focus
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Test no change of focus inside plugin onfocus and onblur events
-
-  
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt
deleted file mode 100644
index e08d8be7..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Content-Type: text/plain
-This is a testharness.js-based test.
-FAIL href assert_equals: expected "http://web-platform.test:8001/common/blank.html?thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
-FAIL search assert_equals: expected "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.search%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
-FAIL hash assert_equals: expected "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.hash%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20#thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.hash%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
-Harness: the test ran to completion.
-
-#EOF
-#EOF
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/scroll-unification/plugins/focus-change-1-no-change-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/scroll-unification/plugins/focus-change-1-no-change-expected.txt
deleted file mode 100644
index 4ba4aed..0000000
--- a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/scroll-unification/plugins/focus-change-1-no-change-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-CONSOLE MESSAGE: Blink Test Plugin: initializing
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(false)
-i1focus
-i1blur
-pfocus
-pblur
-i2focus
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Test no change of focus inside plugin onfocus and onblur events
-
-  
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt
index e08d8be7..636b5cbd 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-click-expected.txt
@@ -1,9 +1,6 @@
-Content-Type: text/plain
 This is a testharness.js-based test.
 FAIL href assert_equals: expected "http://web-platform.test:8001/common/blank.html?thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
 FAIL search assert_equals: expected "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.search%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
 FAIL hash assert_equals: expected "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.hash%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20#thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onclick%20%3D%20()%20%3D%3E%20%7B%20location.hash%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
 Harness: the test ran to completion.
 
-#EOF
-#EOF
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup-expected.txt
index 60f94000..4eecf2b 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/location-setter-user-mouseup-expected.txt
@@ -1,9 +1,6 @@
-Content-Type: text/plain
 This is a testharness.js-based test.
 FAIL href assert_equals: expected "http://web-platform.test:8001/common/blank.html?thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onmouseup%20%3D%20()%20%3D%3E%20%7B%20location.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
 FAIL search assert_equals: expected "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onmouseup%20%3D%20()%20%3D%3E%20%7B%20location.search%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
 FAIL hash assert_equals: expected "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onmouseup%20%3D%20()%20%3D%3E%20%7B%20location.hash%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20#thereplacement" but got "http://web-platform.test:8001/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/slow-code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20button%20%3D%20document.createElement(%22button%22)%3B%0A%20%20%20%20button.id%20%3D%20%22the-button%22%3B%0A%20%20%20%20button.textContent%20%3D%20%22needs%20to%20have%20content%20to%20be%20clickable%22%3B%0A%20%20%20%20button.onmouseup%20%3D%20()%20%3D%3E%20%7B%20location.hash%20%3D%20%22thereplacement%22%3B%20%7D%3B%0A%20%20%20%20document.currentScript.before(button)%3B%0A%20%20%20%20parent.test_driver.click(button)%3B%0A%20%20"
 Harness: the test ran to completion.
 
-#EOF
-#EOF
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/clip/control-clip-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/clip/control-clip-expected.txt
index dde4aa6..acd5dc97c 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/clip/control-clip-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/clip/control-clip-expected.txt
@@ -6,8 +6,8 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [75, 114, 66, 15],
-        [9, 84, 65, 15]
+        [8, 76, 200, 30],
+        [75, 114, 66, 15]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/clip/control-clip-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/clip/control-clip-expected.txt
index fbe3f23..ee88af3 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/clip/control-clip-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/clip/control-clip-expected.txt
@@ -6,8 +6,8 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [76, 117, 64, 16],
-        [9, 87, 63, 16]
+        [8, 80, 200, 30],
+        [76, 117, 64, 16]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/plugins/focus-change-1-no-change-expected.txt b/third_party/blink/web_tests/plugins/focus-change-1-no-change-expected.txt
deleted file mode 100644
index 4ba4aed..0000000
--- a/third_party/blink/web_tests/plugins/focus-change-1-no-change-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-CONSOLE MESSAGE: Blink Test Plugin: initializing
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(false)
-i1focus
-i1blur
-pfocus
-pblur
-i2focus
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Test no change of focus inside plugin onfocus and onblur events
-
-  
diff --git a/third_party/blink/web_tests/plugins/focus-change-1-no-change.html b/third_party/blink/web_tests/plugins/focus-change-1-no-change.html
index d4008fc..6ba354b4 100644
--- a/third_party/blink/web_tests/plugins/focus-change-1-no-change.html
+++ b/third_party/blink/web_tests/plugins/focus-change-1-no-change.html
@@ -1,27 +1,31 @@
-<script src="../resources/js-test.js"></script>
-<p>Test no change of focus inside plugin onfocus and onblur events</p>
-<input id="input1" type="text" onfocus="i1Focus()" onblur="i1Blur()"></input>
-<input id="input2" type="text" onfocus="i2Focus()" onblur="i2Blur()"></input>
+
+<!DOCTYPE html>
+<title>Test no change of focus inside plugin onfocus and onblur events</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<input id="input1" type="text" onfocus="i1Focus()" onblur="i1Blur()">
+<input id="input2" type="text" onfocus="i2Focus()" onblur="i2Blur()">
 <embed id="plugin" type="application/x-blink-test-plugin" onfocus="pFocus()" onblur="pBlur()"></embed>
+
 <script>
-function i1Focus() { debug('i1focus'); }
-function i1Blur() { debug('i1blur'); }
-function i2Focus() { debug('i2focus'); }
-function i2Blur() { debug('i2blur'); }
-function pFocus() { debug('pfocus'); }
-function pBlur() { debug('pblur'); }
+let events = [];
+function i1Focus() { events.push('i1focus'); }
+function i1Blur() { events.push('i1blur'); }
+function i2Focus() { events.push('i2focus'); }
+function i2Blur() { events.push('i2blur'); }
+function pFocus() { events.push('pfocus'); }
+function pBlur() { events.push('pblur'); }
 
-if (testRunner)
-  testRunner.waitUntilDone();
+async_test(t => {
+  function finish() {
+    assert_array_equals(events, ["i1focus","i1blur","pfocus","pblur","i2focus"]);
+    t.done();
+  }
+  document.getElementById('input1').focus();
+  document.getElementById('plugin').focus();
+  document.getElementById('input2').focus();
 
-document.getElementById('input1').focus();
-document.getElementById('plugin').focus();
-document.getElementById('input2').focus();
-
-setTimeout(
-    function() {
-      if (testRunner)
-        testRunner.notifyDone();
-    },
-    0);
+  t.step_timeout(finish, 0);
+},"Test plugin focus behavior");
 </script>
diff --git a/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur-expected.txt b/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur-expected.txt
deleted file mode 100644
index e669345d..0000000
--- a/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-CONSOLE MESSAGE: Blink Test Plugin: initializing
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(false)
-i1focus
-i1blur
-pfocus-change-2
-pblur-change-4
-i4focus
-i4blur
-i3focus
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Test changing focus inside plugin onfocus and onblur events
-
-    
diff --git a/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur.html b/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur.html
index bb41ab98..6b11b8a 100644
--- a/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur.html
+++ b/third_party/blink/web_tests/plugins/focus-change-4-change-focus-and-blur.html
@@ -1,39 +1,43 @@
-<script src="../resources/js-test.js"></script>
-<p>Test changing focus inside plugin onfocus and onblur events</p>
+<!doctype html>
+<title>Test changing focus inside plugin onfocus and onblur events</title>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
 <input id="input1" type="text" onfocus="i1Focus()" onblur="i1Blur()"></input>
 <input id="input2" type="text" onfocus="i2Focus()" onblur="i2Blur()"></input>
 <input id="input3" type="text" onfocus="i3Focus()" onblur="i3Blur()"></input>
 <input id="input4" type="text" onfocus="i4Focus()" onblur="i4Blur()"></input>
 <embed id="plugin" type="application/x-blink-test-plugin" onfocus="pFocus()" onblur="pBlur()"></embed>
+
 <script>
-function i1Focus() { debug('i1focus'); }
-function i1Blur() { debug('i1blur'); }
-function i2Focus() { debug('i2focus'); }
-function i2Blur() { debug('i2blur'); }
-function i3Focus() { debug('i3focus'); } 
-function i3Blur() { debug('i3blur'); }
-function i4Focus() { debug('i4focus'); } 
-function i4Blur() { debug('i4blur'); }
+let events = [];
+function i1Focus() { events.push('i1focus'); }
+function i1Blur() { events.push('i1blur'); }
+function i2Focus() { events.push('i2focus'); }
+function i2Blur() { events.push('i2blur'); }
+function i3Focus() { events.push('i3focus'); } 
+function i3Blur() { events.push('i3blur'); }
+function i4Focus() { events.push('i4focus'); } 
+function i4Blur() { events.push('i4blur'); }
 function pFocus() {
-  debug('pfocus-change-2');
+  events.push('pfocus-change-2');
   document.getElementById('input2').focus();
 }
 function pBlur() {
-  debug('pblur-change-4');
+  events.push('pblur-change-4');
   document.getElementById('input4').focus();
 }
 
-if (testRunner)
-  testRunner.waitUntilDone();
+async_test(t => {
+  function finish() {
+    assert_array_equals(events, ["i1focus","i1blur","pfocus-change-2","pblur-change-4","i4focus","i4blur","i3focus"]);
+    t.done();
+  }
+  document.getElementById('input1').focus();
+  document.getElementById('plugin').focus();
+  document.getElementById('input3').focus();
 
-document.getElementById('input1').focus();
-document.getElementById('plugin').focus();
-document.getElementById('input3').focus();
+  t.step_timeout(finish, 0);
+},"Test plugin focus behavior");
 
-setTimeout(
-    function() {
-      if (testRunner)
-        testRunner.notifyDone();
-    },
-    0);
 </script>
diff --git a/third_party/blink/web_tests/virtual/scroll-unification/plugins/focus-change-4-change-focus-and-blur-expected.txt b/third_party/blink/web_tests/virtual/scroll-unification/plugins/focus-change-4-change-focus-and-blur-expected.txt
deleted file mode 100644
index e669345d..0000000
--- a/third_party/blink/web_tests/virtual/scroll-unification/plugins/focus-change-4-change-focus-and-blur-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-CONSOLE MESSAGE: Blink Test Plugin: initializing
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(true)
-CONSOLE MESSAGE: Blink Test Plugin: DidChangeFocus(false)
-i1focus
-i1blur
-pfocus-change-2
-pblur-change-4
-i4focus
-i4blur
-i3focus
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Test changing focus inside plugin onfocus and onblur events
-
-    
diff --git a/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https-expected.txt b/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https-expected.txt
new file mode 100644
index 0000000..516319b0
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/service-workers/service-worker/partitioned-service-worker-claim.tentative.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+PASS ServiceWorker's clients.claim() is partitioned
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/permission-geolocation.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/permission-geolocation.https.html
new file mode 100644
index 0000000..6c3aff29
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/permission-geolocation.https.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<title>Test permission of geolocation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+
+<script>
+
+async function runTest(policy_header_in_primary_page,
+                       policy_header_in_fenced_frame_page,
+                       allow_attribute_iframe_in_fanced_frame) {
+  const pipe_for_policy = 'pipe=header(Permissions-Policy,geolocation=self)';
+  const test_runner_url =
+      'resources/permission-geolocation-test-runner.html?' +
+      (policy_header_in_primary_page ? pipe_for_policy : '');
+  let fenced_frame_url_params = [];
+  if (policy_header_in_fenced_frame_page) {
+    fenced_frame_url_params.push(pipe_for_policy);
+  }
+  if (allow_attribute_iframe_in_fanced_frame) {
+    fenced_frame_url_params.push('load_allow_attribute_iframe=true');
+  }
+  const fenced_frame_url =
+      'permission-geolocation-inner.html?' +
+      fenced_frame_url_params.join('&');
+
+  const win = window.open(test_runner_url);
+  await new Promise(resolve => {
+    win.onload = resolve;
+  });
+
+  const unloadPromise = new Promise(resolve => {
+    win.onunload = resolve;
+  });
+
+  await win.runTest(fenced_frame_url);
+  win.close();
+  await unloadPromise;
+}
+
+promise_test(async t => {
+  await runTest(false, false, false);
+}, 'geolocation permission is not permitted for fenced frames');
+
+promise_test(async t => {
+  await runTest(true, false, false);
+}, 'geolocation permission is not permitted for fenced frames, even if a ' +
+   '`Permissions-Policy` header is sent on the primary page.');
+
+promise_test(async t => {
+  await runTest(false, true, false);
+}, 'geolocation permission is not permitted for fenced frames, even if a ' +
+   '`Permissions-Policy` header is sent on the fenced frame response.');
+
+promise_test(async t => {
+  await runTest(false, false, true);
+}, 'geolocation permission is not permitted for fenced frames, even if an ' +
+   '`allow` attribute is set for an iframe in the fenced frame.');
+
+promise_test(async t => {
+  await runTest(false, true, true);
+}, 'geolocation permission is not permitted for fenced frames, even if a ' +
+   '`Permissions-Policy` header and an `allow` attribute is set for an iframe' +
+   ' in the fenced frame.');
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-inner.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-inner.html
new file mode 100644
index 0000000..dc9f30c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-inner.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="utils.js"></script>
+<title>Fenced frame content to report the result of navigator.geolocation.getCurrentPosition()</title>
+
+<body>
+<script>
+(async () => {
+  const permission_geolocation_key = KEYS['permission.geolocation'];
+  const result = await new Promise(resolve => {
+    navigator.geolocation.getCurrentPosition(
+        () => resolve('granted'), () => resolve('denied'));
+  });
+  writeValueToServer(permission_geolocation_key, `result: ${result}`);
+})();
+</script>
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-inner.html.headers b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-inner.html.headers
new file mode 100644
index 0000000..1b63235
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-inner.html.headers
@@ -0,0 +1 @@
+Supports-Loading-Mode: fenced-frame
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-test-runner.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-test-runner.html
new file mode 100644
index 0000000..68875a3
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/permission-geolocation-test-runner.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Fenced frame content to report the result of navigator.geolocation.getCurrentPosition()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="utils.js"></script>
+
+<body>
+<script>
+
+window.runTest = async (fenced_frame_url) => {
+  const permission_geolocation_key = KEYS['permission.geolocation'];
+  await test_driver.set_permission({name: 'geolocation'}, 'granted', true);
+
+  attachFencedFrame(fenced_frame_url);
+  const actual_result = await nextValueFromServer(permission_geolocation_key);
+
+  assert_equals(
+      actual_result, 'result: denied',
+      'geolocation permission is not permitted for fenced frames.');
+};
+</script>
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js
index 9c402da4..29da0ed1 100644
--- a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/utils.js
@@ -63,6 +63,8 @@
 
   "popup_noopener"                              : "00000000-0000-0000-0000-00000000001E",
   "popup_openee"                                : "00000000-0000-0000-0000-00000000001F",
+
+  "permission.geolocation"                      : "00000000-0000-0000-0000-000000000020",
   // Add keys above this list, incrementing the key UUID in hexadecimal
 }
 
diff --git a/third_party/blink/web_tests/wpt_internal/fragment-directive/scroll-to-selector-fragment-target.html b/third_party/blink/web_tests/wpt_internal/fragment-directive/scroll-to-selector-fragment-target.html
new file mode 100644
index 0000000..62d06b0
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fragment-directive/scroll-to-selector-fragment-target.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<title>Navigating to a selector fragment anchor</title>
+<script src="stash.js"></script>
+<script>
+function isInView(element) {
+  let rect = element.getBoundingClientRect();
+  return rect.top >= 0 && rect.top <= window.innerHeight
+      && rect.left >= 0 && rect.left <= window.innerWidth;
+}
+
+function checkScroll() {
+  let position = 'unknown';
+  if (window.scrollY === 0)
+    position = 'top';
+  else if (isInView(document.getElementById('some-text')))
+    position = 'some-text';
+  else if (isInView(document.getElementById('cat')))
+    position = 'cat';
+  else if (isInView(document.getElementById('some-other-text')))
+    position = 'some-other-text';
+  else if (isInView(document.getElementById('input-button')))
+    position = 'input-button';
+  else if (isInView(document.getElementById('more-text-goes-here')))
+    position = 'more-text-goes-here';
+
+  let target = document.querySelector(":target");
+
+  let results = {
+    scrollPosition: position,
+    href: window.location.href,
+    target: target ? target.id : 'undefined'
+  };
+
+  let key = (new URL(document.location)).searchParams.get("key");
+  stashResultsThenClose(key, results);
+}
+
+window.onload = function() {
+  window.requestAnimationFrame(checkScroll)
+}
+</script>
+<body>
+  <div id='some-text' style='height:600px;'>some text</div>
+  <svg id='cat' width='200' height='200' xmlns='http://www.w3.org/2000/svg'>
+    <circle class='path' cx='100' cy='100' r='100' fill='red'/>
+  </svg>
+  <div id='some-other-text' style='height:600px;'>some other text</div>
+  <input id='input-button' type="button" value="Add to favorites">
+  <div id='more-text-goes-here' style='height:600px;'>more text goes here</div>
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fragment-directive/scroll-to-selector-fragment.html b/third_party/blink/web_tests/wpt_internal/fragment-directive/scroll-to-selector-fragment.html
new file mode 100644
index 0000000..2ffda17
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fragment-directive/scroll-to-selector-fragment.html
@@ -0,0 +1,119 @@
+<!doctype html>
+<title>Navigating to a selector fragment directive</title>
+<meta charset=utf-8>
+<link rel="help" href="https://github.com/WICG/scroll-to-text-fragment/blob/main/EXTENSIONS.md#proposed-solution">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/common/utils.js"></script>
+<script src="stash.js"></script>
+<!--
+  This test suite performs scroll to selector navigations to
+  scroll-to-selector-fragment-target.html and then checks the results, which are
+  communicated back from the target page via the WPT Stash server (see stash.py).
+-->
+<script>
+let test_cases = [
+  {
+    description: 'Basic selector test',
+    fragment: '#:~:selector(type=CssSelector,value=svg[id=cat])',
+    expect_position: 'cat'
+  },
+  {
+    description: 'value= comes before type=',
+    fragment: '#:~:selector(value=svg[id=cat],type=CssSelector)',
+    expect_position: 'cat'
+  },
+  {
+    description: 'Invalid selector directive 1',
+    fragment: '#:~:selector(ignorethisvalue=type=)',
+    expect_position: 'top'
+  },
+  {
+    description: 'Invalid selector directive 2',
+    fragment: '#:~:selector()',
+    expect_position: 'top'
+  },
+  {
+    description: 'Invalid selector directive 3',
+    fragment: '#:~:selector(type=,value=)',
+    expect_position: 'top'
+  },
+  {
+    description: 'Invalid selector directive 4',
+    fragment: '#:~:selector(value=,type=)',
+    expect_position: 'top'
+  },
+  {
+    description: 'Value is empty, technically a valid selector, though it wouldn\'t select antyhing',
+    fragment: '#:~:selector(value=,type=CssSelector)',
+    expect_position: 'top'
+  },
+  {
+    description: 'There is a type= in css selector value',
+    fragment: '#:~:selector(value=input[type=button],type=CssSelector)',
+    expect_position: 'input-button'
+  },
+  {
+    description: 'There is a type= in css selector value, value is URLEncoded',
+    // fragment: '#:~:selector(value=input[type=button],type=CssSelector)',
+    fragment: '#:~:selector(value=input%5Btype%3Dbutton%5D,type=CssSelector)',
+    expect_position: 'input-button'
+  },
+  {
+    description: 'Should parse 2 selector directives',
+    fragment: '#:~:selector(type=CssSelector,value=svg[id=cat])&selector(type=CssSelector,value=input[type=button])',
+    expect_position: 'cat'
+  },
+  {
+    description: 'Ignore other parts, only parse type= and value=',
+    fragment: '#:~:selector(type=CssSelector,lorem_part,value=svg[id=cat])',
+    expect_position: 'cat'
+  },
+  {
+    description: 'Don\'t accept ambiguous directive, don\'t allow two type= parts',
+    fragment: '#:~:selector(type=CssSelector,type=SomethingElse,value=svg[id=cat])',
+    expect_position: 'top'
+  },
+  {
+    description: 'Don\'t accept ambiguous directive, don\'t allow two value= parts',
+    fragment: '#:~:selector(type=CssSelector,value=input[type=button],value=svg[id=cat])',
+    expect_position: 'top'
+  },
+  // {
+  //   description: 'a comma in value= part should be encoded',
+  //   fragment: '#:~:selector(value=svg[id%3Dcat%2Cdog],type=CssSelector)',
+  //   expect_position: 'cat'
+  // },
+  {
+    description: 'Should not allow multiple value= parts v1',
+    fragment: '#:~:selector(value=,type=CssSelector,value=img) ',
+    expect_position: 'top'
+  },
+  {
+    description: 'Should not allow multiple value= parts v2',
+    fragment: '#:~:selector(value=img,value=,type=CssSelector) ',
+    expect_position: 'top'
+  }
+];
+
+for (const test_case of test_cases) {
+  promise_test(t => new Promise((resolve, reject) => {
+    let key = token();
+
+    test_driver.bless('Open a URL with a selector fragment directive', () => {
+      window.open(`scroll-to-selector-fragment-target.html?key=${key}${test_case.fragment}`, '_blank', 'noopener');
+    });
+
+    fetchResults(key, resolve, reject);
+  }).then(data => {
+    // If the position is not 'top', the :target element should be the positioned element.
+    assert_true(data.scrollPosition == 'top' || data.target == data.scrollPosition);
+    assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
+    assert_equals(data.scrollPosition, test_case.expect_position,
+                  `Expected ${test_case.fragment} (${test_case.description}) to scroll to ${test_case.expect_position}.`);
+  }), `Test navigation with fragment: ${test_case.description}.`);
+}
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/fragment-directive/selector-directive-check-parsing.html b/third_party/blink/web_tests/wpt_internal/fragment-directive/selector-directive-check-parsing.html
new file mode 100644
index 0000000..56362a9
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fragment-directive/selector-directive-check-parsing.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<title>Tests the SelectorDirective type in fragmentDirective</title>
+<meta charset='utf-8'>
+<link rel='help' href='https://github.com/WICG/scroll-to-text-fragment/blob/main/EXTENSIONS.md'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<style>
+</style>
+<body>
+  <div style='height:600px;'>some text</div>
+  <svg id='cat' width='200' height='200' xmlns='http://www.w3.org/2000/svg'>
+    <circle class='path' cx='100' cy='100' r='100' fill='red'/>
+  </svg>
+  <div style='height:600px;'>some other text</div>
+  <input type="button" value="Add to favorites">
+  <div style='height:600px;'>more text goes here</div>
+
+  <script>
+    function reset() {
+      window.location.hash = ':~:thiswillclear';
+      assert_equals(document.fragmentDirective.items.length, 0,
+                    '[PRECONDITION] reset cleared directives');
+    }
+
+    const test_cases = [
+      {
+        name: 'Basic selector test',
+        directive: ':~:selector(type=CssSelector,value=svg[id=cat])',
+        number_successfully_parsed: 1
+      },
+      {
+        name: 'value= comes before type=',
+        directive: ':~:selector(value=svg[id=cat],type=CssSelector)',
+        number_successfully_parsed: 1
+      },
+      {
+        name: 'Invalid selector directive 1',
+        directive: ':~:selector(ignorethisvalue=type=)',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Invalid selector directive 2',
+        directive: ':~:selector()',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Invalid selector directive 3',
+        directive: ':~:selector(type=,value=)',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Invalid selector directive 4',
+        directive: ':~:selector(value=,type=)',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Value is empty, technically a valid selector, though it wouldn\'t select antyhing',
+        directive: ':~:selector(value=,type=CssSelector)',
+        number_successfully_parsed: 1
+      },
+      {
+        name: 'There is a type= in css selector value',
+        directive: ':~:selector(value=input[type=button],type=CssSelector)',
+        number_successfully_parsed: 1
+      },
+      {
+        name: 'There is a type= in css selector value, value is URLEncoded',
+        // directive: ':~:selector(value=input[type=button],type=CssSelector)',
+        directive: ':~:selector(value=input%5Btype%3Dbutton%5D,type=CssSelector)',
+        number_successfully_parsed: 1
+      },
+      {
+        name: 'Should parse 2 selector directives',
+        directive: ':~:selector(type=CssSelector,value=svg[id=cat])&selector(type=CssSelector,value=input[type=button])',
+        number_successfully_parsed: 2
+      },
+      {
+        name: 'Ignore other parts, only parse type= and value=',
+        directive: ':~:selector(type=CssSelector,lorem_part,value=svg[id=cat])',
+        number_successfully_parsed: 1
+      },
+      {
+        name: 'Don\'t accept ambiguous directive, don\'t allow two type= parts',
+        directive: ':~:selector(type=CssSelector,type=SomethingElse,value=svg[id=cat])',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Don\'t accept ambiguous directive, don\'t allow two value= parts',
+        directive: ':~:selector(type=CssSelector,value=input[type=button],value=svg[id=cat])',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Should not allow multiple value= parts v1',
+        directive: ':~:selector(value=,type=CssSelector,value=img) ',
+        number_successfully_parsed: 0
+      },
+      {
+        name: 'Should not allow multiple value= parts v2',
+        directive: ':~:selector(value=img,value=,type=CssSelector) ',
+        number_successfully_parsed: 0
+      }
+    ];
+
+    onload = () => {
+      for (let test_case of test_cases) {
+        promise_test(async (t) => {
+          reset();
+
+          window.location.hash = test_case.directive;
+          assert_equals(document.fragmentDirective.items.length,
+                        test_case.number_successfully_parsed,
+                        'Expected number of selector directives parsed successfully.');
+        }, test_case.name);
+      }
+    };
+  </script>
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/fragment-directive/stash.js b/third_party/blink/web_tests/wpt_internal/fragment-directive/stash.js
new file mode 100644
index 0000000..f1b2ea8
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fragment-directive/stash.js
@@ -0,0 +1,29 @@
+// Put test results into Stash
+function stashResultsThenClose(key, results) {
+  fetch(`/scroll-to-text-fragment/stash.py?key=${key}`, {
+    method: 'POST',
+    body: JSON.stringify(results)
+  }).then(() => {
+    window.close();
+  });
+}
+
+// Fetch test results from the Stash
+function fetchResults(key, resolve, reject) {
+  fetch(`/scroll-to-text-fragment/stash.py?key=${key}`).then(response => {
+    return response.text();
+  }).then(text => {
+    if (text) {
+      try {
+        const results = JSON.parse(text);
+        resolve(results);
+      } catch(e) {
+        reject();
+      }
+    } else {
+      // We keep trying to fetch results as the target page may not have stashed
+      // them yet.
+      fetchResults(key, resolve, reject);
+    }
+  });
+}
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index cf39fbd..fed3f02 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -254,7 +254,6 @@
   "src/crypto/x509v3/internal.h",
   "src/crypto/x509v3/pcy_cache.c",
   "src/crypto/x509v3/pcy_data.c",
-  "src/crypto/x509v3/pcy_int.h",
   "src/crypto/x509v3/pcy_lib.c",
   "src/crypto/x509v3/pcy_map.c",
   "src/crypto/x509v3/pcy_node.c",
diff --git a/third_party/boringssl/BUILD.generated_tests.gni b/third_party/boringssl/BUILD.generated_tests.gni
index ea4709f..20a4212d 100644
--- a/third_party/boringssl/BUILD.generated_tests.gni
+++ b/third_party/boringssl/BUILD.generated_tests.gni
@@ -193,6 +193,13 @@
   "src/crypto/x509/test/some_names1.pem",
   "src/crypto/x509/test/some_names2.pem",
   "src/crypto/x509/test/some_names3.pem",
+  "src/crypto/x509/test/trailing_data_leaf_authority_key_identifier.pem",
+  "src/crypto/x509/test/trailing_data_leaf_basic_constraints.pem",
+  "src/crypto/x509/test/trailing_data_leaf_ext_key_usage.pem",
+  "src/crypto/x509/test/trailing_data_leaf_key_usage.pem",
+  "src/crypto/x509/test/trailing_data_leaf_name_constraints.pem",
+  "src/crypto/x509/test/trailing_data_leaf_subject_alt_name.pem",
+  "src/crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem",
   "src/third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
   "src/third_party/wycheproof_testvectors/aes_cmac_test.txt",
   "src/third_party/wycheproof_testvectors/aes_gcm_siv_test.txt",
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c
index 4f4e973..98bc22a4 100644
--- a/third_party/boringssl/err_data.c
+++ b/third_party/boringssl/err_data.c
@@ -55,185 +55,185 @@
 OPENSSL_STATIC_ASSERT(ERR_NUM_LIBS == 34, "number of libraries changed");
 
 const uint32_t kOpenSSLReasonValues[] = {
-    0xc320847,
-    0xc328861,
-    0xc330870,
-    0xc338880,
-    0xc34088f,
-    0xc3488a8,
-    0xc3508b4,
-    0xc3588d1,
-    0xc3608f1,
-    0xc3688ff,
-    0xc37090f,
-    0xc37891c,
-    0xc38092c,
-    0xc388937,
-    0xc39094d,
-    0xc39895c,
-    0xc3a0970,
-    0xc3a8854,
+    0xc320862,
+    0xc32887c,
+    0xc33088b,
+    0xc33889b,
+    0xc3408aa,
+    0xc3488c3,
+    0xc3508cf,
+    0xc3588ec,
+    0xc36090c,
+    0xc36891a,
+    0xc37092a,
+    0xc378937,
+    0xc380947,
+    0xc388952,
+    0xc390968,
+    0xc398977,
+    0xc3a098b,
+    0xc3a886f,
     0xc3b00f7,
-    0xc3b88e3,
-    0x10320854,
-    0x103295ca,
-    0x103315d6,
-    0x103395ef,
-    0x10341602,
-    0x10348f34,
-    0x10350c6d,
-    0x10359615,
-    0x1036163f,
-    0x10369652,
-    0x10371671,
-    0x1037968a,
-    0x1038169f,
-    0x103896bd,
-    0x103916cc,
-    0x103996e8,
-    0x103a1703,
-    0x103a9712,
-    0x103b172e,
-    0x103b9749,
-    0x103c176f,
+    0xc3b88fe,
+    0x1032086f,
+    0x103295e5,
+    0x103315f1,
+    0x1033960a,
+    0x1034161d,
+    0x10348f4f,
+    0x10350c88,
+    0x10359630,
+    0x1036165a,
+    0x1036966d,
+    0x1037168c,
+    0x103796a5,
+    0x103816ba,
+    0x103896d8,
+    0x103916e7,
+    0x10399703,
+    0x103a171e,
+    0x103a972d,
+    0x103b1749,
+    0x103b9764,
+    0x103c178a,
     0x103c80f7,
-    0x103d1780,
-    0x103d9794,
-    0x103e17b3,
-    0x103e97c2,
-    0x103f17d9,
-    0x103f97ec,
-    0x10400c31,
-    0x104097ff,
-    0x1041181d,
-    0x10419830,
-    0x1042184a,
-    0x1042985a,
-    0x1043186e,
-    0x10439884,
-    0x1044189c,
-    0x104498b1,
-    0x104518c5,
-    0x104598d7,
-    0x1046060a,
-    0x1046895c,
-    0x104718ec,
-    0x10479903,
-    0x10481918,
-    0x10489926,
-    0x10490e80,
-    0x10499760,
-    0x104a162a,
-    0x14320c14,
-    0x14328c22,
-    0x14330c31,
-    0x14338c43,
+    0x103d179b,
+    0x103d97af,
+    0x103e17ce,
+    0x103e97dd,
+    0x103f17f4,
+    0x103f9807,
+    0x10400c4c,
+    0x1040981a,
+    0x10411838,
+    0x1041984b,
+    0x10421865,
+    0x10429875,
+    0x10431889,
+    0x1043989f,
+    0x104418b7,
+    0x104498cc,
+    0x104518e0,
+    0x104598f2,
+    0x10460625,
+    0x10468977,
+    0x10471907,
+    0x1047991e,
+    0x10481933,
+    0x10489941,
+    0x10490e9b,
+    0x1049977b,
+    0x104a1645,
+    0x14320c2f,
+    0x14328c3d,
+    0x14330c4c,
+    0x14338c5e,
     0x143400b9,
     0x143480f7,
     0x18320090,
-    0x18328f8a,
+    0x18328fa5,
     0x183300b9,
-    0x18338fa0,
-    0x18340fb4,
+    0x18338fbb,
+    0x18340fcf,
     0x183480f7,
-    0x18350fd3,
-    0x18358feb,
-    0x18361000,
-    0x18369014,
-    0x1837104c,
-    0x18379062,
-    0x18381076,
-    0x18389086,
-    0x18390a82,
-    0x18399096,
-    0x183a10bc,
-    0x183a90e2,
-    0x183b0c8c,
-    0x183b9131,
-    0x183c1143,
-    0x183c914e,
-    0x183d115e,
-    0x183d916f,
-    0x183e1180,
-    0x183e9192,
-    0x183f11bb,
-    0x183f91d4,
-    0x184011ec,
-    0x184086e2,
-    0x18411105,
-    0x184190d0,
-    0x184210ef,
-    0x18428c79,
-    0x184310ab,
-    0x18439117,
-    0x18440fc9,
-    0x18449038,
-    0x20321226,
-    0x20329213,
-    0x24321232,
-    0x243289a2,
-    0x24331244,
-    0x24339251,
-    0x2434125e,
-    0x24349270,
-    0x2435127f,
-    0x2435929c,
-    0x243612a9,
-    0x243692b7,
-    0x243712c5,
-    0x243792d3,
-    0x243812dc,
-    0x243892e9,
-    0x243912fc,
-    0x28320c61,
-    0x28328c8c,
-    0x28330c31,
-    0x28338c9f,
-    0x28340c6d,
+    0x18350fee,
+    0x18359006,
+    0x1836101b,
+    0x1836902f,
+    0x18371067,
+    0x1837907d,
+    0x18381091,
+    0x183890a1,
+    0x18390a9d,
+    0x183990b1,
+    0x183a10d7,
+    0x183a90fd,
+    0x183b0ca7,
+    0x183b914c,
+    0x183c115e,
+    0x183c9169,
+    0x183d1179,
+    0x183d918a,
+    0x183e119b,
+    0x183e91ad,
+    0x183f11d6,
+    0x183f91ef,
+    0x18401207,
+    0x184086fd,
+    0x18411120,
+    0x184190eb,
+    0x1842110a,
+    0x18428c94,
+    0x184310c6,
+    0x18439132,
+    0x18440fe4,
+    0x18449053,
+    0x20321241,
+    0x2032922e,
+    0x2432124d,
+    0x243289bd,
+    0x2433125f,
+    0x2433926c,
+    0x24341279,
+    0x2434928b,
+    0x2435129a,
+    0x243592b7,
+    0x243612c4,
+    0x243692d2,
+    0x243712e0,
+    0x243792ee,
+    0x243812f7,
+    0x24389304,
+    0x24391317,
+    0x28320c7c,
+    0x28328ca7,
+    0x28330c4c,
+    0x28338cba,
+    0x28340c88,
     0x283480b9,
     0x283500f7,
-    0x28358c79,
-    0x2c32326b,
-    0x2c329313,
-    0x2c333279,
-    0x2c33b28b,
-    0x2c34329f,
-    0x2c34b2b1,
-    0x2c3532cc,
-    0x2c35b2de,
-    0x2c36330e,
+    0x28358c94,
+    0x2c323286,
+    0x2c32932e,
+    0x2c333294,
+    0x2c33b2a6,
+    0x2c3432ba,
+    0x2c34b2cc,
+    0x2c3532e7,
+    0x2c35b2f9,
+    0x2c363329,
     0x2c36833a,
-    0x2c37331b,
-    0x2c37b347,
-    0x2c38336c,
-    0x2c38b383,
-    0x2c3933a1,
-    0x2c39b3b1,
-    0x2c3a33c3,
-    0x2c3ab3d7,
-    0x2c3b33e8,
-    0x2c3bb407,
-    0x2c3c1325,
-    0x2c3c933b,
-    0x2c3d341b,
-    0x2c3d9354,
-    0x2c3e3438,
-    0x2c3eb446,
-    0x2c3f345e,
-    0x2c3fb476,
-    0x2c4034a0,
-    0x2c409226,
-    0x2c4134b1,
-    0x2c41b4c4,
-    0x2c4211ec,
-    0x2c42b4d5,
-    0x2c43072f,
-    0x2c43b3f9,
-    0x2c44335a,
-    0x2c44b483,
-    0x2c4532f1,
-    0x2c45b32d,
-    0x2c463391,
+    0x2c373336,
+    0x2c37b362,
+    0x2c383387,
+    0x2c38b39e,
+    0x2c3933bc,
+    0x2c39b3cc,
+    0x2c3a33de,
+    0x2c3ab3f2,
+    0x2c3b3403,
+    0x2c3bb422,
+    0x2c3c1340,
+    0x2c3c9356,
+    0x2c3d3436,
+    0x2c3d936f,
+    0x2c3e3453,
+    0x2c3eb461,
+    0x2c3f3479,
+    0x2c3fb491,
+    0x2c4034bb,
+    0x2c409241,
+    0x2c4134cc,
+    0x2c41b4df,
+    0x2c421207,
+    0x2c42b4f0,
+    0x2c43074a,
+    0x2c43b414,
+    0x2c443375,
+    0x2c44b49e,
+    0x2c45330c,
+    0x2c45b348,
+    0x2c4633ac,
     0x30320000,
     0x30328015,
     0x3033001f,
@@ -276,528 +276,530 @@
     0x30458306,
     0x3046031f,
     0x3046833a,
-    0x30470357,
-    0x30478369,
-    0x30480377,
-    0x30488388,
-    0x30490397,
-    0x304983af,
-    0x304a03c1,
-    0x304a83d5,
-    0x304b03ed,
-    0x304b8400,
-    0x304c040b,
-    0x304c841c,
-    0x304d0428,
-    0x304d843e,
-    0x304e044c,
-    0x304e8462,
-    0x304f0474,
-    0x304f8486,
-    0x305004a9,
-    0x305084bc,
-    0x305104cd,
-    0x305184dd,
-    0x305204f5,
-    0x3052850a,
-    0x30530522,
-    0x30538536,
-    0x3054054e,
-    0x30548567,
-    0x30550580,
-    0x3055859d,
-    0x305605a8,
-    0x305685c0,
-    0x305705d0,
-    0x305785e1,
-    0x305805f4,
-    0x3058860a,
-    0x30590613,
-    0x30598628,
-    0x305a063b,
-    0x305a864a,
-    0x305b066a,
-    0x305b8679,
-    0x305c069a,
-    0x305c86b6,
-    0x305d06c2,
-    0x305d86e2,
-    0x305e06fe,
-    0x305e870f,
-    0x305f0725,
-    0x305f872f,
-    0x30600499,
+    0x30470372,
+    0x30478384,
+    0x30480392,
+    0x304883a3,
+    0x304903b2,
+    0x304983ca,
+    0x304a03dc,
+    0x304a83f0,
+    0x304b0408,
+    0x304b841b,
+    0x304c0426,
+    0x304c8437,
+    0x304d0443,
+    0x304d8459,
+    0x304e0467,
+    0x304e847d,
+    0x304f048f,
+    0x304f84a1,
+    0x305004c4,
+    0x305084d7,
+    0x305104e8,
+    0x305184f8,
+    0x30520510,
+    0x30528525,
+    0x3053053d,
+    0x30538551,
+    0x30540569,
+    0x30548582,
+    0x3055059b,
+    0x305585b8,
+    0x305605c3,
+    0x305685db,
+    0x305705eb,
+    0x305785fc,
+    0x3058060f,
+    0x30588625,
+    0x3059062e,
+    0x30598643,
+    0x305a0656,
+    0x305a8665,
+    0x305b0685,
+    0x305b8694,
+    0x305c06b5,
+    0x305c86d1,
+    0x305d06dd,
+    0x305d86fd,
+    0x305e0719,
+    0x305e872a,
+    0x305f0740,
+    0x305f874a,
+    0x306004b4,
     0x3060804a,
-    0x34320b72,
-    0x34328b86,
-    0x34330ba3,
-    0x34338bb6,
-    0x34340bc5,
-    0x34348bfe,
-    0x34350be2,
+    0x30610357,
+    0x34320b8d,
+    0x34328ba1,
+    0x34330bbe,
+    0x34338bd1,
+    0x34340be0,
+    0x34348c19,
+    0x34350bfd,
     0x3c320090,
-    0x3c328cc9,
-    0x3c330ce2,
-    0x3c338cfd,
-    0x3c340d1a,
-    0x3c348d44,
-    0x3c350d5f,
-    0x3c358d85,
-    0x3c360d9e,
-    0x3c368db6,
-    0x3c370dc7,
-    0x3c378dd5,
-    0x3c380de2,
-    0x3c388df6,
-    0x3c390c8c,
-    0x3c398e19,
-    0x3c3a0e2d,
-    0x3c3a891c,
-    0x3c3b0e3d,
-    0x3c3b8e58,
-    0x3c3c0e6a,
-    0x3c3c8e9d,
-    0x3c3d0ea7,
-    0x3c3d8ebb,
-    0x3c3e0ec9,
-    0x3c3e8eee,
-    0x3c3f0cb5,
-    0x3c3f8ed7,
+    0x3c328ce4,
+    0x3c330cfd,
+    0x3c338d18,
+    0x3c340d35,
+    0x3c348d5f,
+    0x3c350d7a,
+    0x3c358da0,
+    0x3c360db9,
+    0x3c368dd1,
+    0x3c370de2,
+    0x3c378df0,
+    0x3c380dfd,
+    0x3c388e11,
+    0x3c390ca7,
+    0x3c398e34,
+    0x3c3a0e48,
+    0x3c3a8937,
+    0x3c3b0e58,
+    0x3c3b8e73,
+    0x3c3c0e85,
+    0x3c3c8eb8,
+    0x3c3d0ec2,
+    0x3c3d8ed6,
+    0x3c3e0ee4,
+    0x3c3e8f09,
+    0x3c3f0cd0,
+    0x3c3f8ef2,
     0x3c4000b9,
     0x3c4080f7,
-    0x3c410d35,
-    0x3c418d74,
-    0x3c420e80,
-    0x3c428e0a,
-    0x403219b8,
-    0x403299ce,
-    0x403319fc,
-    0x40339a06,
-    0x40341a1d,
-    0x40349a3b,
-    0x40351a4b,
-    0x40359a5d,
-    0x40361a6a,
-    0x40369a76,
-    0x40371a8b,
-    0x40379a9d,
-    0x40381aa8,
-    0x40389aba,
-    0x40390f34,
-    0x40399aca,
-    0x403a1add,
-    0x403a9afe,
-    0x403b1b0f,
-    0x403b9b1f,
+    0x3c410d50,
+    0x3c418d8f,
+    0x3c420e9b,
+    0x3c428e25,
+    0x403219d3,
+    0x403299e9,
+    0x40331a17,
+    0x40339a21,
+    0x40341a38,
+    0x40349a56,
+    0x40351a66,
+    0x40359a78,
+    0x40361a85,
+    0x40369a91,
+    0x40371aa6,
+    0x40379ab8,
+    0x40381ac3,
+    0x40389ad5,
+    0x40390f4f,
+    0x40399ae5,
+    0x403a1af8,
+    0x403a9b19,
+    0x403b1b2a,
+    0x403b9b3a,
     0x403c0071,
     0x403c8090,
-    0x403d1b80,
-    0x403d9b96,
-    0x403e1ba5,
-    0x403e9bdd,
-    0x403f1bf7,
-    0x403f9c1f,
-    0x40401c34,
-    0x40409c48,
-    0x40411c83,
-    0x40419c9e,
-    0x40421cb7,
-    0x40429cca,
-    0x40431cde,
-    0x40439d0c,
-    0x40441d23,
+    0x403d1b9b,
+    0x403d9bb1,
+    0x403e1bc0,
+    0x403e9bf8,
+    0x403f1c12,
+    0x403f9c3a,
+    0x40401c4f,
+    0x40409c63,
+    0x40411c9e,
+    0x40419cb9,
+    0x40421cd2,
+    0x40429ce5,
+    0x40431cf9,
+    0x40439d27,
+    0x40441d3e,
     0x404480b9,
-    0x40451d38,
-    0x40459d4a,
-    0x40461d6e,
-    0x40469d8e,
-    0x40471d9c,
-    0x40479dc3,
-    0x40481e34,
-    0x40489eee,
-    0x40491f05,
-    0x40499f1f,
-    0x404a1f36,
-    0x404a9f54,
-    0x404b1f6c,
-    0x404b9f99,
-    0x404c1faf,
-    0x404c9fc1,
-    0x404d1fe2,
-    0x404da01b,
-    0x404e202f,
-    0x404ea03c,
-    0x404f20d6,
-    0x404fa14c,
-    0x405021a3,
-    0x4050a1b7,
-    0x405121ea,
-    0x405221fa,
-    0x4052a21e,
-    0x40532236,
-    0x4053a249,
-    0x4054225e,
-    0x4054a281,
-    0x405522ac,
-    0x4055a2e9,
-    0x4056230e,
-    0x4056a327,
-    0x4057233f,
-    0x4057a352,
-    0x40582367,
-    0x4058a38e,
-    0x405923bd,
-    0x4059a3ea,
-    0x405a23fe,
-    0x405aa40e,
-    0x405b2426,
-    0x405ba437,
-    0x405c244a,
-    0x405ca489,
-    0x405d2496,
-    0x405da4bb,
-    0x405e24f9,
-    0x405e8ac0,
-    0x405f2534,
-    0x405fa541,
-    0x4060254f,
-    0x4060a571,
-    0x406125d2,
-    0x4061a60a,
-    0x40622621,
-    0x4062a632,
-    0x4063267f,
-    0x4063a694,
-    0x406426ab,
-    0x4064a6d7,
-    0x406526f2,
-    0x4065a709,
-    0x40662721,
-    0x4066a74b,
-    0x40672776,
-    0x4067a7bb,
-    0x40682803,
-    0x4068a824,
-    0x40692856,
-    0x4069a884,
-    0x406a28a5,
-    0x406aa8c5,
-    0x406b2a4d,
-    0x406baa70,
-    0x406c2a86,
-    0x406cad90,
-    0x406d2dbf,
-    0x406dade7,
-    0x406e2e15,
-    0x406eae62,
-    0x406f2ebb,
-    0x406faef3,
-    0x40702f06,
-    0x4070af23,
-    0x4071080f,
-    0x4071af35,
-    0x40722f48,
-    0x4072af7e,
-    0x40732f96,
-    0x40739525,
-    0x40742faa,
-    0x4074afc4,
-    0x40752fd5,
-    0x4075afe9,
-    0x40762ff7,
-    0x407692e9,
-    0x4077301c,
-    0x4077b05c,
-    0x40783077,
-    0x4078b0b0,
-    0x407930c7,
-    0x4079b0dd,
-    0x407a3109,
-    0x407ab11c,
-    0x407b3131,
-    0x407bb143,
-    0x407c3174,
-    0x407cb17d,
-    0x407d283f,
-    0x407da15c,
-    0x407e308c,
-    0x407ea39e,
-    0x407f1db0,
-    0x407f9f83,
-    0x408020e6,
-    0x40809dd8,
-    0x4081220c,
-    0x4081a08a,
-    0x40822e00,
-    0x40829b2b,
-    0x40832379,
-    0x4083a6bc,
-    0x40841dec,
-    0x4084a3d6,
-    0x4085245b,
-    0x4085a599,
-    0x408624db,
-    0x4086a176,
-    0x40872e46,
-    0x4087a5e7,
-    0x40881b69,
-    0x4088a7ce,
-    0x40891bb8,
-    0x40899b45,
-    0x408a2abe,
-    0x408a993d,
-    0x408b3158,
-    0x408baed0,
-    0x408c246b,
-    0x408c9975,
-    0x408d1ed4,
-    0x408d9e1e,
-    0x408e2004,
-    0x408ea2c9,
-    0x408f27e2,
-    0x408fa5b5,
-    0x40902797,
-    0x4090a4ad,
-    0x40912aa6,
-    0x4091999b,
-    0x40921c05,
-    0x4092ae81,
-    0x40932f61,
-    0x4093a187,
-    0x40941e00,
-    0x4094aad7,
-    0x40952643,
-    0x4095b0e9,
-    0x40962e2d,
-    0x4096a0ff,
-    0x409721d2,
-    0x4097a053,
-    0x40981c65,
-    0x4098a657,
-    0x40992e9d,
-    0x4099a2f6,
-    0x409a228f,
-    0x409a9959,
-    0x409b1e5a,
-    0x409b9e85,
-    0x409c303e,
-    0x409c9ead,
-    0x409d20bb,
-    0x409da0a0,
-    0x409e1cf6,
-    0x409ea134,
-    0x409f211c,
-    0x409f9e4d,
-    0x40a0251a,
-    0x40a0a06d,
-    0x41f42978,
-    0x41f92a0a,
-    0x41fe28fd,
-    0x41feabb3,
-    0x41ff2ce1,
-    0x42032991,
-    0x420829b3,
-    0x4208a9ef,
-    0x420928e1,
-    0x4209aa29,
-    0x420a2938,
-    0x420aa918,
-    0x420b2958,
-    0x420ba9d1,
-    0x420c2cfd,
-    0x420caae7,
-    0x420d2b9a,
-    0x420dabd1,
-    0x42122c04,
-    0x42172cc4,
-    0x4217ac46,
-    0x421c2c68,
-    0x421f2c23,
-    0x42212d75,
-    0x42262ca7,
-    0x422b2d53,
-    0x422bab75,
-    0x422c2d35,
-    0x422cab28,
-    0x422d2b01,
-    0x422dad14,
-    0x422e2b54,
-    0x42302c83,
-    0x4230abeb,
-    0x4432073a,
-    0x44328749,
-    0x44330755,
-    0x44338763,
-    0x44340776,
-    0x44348787,
-    0x4435078e,
-    0x44358798,
-    0x443607ab,
-    0x443687c1,
-    0x443707d3,
-    0x443787e0,
-    0x443807ef,
-    0x443887f7,
-    0x4439080f,
-    0x4439881d,
-    0x443a0830,
-    0x48321313,
-    0x48329325,
-    0x4833133b,
-    0x48339354,
-    0x4c321379,
-    0x4c329389,
-    0x4c33139c,
-    0x4c3393bc,
+    0x40451d53,
+    0x40459d65,
+    0x40461d89,
+    0x40469da9,
+    0x40471db7,
+    0x40479dde,
+    0x40481e4f,
+    0x40489f09,
+    0x40491f20,
+    0x40499f3a,
+    0x404a1f51,
+    0x404a9f6f,
+    0x404b1f87,
+    0x404b9fb4,
+    0x404c1fca,
+    0x404c9fdc,
+    0x404d1ffd,
+    0x404da036,
+    0x404e204a,
+    0x404ea057,
+    0x404f20f1,
+    0x404fa167,
+    0x405021be,
+    0x4050a1d2,
+    0x40512205,
+    0x40522215,
+    0x4052a239,
+    0x40532251,
+    0x4053a264,
+    0x40542279,
+    0x4054a29c,
+    0x405522c7,
+    0x4055a304,
+    0x40562329,
+    0x4056a342,
+    0x4057235a,
+    0x4057a36d,
+    0x40582382,
+    0x4058a3a9,
+    0x405923d8,
+    0x4059a405,
+    0x405a2419,
+    0x405aa429,
+    0x405b2441,
+    0x405ba452,
+    0x405c2465,
+    0x405ca4a4,
+    0x405d24b1,
+    0x405da4d6,
+    0x405e2514,
+    0x405e8adb,
+    0x405f254f,
+    0x405fa55c,
+    0x4060256a,
+    0x4060a58c,
+    0x406125ed,
+    0x4061a625,
+    0x4062263c,
+    0x4062a64d,
+    0x4063269a,
+    0x4063a6af,
+    0x406426c6,
+    0x4064a6f2,
+    0x4065270d,
+    0x4065a724,
+    0x4066273c,
+    0x4066a766,
+    0x40672791,
+    0x4067a7d6,
+    0x4068281e,
+    0x4068a83f,
+    0x40692871,
+    0x4069a89f,
+    0x406a28c0,
+    0x406aa8e0,
+    0x406b2a68,
+    0x406baa8b,
+    0x406c2aa1,
+    0x406cadab,
+    0x406d2dda,
+    0x406dae02,
+    0x406e2e30,
+    0x406eae7d,
+    0x406f2ed6,
+    0x406faf0e,
+    0x40702f21,
+    0x4070af3e,
+    0x4071082a,
+    0x4071af50,
+    0x40722f63,
+    0x4072af99,
+    0x40732fb1,
+    0x40739540,
+    0x40742fc5,
+    0x4074afdf,
+    0x40752ff0,
+    0x4075b004,
+    0x40763012,
+    0x40769304,
+    0x40773037,
+    0x4077b077,
+    0x40783092,
+    0x4078b0cb,
+    0x407930e2,
+    0x4079b0f8,
+    0x407a3124,
+    0x407ab137,
+    0x407b314c,
+    0x407bb15e,
+    0x407c318f,
+    0x407cb198,
+    0x407d285a,
+    0x407da177,
+    0x407e30a7,
+    0x407ea3b9,
+    0x407f1dcb,
+    0x407f9f9e,
+    0x40802101,
+    0x40809df3,
+    0x40812227,
+    0x4081a0a5,
+    0x40822e1b,
+    0x40829b46,
+    0x40832394,
+    0x4083a6d7,
+    0x40841e07,
+    0x4084a3f1,
+    0x40852476,
+    0x4085a5b4,
+    0x408624f6,
+    0x4086a191,
+    0x40872e61,
+    0x4087a602,
+    0x40881b84,
+    0x4088a7e9,
+    0x40891bd3,
+    0x40899b60,
+    0x408a2ad9,
+    0x408a9958,
+    0x408b3173,
+    0x408baeeb,
+    0x408c2486,
+    0x408c9990,
+    0x408d1eef,
+    0x408d9e39,
+    0x408e201f,
+    0x408ea2e4,
+    0x408f27fd,
+    0x408fa5d0,
+    0x409027b2,
+    0x4090a4c8,
+    0x40912ac1,
+    0x409199b6,
+    0x40921c20,
+    0x4092ae9c,
+    0x40932f7c,
+    0x4093a1a2,
+    0x40941e1b,
+    0x4094aaf2,
+    0x4095265e,
+    0x4095b104,
+    0x40962e48,
+    0x4096a11a,
+    0x409721ed,
+    0x4097a06e,
+    0x40981c80,
+    0x4098a672,
+    0x40992eb8,
+    0x4099a311,
+    0x409a22aa,
+    0x409a9974,
+    0x409b1e75,
+    0x409b9ea0,
+    0x409c3059,
+    0x409c9ec8,
+    0x409d20d6,
+    0x409da0bb,
+    0x409e1d11,
+    0x409ea14f,
+    0x409f2137,
+    0x409f9e68,
+    0x40a02535,
+    0x40a0a088,
+    0x41f42993,
+    0x41f92a25,
+    0x41fe2918,
+    0x41feabce,
+    0x41ff2cfc,
+    0x420329ac,
+    0x420829ce,
+    0x4208aa0a,
+    0x420928fc,
+    0x4209aa44,
+    0x420a2953,
+    0x420aa933,
+    0x420b2973,
+    0x420ba9ec,
+    0x420c2d18,
+    0x420cab02,
+    0x420d2bb5,
+    0x420dabec,
+    0x42122c1f,
+    0x42172cdf,
+    0x4217ac61,
+    0x421c2c83,
+    0x421f2c3e,
+    0x42212d90,
+    0x42262cc2,
+    0x422b2d6e,
+    0x422bab90,
+    0x422c2d50,
+    0x422cab43,
+    0x422d2b1c,
+    0x422dad2f,
+    0x422e2b6f,
+    0x42302c9e,
+    0x4230ac06,
+    0x44320755,
+    0x44328764,
+    0x44330770,
+    0x4433877e,
+    0x44340791,
+    0x443487a2,
+    0x443507a9,
+    0x443587b3,
+    0x443607c6,
+    0x443687dc,
+    0x443707ee,
+    0x443787fb,
+    0x4438080a,
+    0x44388812,
+    0x4439082a,
+    0x44398838,
+    0x443a084b,
+    0x4832132e,
+    0x48329340,
+    0x48331356,
+    0x4833936f,
+    0x4c321394,
+    0x4c3293a4,
+    0x4c3313b7,
+    0x4c3393d7,
     0x4c3400b9,
     0x4c3480f7,
-    0x4c3513c8,
-    0x4c3593d6,
-    0x4c3613f2,
-    0x4c369418,
-    0x4c371427,
-    0x4c379435,
-    0x4c38144a,
-    0x4c389456,
-    0x4c391476,
-    0x4c3994a0,
-    0x4c3a14b9,
-    0x4c3a94d2,
-    0x4c3b060a,
-    0x4c3b94eb,
-    0x4c3c14fd,
-    0x4c3c950c,
-    0x4c3d1525,
-    0x4c3d8c54,
-    0x4c3e1592,
-    0x4c3e9534,
-    0x4c3f15b4,
-    0x4c3f92e9,
-    0x4c40154a,
-    0x4c409365,
-    0x4c411582,
-    0x4c419405,
-    0x4c42156e,
-    0x503234e7,
-    0x5032b4f6,
-    0x50333501,
-    0x5033b511,
-    0x5034352a,
-    0x5034b544,
-    0x50353552,
-    0x5035b568,
-    0x5036357a,
-    0x5036b590,
-    0x503735a9,
-    0x5037b5bc,
-    0x503835d4,
-    0x5038b5e5,
-    0x503935fa,
-    0x5039b60e,
-    0x503a362e,
-    0x503ab644,
-    0x503b365c,
-    0x503bb66e,
-    0x503c368a,
-    0x503cb6a1,
-    0x503d36ba,
-    0x503db6d0,
-    0x503e36dd,
-    0x503eb6f3,
-    0x503f3705,
-    0x503f8388,
-    0x50403718,
-    0x5040b728,
-    0x50413742,
-    0x5041b751,
-    0x5042376b,
-    0x5042b788,
-    0x50433798,
-    0x5043b7a8,
-    0x504437c5,
-    0x5044843e,
-    0x504537d9,
-    0x5045b7f7,
-    0x5046380a,
-    0x5046b820,
-    0x50473832,
-    0x5047b847,
-    0x5048386d,
-    0x5048b87b,
-    0x5049388e,
-    0x5049b8a3,
-    0x504a38b9,
-    0x504ab8c9,
-    0x504b38e9,
-    0x504bb8fc,
-    0x504c391f,
-    0x504cb94d,
-    0x504d395f,
-    0x504db97c,
-    0x504e3997,
-    0x504eb9b3,
-    0x504f39c5,
-    0x504fb9dc,
-    0x505039eb,
-    0x505086fe,
-    0x505139fe,
-    0x5051b7b7,
-    0x58320f72,
-    0x68320f34,
-    0x68328c8c,
-    0x68330c9f,
-    0x68338f42,
-    0x68340f52,
+    0x4c3513e3,
+    0x4c3593f1,
+    0x4c36140d,
+    0x4c369433,
+    0x4c371442,
+    0x4c379450,
+    0x4c381465,
+    0x4c389471,
+    0x4c391491,
+    0x4c3994bb,
+    0x4c3a14d4,
+    0x4c3a94ed,
+    0x4c3b0625,
+    0x4c3b9506,
+    0x4c3c1518,
+    0x4c3c9527,
+    0x4c3d1540,
+    0x4c3d8c6f,
+    0x4c3e15ad,
+    0x4c3e954f,
+    0x4c3f15cf,
+    0x4c3f9304,
+    0x4c401565,
+    0x4c409380,
+    0x4c41159d,
+    0x4c419420,
+    0x4c421589,
+    0x50323502,
+    0x5032b511,
+    0x5033351c,
+    0x5033b52c,
+    0x50343545,
+    0x5034b55f,
+    0x5035356d,
+    0x5035b583,
+    0x50363595,
+    0x5036b5ab,
+    0x503735c4,
+    0x5037b5d7,
+    0x503835ef,
+    0x5038b600,
+    0x50393615,
+    0x5039b629,
+    0x503a3649,
+    0x503ab65f,
+    0x503b3677,
+    0x503bb689,
+    0x503c36a5,
+    0x503cb6bc,
+    0x503d36d5,
+    0x503db6eb,
+    0x503e36f8,
+    0x503eb70e,
+    0x503f3720,
+    0x503f83a3,
+    0x50403733,
+    0x5040b743,
+    0x5041375d,
+    0x5041b76c,
+    0x50423786,
+    0x5042b7a3,
+    0x504337b3,
+    0x5043b7c3,
+    0x504437e0,
+    0x50448459,
+    0x504537f4,
+    0x5045b812,
+    0x50463825,
+    0x5046b83b,
+    0x5047384d,
+    0x5047b862,
+    0x50483888,
+    0x5048b896,
+    0x504938a9,
+    0x5049b8be,
+    0x504a38d4,
+    0x504ab8e4,
+    0x504b3904,
+    0x504bb917,
+    0x504c393a,
+    0x504cb968,
+    0x504d3995,
+    0x504db9b2,
+    0x504e39cd,
+    0x504eb9e9,
+    0x504f39fb,
+    0x504fba12,
+    0x50503a21,
+    0x50508719,
+    0x50513a34,
+    0x5051b7d2,
+    0x5052397a,
+    0x58320f8d,
+    0x68320f4f,
+    0x68328ca7,
+    0x68330cba,
+    0x68338f5d,
+    0x68340f6d,
     0x683480f7,
-    0x6c320efa,
-    0x6c328c43,
-    0x6c330f05,
-    0x6c338f1e,
-    0x74320a28,
+    0x6c320f15,
+    0x6c328c5e,
+    0x6c330f20,
+    0x6c338f39,
+    0x74320a43,
     0x743280b9,
-    0x74330c54,
-    0x7832098d,
-    0x783289a2,
-    0x783309ae,
+    0x74330c6f,
+    0x783209a8,
+    0x783289bd,
+    0x783309c9,
     0x78338090,
-    0x783409bd,
-    0x783489d2,
-    0x783509f1,
-    0x78358a13,
-    0x78360a28,
-    0x78368a3e,
-    0x78370a4e,
-    0x78378a6f,
-    0x78380a82,
-    0x78388a94,
-    0x78390aa1,
-    0x78398ac0,
-    0x783a0ad5,
-    0x783a8ae3,
-    0x783b0aed,
-    0x783b8b01,
-    0x783c0b18,
-    0x783c8b2d,
-    0x783d0b44,
-    0x783d8b59,
-    0x783e0aaf,
-    0x783e8a61,
-    0x7c321202,
-    0x80321418,
+    0x783409d8,
+    0x783489ed,
+    0x78350a0c,
+    0x78358a2e,
+    0x78360a43,
+    0x78368a59,
+    0x78370a69,
+    0x78378a8a,
+    0x78380a9d,
+    0x78388aaf,
+    0x78390abc,
+    0x78398adb,
+    0x783a0af0,
+    0x783a8afe,
+    0x783b0b08,
+    0x783b8b1c,
+    0x783c0b33,
+    0x783c8b48,
+    0x783d0b5f,
+    0x783d8b74,
+    0x783e0aca,
+    0x783e8a7c,
+    0x7c32121d,
+    0x80321433,
     0x80328090,
-    0x8033323a,
+    0x80333255,
     0x803380b9,
-    0x80343249,
-    0x8034b1b1,
-    0x803531cf,
-    0x8035b25d,
-    0x80363211,
-    0x8036b1c0,
-    0x80373203,
-    0x8037b19e,
-    0x80383224,
-    0x8038b1e0,
-    0x803931f5,
+    0x80343264,
+    0x8034b1cc,
+    0x803531ea,
+    0x8035b278,
+    0x8036322c,
+    0x8036b1db,
+    0x8037321e,
+    0x8037b1b9,
+    0x8038323f,
+    0x8038b1fb,
+    0x80393210,
 };
 
 const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]);
@@ -846,6 +848,7 @@
     "INTEGER_NOT_ASCII_FORMAT\0"
     "INTEGER_TOO_LARGE_FOR_LONG\0"
     "INVALID_BIT_STRING_BITS_LEFT\0"
+    "INVALID_BIT_STRING_PADDING\0"
     "INVALID_BMPSTRING\0"
     "INVALID_DIGIT\0"
     "INVALID_MODIFIER\0"
@@ -1477,6 +1480,7 @@
     "POLICY_PATH_LENGTH_ALREADY_DEFINED\0"
     "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\0"
     "SECTION_NOT_FOUND\0"
+    "TRAILING_DATA_IN_EXTENSION\0"
     "UNABLE_TO_GET_ISSUER_DETAILS\0"
     "UNABLE_TO_GET_ISSUER_KEYID\0"
     "UNKNOWN_BIT_STRING_ARGUMENT\0"
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 6ca8e68d..6709093 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-11-0-180-g81912a138
-Revision: 81912a1385e8fc7694eda820221e15745cdcada4
+Version: VER-2-11-0-181-g3cabd142c
+Revision: 3cabd142ce42627a7e4410ce62616e5c4b91dc6e
 CPEPrefix: cpe:/a:freetype:freetype:2.10.4
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/polymer/v3_0/chromium_dts.patch b/third_party/polymer/v3_0/chromium_dts.patch
index 1521c090..e07bcdc 100644
--- a/third_party/polymer/v3_0/chromium_dts.patch
+++ b/third_party/polymer/v3_0/chromium_dts.patch
@@ -31,6 +31,19 @@
    /**
     * Remove an icon from the given element by undoing the changes effected
     * by `applyIcon`.
+diff --git a/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts b/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts
+index a1a4c1fdc485c..67634c9abb81c 100644
+--- a/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts
++++ b/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts
+@@ -23,7 +23,7 @@ interface IronOverlayBehaviorImpl {
+   /**
+    * True if the overlay is currently displayed.
+    */
+-  opened: boolean|null|undefined;
++  opened: boolean;
+
+   /**
+    * True if the overlay was canceled when it was last closed.
 diff --git a/components-chromium/paper-tooltip/paper-tooltip.d.ts b/components-chromium/paper-tooltip/paper-tooltip.d.ts
 index ed159e50ca1dd..7ef18f0bc7cc8 100644
 --- a/components-chromium/paper-tooltip/paper-tooltip.d.ts
diff --git a/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts b/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts
index a1a4c1fd..67634c9 100644
--- a/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts
+++ b/third_party/polymer/v3_0/components-chromium/iron-overlay-behavior/iron-overlay-behavior.d.ts
@@ -23,7 +23,7 @@
   /**
    * True if the overlay is currently displayed.
    */
-  opened: boolean|null|undefined;
+  opened: boolean;
 
   /**
    * True if the overlay was canceled when it was last closed.
diff --git a/third_party/protobuf/OWNERS b/third_party/protobuf/OWNERS
index ec5c11d..0e66e0e 100644
--- a/third_party/protobuf/OWNERS
+++ b/third_party/protobuf/OWNERS
@@ -1,4 +1,3 @@
-ajwong@chromium.org
 lgrey@chromium.org
 nyquist@chromium.org
 pkasting@chromium.org
diff --git a/third_party/tlslite/BUILD.gn b/third_party/tlslite/BUILD.gn
deleted file mode 100644
index 0b13774..0000000
--- a/third_party/tlslite/BUILD.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2015 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.
-
-# Tlslite is a Python program. Depend on this to get the data deps necessary
-# to run tlslite in the test environment.
-group("tlslite") {
-  # For now, depend on the entire directory.
-  data = [ "//third_party/tlslite/" ]
-}
diff --git a/third_party/tlslite/DIR_METADATA b/third_party/tlslite/DIR_METADATA
deleted file mode 100644
index ca543b8..0000000
--- a/third_party/tlslite/DIR_METADATA
+++ /dev/null
@@ -1,4 +0,0 @@
-monorail: {
-  component: "Internals>Network>SSL"
-}
-team_email: "trusty-transport@chromium.org"
diff --git a/third_party/tlslite/LICENSE b/third_party/tlslite/LICENSE
deleted file mode 100644
index 7e71620..0000000
--- a/third_party/tlslite/LICENSE
+++ /dev/null
@@ -1,67 +0,0 @@
-
-TLS Lite includes code from different sources. All code is either dedicated to
-the public domain by its authors, or available under a BSD-style license. In
-particular:
-
-- 
-
-Code written by Trevor Perrin, Kees Bos, Sam Rushing, Dimitris Moraitis,
-Marcelo Fernandez, Martin von Loewis, Dave Baggett, and Yngve Pettersen is 
-available under the following terms:
-
-This is free and unencumbered software released into the public domain.
-
-Anyone is free to copy, modify, publish, use, compile, sell, or distribute
-this software, either in source code form or as a compiled binary, for any
-purpose, commercial or non-commercial, and by any means.
-
-In jurisdictions that recognize copyright laws, the author or authors of this
-software dedicate any and all copyright interest in the software to the public
-domain. We make this dedication for the benefit of the public at large and to
-the detriment of our heirs and successors. We intend this dedication to be an
-overt act of relinquishment in perpetuity of all present and future rights to
-this software under copyright law.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
--
-
-Code written by Bram Cohen (rijndael.py) was dedicated to the public domain by
-its author. See rijndael.py for details.
-
--
-
-Code written by Google is available under the following terms:
-
-Copyright (c) 2008, The Chromium Authors 
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
- * Neither the name of the Google Inc. nor the names of its contributors may
-   be used to endorse or promote products derived from this software without
-   specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/tlslite/MANIFEST.in b/third_party/tlslite/MANIFEST.in
deleted file mode 100644
index 340da6966..0000000
--- a/third_party/tlslite/MANIFEST.in
+++ /dev/null
@@ -1,6 +0,0 @@
-recursive-include tests *
-recursive-include docs *
-include LICENSE
-include README
-include Makefile
-include MANIFEST.in
\ No newline at end of file
diff --git a/third_party/tlslite/Makefile b/third_party/tlslite/Makefile
deleted file mode 100644
index 871125e6a..0000000
--- a/third_party/tlslite/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Hubert Kario - test and test-dev
-#
-.PHONY : default
-default:
-	@echo To install tlslite run \"./setup.py install\" or \"make install\"
-
-.PHONY: install
-install:
-	./setup.py install
-
-.PHONY : clean
-clean:
-	rm -rf tlslite/*.pyc
-	rm -rf tlslite/utils/*.pyc
-	rm -rf tlslite/integration/*.pyc	
-	rm -rf dist
-	rm -rf docs
-	rm -rf build
-	rm -f MANIFEST
-
-docs:
-	epydoc --html -v --introspect-only -o docs tlslite
-
-dist: docs
-	./setup.py sdist
-
-test:
-	cd tests/ && python ./tlstest.py server localhost:4433 . & sleep 1
-	cd tests/ && python ./tlstest.py client localhost:4433 .
-
-test-dev:
-	cd tests/ && PYTHONPATH=.. python ./tlstest.py server localhost:4433 . & sleep 1
-	cd tests/ && PYTHONPATH=.. python ./tlstest.py client localhost:4433 .
diff --git a/third_party/tlslite/OWNERS b/third_party/tlslite/OWNERS
deleted file mode 100644
index 42d0d3b..0000000
--- a/third_party/tlslite/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-agl@chromium.org
-davidben@chromium.org
-rsleevi@chromium.org
diff --git a/third_party/tlslite/PKG-INFO b/third_party/tlslite/PKG-INFO
deleted file mode 100644
index 0b6bbd1..0000000
--- a/third_party/tlslite/PKG-INFO
+++ /dev/null
@@ -1,10 +0,0 @@
-Metadata-Version: 1.0
-Name: tlslite
-Version: 0.4.8
-Summary: tlslite implements SSL and TLS.
-Home-page: http://trevp.net/tlslite/
-Author: Trevor Perrin
-Author-email: tlslite@trevp.net
-License: public domain and BSD
-Description: UNKNOWN
-Platform: UNKNOWN
diff --git a/third_party/tlslite/README b/third_party/tlslite/README
deleted file mode 100644
index 97c57e17..0000000
--- a/third_party/tlslite/README
+++ /dev/null
@@ -1,663 +0,0 @@
-
-tlslite version 0.4.8                                            Nov 12 2014
-Trevor Perrin <tlslite at trevp.net>
-http://trevp.net/tlslite/
-============================================================================
-
-
-Table of Contents
-==================
-1  Introduction
-2  License/Acknowledgements
-3  Installation
-4  Getting Started with the Command-Line Tools
-5  Getting Started with the Library
-6  Using TLS Lite with httplib
-7  Using TLS Lite with poplib or imaplib
-8  Using TLS Lite with smtplib
-9 Using TLS Lite with SocketServer
-10 Using TLS Lite with asyncore
-11 SECURITY CONSIDERATIONS
-12 History
-
-
-1 Introduction 
-=============== 
-TLS Lite is an open source python library that implements SSL and TLS. TLS
-Lite supports RSA and SRP ciphersuites. TLS Lite is pure python, however it
-can use other libraries for faster crypto operations. TLS Lite integrates with
-several stdlib neworking libraries.
-
-API documentation is available in the 'docs' directory.
-
-If you have questions or feedback, feel free to contact me.  For discussing
-improvements to tlslite, also see 'tlslite-dev@googlegroups.com'.
-
-
-2 Licenses/Acknowledgements
-============================
-TLS Lite is written (mostly) by Trevor Perrin. It includes code from Bram
-Cohen, Google, Kees Bos, Sam Rushing, Dimitris Moraitis, Marcelo Fernandez,
-Martin von Loewis, Dave Baggett, and Yngve N. Pettersen (ported by Paul 
-Sokolovsky).
-
-All code in TLS Lite has either been dedicated to the public domain by its
-authors, or placed under a BSD-style license. See the LICENSE file for
-details.
-
-Thanks to Edward Loper for Epydoc, which generated the API docs.
-
-3 Installation
-===============
-Requirements:
-  Python 2.6 or higher is required. Python 3 is supported.
-
-Options:
-  - If you have the M2Crypto interface to OpenSSL, this will be used for fast
-    RSA operations and fast ciphers.
-
-  - If you have pycrypto this will be used for fast RSA operations and fast
-    ciphers.
-
-  - If you have the GMPY interface to GMP, this will be used for fast RSA and
-    SRP operations.
-
-  - These modules don't need to be present at installation - you can install
-    them any time.
-
-Run 'python setup.py install'
-
-Test the Installation:
-  - From the distribution's ./tests subdirectory, run:
-      ./tlstest.py server localhost:4443 .
-  - While the test server is waiting, run:
-      ./tlstest.py client localhost:4443 .
-
-  If both say "Test succeeded" at the end, you're ready to go.
-
-
-4 Getting Started with the Command-Line Tools
-==============================================
-tlslite installs two command-line scripts: 'tlsdb.py' and 'tls.py'.
-
-'tls.py' lets you run test clients and servers. It can be used for testing
-other TLS implementations, or as example code. Note that 'tls.py server' runs
-an HTTPS server which will serve files rooted at the current directory by
-default, so be careful.
-
-'tlsdb.py' lets you manage SRP verifier databases. These databases are used by
-a TLS server when authenticating clients with SRP.
-
-X.509
-------
-To run an X.509 server, go to the ./tests directory and do:
-
-  tls.py server -k serverX509Key.pem -c serverX509Cert.pem localhost:4443
-
-Try connecting to the server with a web browser, or with:
-
-  tls.py client localhost:4443
-
-X.509 with TACK
-----------------
-To run an X.509 server using a TACK, install TACKpy, then run the same server
-command as above with added arguments:
-
- ... -t TACK1.pem localhost:4443
-
-SRP
-----
-To run an SRP server, try something like:
-
-  tlsdb.py createsrp verifierDB
-  tlsdb.py add verifierDB alice abra123cadabra 1024
-  tlsdb.py add verifierDB bob swordfish 2048
-
-  tls.py server -v verifierDB localhost:4443
-
-Then try connecting to the server with:
-
-  tls.py client localhost:4443 alice abra123cadabra
-
-HTTPS
-------
-To run an HTTPS server with less typing, run ./tests/httpsserver.sh.
-
-To run an HTTPS client, run ./tests/httpsclient.py.
-
-
-5 Getting Started with the Library
-===================================
-Whether you're writing a client or server, there are six steps:
-
-1) Create a socket and connect it to the other party.
-2) Construct a TLSConnection instance with the socket.
-3) Call a handshake function on TLSConnection to perform the TLS handshake.
-4) Check the results to make sure you're talking to the right party.
-5) Use the TLSConnection to exchange data.
-6) Call close() on the TLSConnection when you're done.
-
-TLS Lite also integrates with several stdlib python libraries. See the
-sections following this one for details.
-
-5 Step 1 - create a socket
----------------------------
-Below demonstrates a socket connection to Amazon's secure site.
-
-  from socket import *
-  sock = socket(AF_INET, SOCK_STREAM)
-  sock.connect( ("www.amazon.com", 443) )
-
-5 Step 2 - construct a TLSConnection
--------------------------------------
-You can import tlslite objects individually, such as:
-  from tlslite import TLSConnection
-
-Or import the most useful objects through:
-  from tlslite.api import *
-
-Then do:
-  connection = TLSConnection(sock)
-
-5 Step 3 - call a handshake function (client)
-----------------------------------------------
-If you're a client, there's two different handshake functions you can call,
-depending on how you want to authenticate:
-
-  connection.handshakeClientCert()
-  connection.handshakeClientCert(certChain, privateKey)
-
-  connection.handshakeClientSRP("alice", "abra123cadabra")
-
-The ClientCert function without arguments is used when connecting to a site
-like Amazon, which doesn't require client authentication, but which will
-authenticate itself using an X.509 certificate chain.
-
-The ClientCert function can also be used to do client authentication with an
-X.509 certificate chain and corresponding private key. To use X.509 chains,
-you'll need some way of creating these, such as OpenSSL (see
-http://www.openssl.org/docs/HOWTO/ for details).
-
-Below is an example of loading an X.509 chain and private key:
-  
-  from tlslite import X509, X509CertChain, parsePEMKey
-  s = open("./test/clientX509Cert.pem").read()
-  x509 = X509()
-  x509.parse(s)
-  certChain = X509CertChain([x509])
-  s = open("./test/clientX509Key.pem").read()
-  privateKey = parsePEMKey(s, private=True)
-
-The SRP function does mutual authentication with a username and password - see
-RFC 5054 for details.
-
-If you want more control over the handshake, you can pass in a
-HandshakeSettings instance. For example, if you're performing SRP, but you
-only want to use SRP parameters of at least 2048 bits, and you only want to
-use the AES-256 cipher, and you only want to allow TLS (version 3.1), not SSL
-(version 3.0), you can do:
-
-  settings = HandshakeSettings()
-  settings.minKeySize = 2048
-  settings.cipherNames = ["aes256"]
-  settings.minVersion = (3,1)
-  settings.useExperimentalTACKExtension = True  # Needed for TACK support
-
-  connection.handshakeClientSRP("alice", "abra123cadabra", settings=settings)
-
-If you want to check the server's certificate using TACK, you should set the
-"useExperiementalTACKExtension" value in HandshakeSettings. (Eventually, TACK
-support will be enabled by default, but for now it is an experimental feature
-which relies on a temporary TLS Extension number, and should not be used for
-production software.) This will cause the client to request the server to send
-you a TACK (and/or any TACK Break Signatures):
-
-Finally, every TLSConnection has a session object. You can try to resume a
-previous session by passing in the session object from the old session. If the
-server remembers this old session and supports resumption, the handshake will
-finish more quickly. Otherwise, the full handshake will be done. For example:
-
-  connection.handshakeClientSRP("alice", "abra123cadabra")
-  .
-  .
-  oldSession = connection.session
-  connection2.handshakeClientSRP("alice", "abra123cadabra", session=
-  oldSession)
-
-5 Step 3 - call a handshake function (server)
-----------------------------------------------
-If you're a server, there's only one handshake function, but you can pass it
-several different parameters, depending on which types of authentication
-you're willing to perform.
-
-To perform SRP authentication, you have to pass in a database of password
-verifiers.  The VerifierDB class manages an in-memory or on-disk verifier
-database.
-
-  verifierDB = VerifierDB("./test/verifierDB")
-  verifierDB.open()
-  connection.handshakeServer(verifierDB=verifierDB)
-
-To perform authentication with a certificate and private key, the server must
-load these as described in the previous section, then pass them in.  If the
-server sets the reqCert boolean to True, a certificate chain will be requested
-from the client.
-
-  connection.handshakeServer(certChain=certChain, privateKey=privateKey,
-                             reqCert=True)
-
-You can pass in a verifier database and/or a certificate chain+private key.
-The client will use one or both to authenticate the server.
-
-You can also pass in a HandshakeSettings object, as described in the last
-section, for finer control over handshaking details.
-
-If you are passing in a certificate chain+private key, you may additionally
-provide a TACK to assist the client in authenticating your certificate chain.
-This requires the TACKpy library. Load a TACKpy.TACK object, then do:
-
-  settings = HandshakeSettings()
-  settings.useExperimentalTACKExtension = True  # Needed for TACK support
-
-  connection.handshakeServer(certChain=certChain, privateKey=privateKey,
-                             tack=tack, settings=settings)
-
-Finally, the server can maintain a SessionCache, which will allow clients to
-use session resumption:
-
-  sessionCache = SessionCache()
-  connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-
-It should be noted that the session cache, and the verifier databases, are all
-thread-safe.
-
-5 Step 4 - check the results
------------------------------
-If the handshake completes without raising an exception, authentication
-results will be stored in the connection's session object.  The following
-variables will be populated if applicable, or else set to None:
-
-  connection.session.srpUsername       # string
-  connection.session.clientCertChain   # X509CertChain
-  connection.session.serverCertChain   # X509CertChain
-  connection.session.tackExt           # TACKpy.TACK_Extension
-
-X.509 chain objects return the end-entity fingerprint via getFingerprint(),
-and ignore the other certificates.
-
-TACK objects return the (validated) TACK ID via getTACKID().
-
-To save yourself the trouble of inspecting certificates after the handshake,
-you can pass a Checker object into the handshake function. The checker will be
-called if the handshake completes successfully. If the other party isn't
-approved by the checker, a subclass of TLSAuthenticationError will be raised.
-
-If the handshake fails for any reason, including a Checker error, an exception
-will be raised and the socket will be closed. If the socket timed out or was
-unexpectedly closed, a socket.error or TLSAbruptCloseError will be raised.
-
-Otherwise, either a TLSLocalAlert or TLSRemoteAlert will be raised, depending
-on whether the local or remote implementation signalled the error. The
-exception object has a 'description' member which identifies the error based
-on the codes in RFC 2246. A TLSLocalAlert also has a 'message' string that may
-have more details.
-
-Example of handling a remote alert:
-
-  try:
-      [...]
-  except TLSRemoteAlert as alert:
-      if alert.description == AlertDescription.unknown_psk_identity:
-          print "Unknown user."
-  [...]
-
-Below are some common alerts and their probable causes, and whether they are
-signalled by the client or server.
-
-Client handshake_failure:
- - SRP parameters are not recognized by client
- - Server's TACK was unrelated to its certificate chain
-
-Client insufficient_security:
- - SRP parameters are too small
-
-Client protocol_version:
- - Client doesn't support the server's protocol version
-
-Server protocol_version:
- - Server doesn't support the client's protocol version
-
-Server bad_record_mac:
- - bad SRP username or password
-
-Server unknown_psk_identity
- - bad SRP username (bad_record_mac could be used for the same thing)
-
-Server handshake_failure:
- - no matching cipher suites
-
-5 Step 5 - exchange data
--------------------------
-Now that you have a connection, you can call read() and write() as if it were
-a socket.SSL object. You can also call send(), sendall(), recv(), and
-makefile() as if it were a socket. These calls may raise TLSLocalAlert,
-TLSRemoteAlert, socket.error, or TLSAbruptCloseError, just like the handshake
-functions.
-
-Once the TLS connection is closed by the other side, calls to read() or recv()
-will return an empty string. If the socket is closed by the other side without
-first closing the TLS connection, calls to read() or recv() will return a
-TLSAbruptCloseError, and calls to write() or send() will return a
-socket.error.
-
-5 Step 6 - close the connection
---------------------------------
-When you're finished sending data, you should call close() to close the
-connection and socket. When the connection is closed properly, the session
-object can be used for session resumption.
-
-If an exception is raised the connection will be automatically closed; you
-don't need to call close(). Furthermore, you will probably not be able to
-re-use the socket, the connection object, or the session object, and you
-shouldn't even try.
-
-By default, calling close() will close the underlying socket. If you set the
-connection's closeSocket flag to False, the socket will remain open after
-close. (NOTE: some TLS implementations will not respond properly to the
-close_notify alert that close() generates, so the connection will hang if
-closeSocket is set to True.)
-
-
-6 Using TLS Lite with httplib
-==============================
-TLS Lite comes with an HTTPTLSConnection class that extends httplib to work
-over SSL/TLS connections.  Depending on how you construct it, it will do
-different types of authentication.
-
-  #No authentication whatsoever
-  h = HTTPTLSConnection("www.amazon.com", 443)
-  h.request("GET", "")
-  r = h.getresponse()
-  [...]
-
-  #Authenticate server based on its TACK ID
-  h = HTTPTLSConnection("localhost", 4443,
-          tackID="B3ARS.EQ61B.F34EL.9KKLN.3WEW5", hardTack=False)
-  [...]
-
-  #Mutually authenticate with SRP
-  h = HTTPTLSConnection("localhost", 443,
-          username="alice", password="abra123cadabra")
-  [...]
-
-
-7 Using TLS Lite with poplib or imaplib
-========================================
-TLS Lite comes with POP3_TLS and IMAP4_TLS classes that extend poplib and
-imaplib to work over SSL/TLS connections.  These classes can be constructed
-with the same parameters as HTTPTLSConnection (see previous section), and 
-behave similarly.
-
-  #To connect to a POP3 server over SSL and display its fingerprint:
-  from tlslite.api import *
-  p = POP3_TLS("---------.net", port=995)
-  print p.sock.session.serverCertChain.getFingerprint()
-  [...]
-
-  #To connect to an IMAP server once you know its fingerprint:
-  from tlslite.api import *
-  i = IMAP4_TLS("cyrus.andrew.cmu.edu",
-          x509Fingerprint="00c14371227b3b677ddb9c4901e6f2aee18d3e45")
-  [...]  
-  
-
-8 Using TLS Lite with smtplib
-==============================
-TLS Lite comes with an SMTP_TLS class that extends smtplib to work
-over SSL/TLS connections.  This class accepts the same parameters as
-HTTPTLSConnection (see previous section), and behaves similarly.  Depending 
-on how you call starttls(), it will do different types of authentication.
-
-  #To connect to an SMTP server once you know its fingerprint:
-  from tlslite.api import *
-  s = SMTP_TLS("----------.net", port=587)
-  s.ehlo()
-  s.starttls(x509Fingerprint="7e39be84a2e3a7ad071752e3001d931bf82c32dc")
-  [...]
-
-
-9 Using TLS Lite with SocketServer
-====================================
-You can use TLS Lite to implement servers using Python's SocketServer
-framework.  TLS Lite comes with a TLSSocketServerMixIn class.  You can combine
-this with a TCPServer such as HTTPServer.  To combine them, define a new class
-that inherits from both of them (with the mix-in first). Then implement the
-handshake() method, doing some sort of server handshake on the connection
-argument.  If the handshake method returns True, the RequestHandler will be
-triggered.  See the tests/httpsserver.py example.
-
-
-10 Using TLS Lite with asyncore
-================================
-TLS Lite can be used with subclasses of asyncore.dispatcher.  See the comments
-in TLSAsyncDispatcherMixIn.py for details.  This is still experimental, and
-may not work with all asyncore.dispatcher subclasses.
-
-
-11 Security Considerations
-===========================
-TLS Lite is beta-quality code. It hasn't received much security analysis. Use
-at your own risk.
-
-TLS Lite does NOT verify certificates by default.
-
-TLS Lite's pure-python ciphers are probably vulnerable to timing attacks.
-
-TLS Lite is probably vulnerable to the "Lucky 13" timing attack if AES or 3DES
-are used, or the weak cipher RC4 otherwise.  This unhappy situation will remain
-until TLS Lite implements authenticated-encryption ciphersuites (like GCM), or
-RFC 7366.
-
-
-12 History
-===========
-0.4.8 - 11/12/2014
- - Added more acknowledgements and security considerations
-0.4.7 - 11/12/2014
- - Added TLS 1.2 support (Yngve Pettersen and Paul Sokolovsky)
- - Don't offer SSLv3 by default (e.g. POODLE)
- - Fixed bug with PyCrypto_RSA integration
- - Fixed harmless bug that added non-prime into sieves list
- - Added "make test" and "make test-dev" targets (Hubert Kario)
-0.4.5 - 3/20/2013
- - **API CHANGE**: TLSClosedConnectionError instead of ValueError when writing
-   to a closed connection.  This inherits from socket.error, so should 
-   interact better with SocketServer (see http://bugs.python.org/issue14574)
-   and other things expecting a socket.error in this situation.
- - Added support for RC4-MD5 ciphersuite (if enabled in settings)
-   - This is allegedly necessary to connect to some Internet servers.
- - Added TLSConnection.unread() function 
- - Switched to New-style classes (inherit from 'object')
- - Minor cleanups
-0.4.4 - 2/25/2013
- - Added Python 3 support (Martin von Loewis)
- - Added NPN client support (Marcelo Fernandez)
- - Switched to RC4 as preferred cipher
-   - faster in Python, avoids "Lucky 13" timing attacks
- - Fixed bug when specifying ciphers for anon ciphersuites
- - Made RSA hashAndVerify() tolerant of sigs w/o encoded NULL AlgorithmParam
-   - (this function is not used for TLS currently, and this tolerance may
-      not even be necessary)
-0.4.3 - 9/27/2012
- - Minor bugfix (0.4.2 doesn't load tackpy)
-0.4.2 - 9/25/2012
- - Updated TACK (compatible with tackpy 0.9.9)
-0.4.1 - 5/22/2012
- - Fixed RSA padding bugs (w/help from John Randolph)
- - Updated TACK (compatible with tackpy 0.9.7)
- - Added SNI
- - Added NPN server support (Sam Rushing/Google)
- - Added AnonDH (Dimitris Moraitis)
- - Added X509CertChain.parsePemList
- - Improved XML-RPC (Kees Bos)
-
-0.4.0 - 2/11/2012
- - Fixed pycrypto support
- - Fixed python 2.6 problems
- 
-0.3.9.x - 2/7/2012
-
-Much code cleanup, in particular decomposing the handshake functions so they
-are readable. The main new feature is support for TACK, an experimental
-authentication method that provides a new way to pin server certificates (See
-https://github.com/moxie0/Convergence/wiki/TACK ).
-
-Also:
-
- - Security Fixes
-   - Sends SCSV ciphersuite as per RFC 5746, to signal non-renegotiated
-     Client Hello.  Does not support renegotiation (never has).
-   - Change from e=3 to e=65537 for generated RSA keys, not strictly 
-     necessary but mitigates risk of sloppy verifier.
-   - 1/(n-1) countermeasure for BEAST.
-
- - Behavior changes:
-   - Split cmdline into tls.py and tlstest.py, improved options.
-   - Formalized LICENSE.
-   - Defaults to closing socket after sending close_notify, fixes hanging.
-     problem that would occur sometime when waiting for other party's    
-     close_notify.
-   - Update SRP to RFC 5054 compliance.
-   - Removed client handshake "callbacks", no longer support the SRP 
-     re-handshake idiom within a single handshake function.
-
- - Bugfixes
-   - Added hashlib support, removes Deprecation Warning due to sha and md5.
-   - Handled GeneratorExit exceptions that are a new Python feature, and
-     interfere with the async code if not handled.
- 
- - Removed:
-   - Shared keys (it was based on an ancient I-D, not TLS-PSK).
-   - cryptlib support, it wasn't used much, we have enough other options.
-   - cryptoIDs (TACK is better).
-   - win32prng extension module, as os.urandom is now available.
-   - Twisted integration (unused?, slowed down loading).
-   - Jython code (ancient, didn't work).
-   - Compat support for python versions < 2.7.
-
- - Additions
-   - Support for TACK via TACKpy.
-   - Support for CertificateRequest.certificate_authorities ("reqCAs")
-   - Added TLSConnection.shutdown() to better mimic socket.
-   - Enabled Session resumption for XMLRPCTransport.
-
-0.3.8 - 2/21/2005
- - Added support for poplib, imaplib, and smtplib
- - Added python 2.4 windows installer
- - Fixed occassional timing problems with test suite
-0.3.7 - 10/05/2004
- - Added support for Python 2.2
- - Cleaned up compatibility code, and docs, a bit
-0.3.6 - 9/28/2004
- - Fixed script installation on UNIX
- - Give better error message on old Python versions
-0.3.5 - 9/16/2004
- - TLS 1.1 support
- - os.urandom() support
- - Fixed win32prng on some systems
-0.3.4 - 9/12/2004
- - Updated for TLS/SRP draft 8
- - Bugfix: was setting _versioncheck on SRP 1st hello, causing problems
-   with GnuTLS (which was offering TLS 1.1)
- - Removed _versioncheck checking, since it could cause interop problems
- - Minor bugfix: when cryptlib_py and and cryptoIDlib present, cryptlib
-   was complaining about being initialized twice
-0.3.3 - 6/10/2004
- - Updated for TLS/SRP draft 7
- - Updated test cryptoID cert chains for cryptoIDlib 0.3.1
-0.3.2 - 5/21/2004
- - fixed bug when handling multiple handshake messages per record (e.g. IIS)
-0.3.1 - 4/21/2004
- - added xmlrpclib integration
- - fixed hanging bug in Twisted integration
- - fixed win32prng to work on a wider range of win32 sytems
- - fixed import problem with cryptoIDlib
- - fixed port allocation problem when test scripts are run on some UNIXes
- - made tolerant of buggy IE sending wrong version in premaster secret
-0.3.0 - 3/20/2004
- - added API docs thanks to epydoc
- - added X.509 path validation via cryptlib
- - much cleaning/tweaking/re-factoring/minor fixes
-0.2.7 - 3/12/2004
- - changed Twisted error handling to use connectionLost()
- - added ignoreAbruptClose
-0.2.6 - 3/11/2004
- - added Twisted errorHandler
- - added TLSAbruptCloseError
- - added 'integration' subdirectory
-0.2.5 - 3/10/2004
- - improved asynchronous support a bit
- - added first-draft of Twisted support
-0.2.4 - 3/5/2004
- - cleaned up asyncore support
- - added proof-of-concept for Twisted
-0.2.3 - 3/4/2004
- - added pycrypto RSA support
- - added asyncore support
-0.2.2 - 3/1/2004
- - added GMPY support
- - added pycrypto support
- - added support for PEM-encoded private keys, in pure python
-0.2.1 - 2/23/2004
- - improved PRNG use (cryptlib, or /dev/random, or CryptoAPI)
- - added RSA blinding, to avoid timing attacks
- - don't install local copy of M2Crypto, too problematic
-0.2.0 - 2/19/2004
- - changed VerifierDB to take per-user parameters
- - renamed tls_lite -> tlslite
-0.1.9 - 2/16/2004
- - added post-handshake 'Checker'
- - made compatible with Python 2.2
- - made more forgiving of abrupt closure, since everyone does it:
-   if the socket is closed while sending/recv'ing close_notify,
-   just ignore it.
-0.1.8 - 2/12/2004
- - TLSConnections now emulate sockets, including makefile()
- - HTTPTLSConnection and TLSMixIn simplified as a result
-0.1.7 - 2/11/2004
- - fixed httplib.HTTPTLSConnection with multiple requests
- - fixed SocketServer to handle close_notify
- - changed handshakeClientNoAuth() to ignore CertificateRequests
- - changed handshakeClient() to ignore non-resumable session arguments
-0.1.6 - 2/10/2004
- - fixed httplib support
-0.1.5 - 2/09/2004
- - added support for httplib and SocketServer
- - added support for SSLv3
- - added support for 3DES
- - cleaned up read()/write() behavior
- - improved HMAC speed
-0.1.4 - 2/06/2004
- - fixed dumb bug in tls.py
-0.1.3 - 2/05/2004
- - change read() to only return requested number of bytes
- - added support for shared-key and in-memory databases
- - added support for PEM-encoded X.509 certificates
- - added support for SSLv2 ClientHello
- - fixed shutdown/re-handshaking behavior
- - cleaned up handling of missing_srp_username
- - renamed readString()/writeString() -> read()/write()
- - added documentation
-0.1.2 - 2/04/2004
- - added clienttest/servertest functions
- - improved OpenSSL cipher wrappers speed
- - fixed server when it has a key, but client selects plain SRP
- - fixed server to postpone errors until it has read client's messages
- - fixed ServerHello to only include extension data if necessary
-0.1.1 - 2/02/2004
- - fixed close_notify behavior
- - fixed handling of empty application data packets
- - fixed socket reads to not consume extra bytes
- - added testing functions to tls.py
-0.1.0 - 2/01/2004
- - first release
diff --git a/third_party/tlslite/README.chromium b/third_party/tlslite/README.chromium
deleted file mode 100644
index 1cd7d32..0000000
--- a/third_party/tlslite/README.chromium
+++ /dev/null
@@ -1,67 +0,0 @@
-Name: tlslite
-URL: http://trevp.net/tlslite/
-Version: 0.4.8
-CPEPrefix: cpe:/a:tlslite_project:tlslite:0.4.8::~~~python~~
-Security Critical: No
-License: Public domain and BSD
-
-Description: Python TLS implementation for use with test server.
-
-Source: https://pypi.python.org/packages/source/t/tlslite/tlslite-0.4.8.tar.gz
-MD5: 36c13858ea63f262c4e4291c2f9ae38f
-SHA-512: bdb42d005b7444667badc6febd38f5b74878c09218b418844c255920f0e6272f
-         55f62b4ea21953953935f73e02657fce9874b44f73499267cf713ddbcd3d6a44
-
-Local Modifications:
-- Drop docs/ directory.
-- patches/tls_intolerant.patch: allow TLSLite to simulate a TLS-intolerant server.
-- patches/channel_id.patch: add basic ChannelID support. (Signatures are not
-  checked.)
-- patches/signed_certificate_timestamps.patch: add support for sending Signed
-  Certificate Timestamps over a TLS extension.
-- patches/fallback_scsv.patch: add support for TLS_FALLBACK_SCSV. See
-  https://tools.ietf.org/html/draft-bmoeller-tls-downgrade-scsv-01
-- patches/status_request.patch: add support for sending stapled OCSP responses.
-- patches/ssl3_padding.patch: SSL3 requires minimal padding in CBC mode.
-- patches/fix_test_file.patch: Fix #! line in random test file to appease our
-  presubmit checks.
-- patches/dhe_rsa.patch: Implement DHE_RSA-based cipher suites on the server.
-- patches/req_cert_types.patch: Add a reqCertTypes parameter to populate the
-  certificate_types field of CertificateRequest. Also fixes type errors.
-- patches/ignore_write_failure.patch: Don't invalidate sessions on write
-  failures.
-- patches/intolerance_options.patch: Add an option to further control
-  simulated TLS version intolerance.
-- patches/save_client_hello.patch: Save the parsed ClientHello on TLSConnection
-  so tests can query it.
-- patches/certificate_request.patch: Fix client auth for TLS 1.2.
-- patches/aes_gcm.patch: Implement AES-GCM and never select TLS 1.2 ciphers
-  unless >= TLS 1.2 is negotiated.
-- patches/alert_after_handshake.patch: Add an option to send a fatal alert
-  immediately after the handshake completes.
-- patches/ecdhe_rsa.patch: Implement ECDHE_RSA-based ciper suites on the server.
-- patches/extended_master_secret.patch: Add server support for extended
-  master secret.
-- patches/token_binding_negotiation.patch: Add server support for token
-  binding negotiation TLS extension (draft-ietf-tokbind-negotiation-02).
-- patches/disable_channel_id.patch: Add flag to HandshakeSettings to allow
-  for disabling channel id.
-- patches/exported_keying_material.patch: Add method to Session to get
-  exported keying material (RFC 5705) for use in e.g. Token Binding.
-- patches/token_binding_resumption.patch: Fix token binding negotiation
-  extension to work on session resumption.
-- patches/extension_number_update.patch: Update TLS extension numbers.
-- patches/save_randoms.patch: Save client and server randoms when resuming
-  sessions.
-- patches/alpn.path: Implement Application-Layer Protocol Negotiation Extension.
-- patches/token_binding_version.patch: Update the Token Binding version number.
-- patches/renegotiation_indication.patch: Implement the renegotiation
-  indication extension (RFC 5746) without supporting renegotiation.
-- patches/tls13_intolerance.patch: Extend the intolerance simulation to TLS 1.3.
-- patches/simulate_tls13_downgrade.patch: Add an option to simulate the TLS 1.3
-  downgrade signal.
-- patches/thread_safe_python_rsa_key.patch: Make Python_RSAKey thread safe,
-  inspired by tlslite-ng implementation.
-- patches/signature_algorithms.patch: Add basic signature algorithms
-  negotiation.
-- patches/python3.patch: Fix with Python 3.
diff --git a/third_party/tlslite/patches/aes_gcm.patch b/third_party/tlslite/patches/aes_gcm.patch
deleted file mode 100644
index 9d4768dd..0000000
--- a/third_party/tlslite/patches/aes_gcm.patch
+++ /dev/null
@@ -1,770 +0,0 @@
-diff --git a/third_party/tlslite/tests/tlstest.py b/third_party/tlslite/tests/tlstest.py
-index fa1b13f..7985d23 100755
---- a/third_party/tlslite/tests/tlstest.py
-+++ b/third_party/tlslite/tests/tlstest.py
-@@ -318,9 +318,11 @@ def clientTestCmd(argv):
- 
-     print("Test 23 - throughput test")
-     for implementation in implementations:
--        for cipher in ["aes128", "aes256", "3des", "rc4"]:
-+        for cipher in ["aes128gcm", "aes128", "aes256", "3des", "rc4"]:
-             if cipher == "3des" and implementation not in ("openssl", "pycrypto"):
-                 continue
-+            if cipher == "aes128gcm" and implementation not in ("pycrypto", "python"):
-+                continue
- 
-             print("Test 23:", end=' ')
-             connection = connect()
-@@ -678,9 +680,11 @@ def serverTestCmd(argv):
- 
-     print("Test 23 - throughput test")
-     for implementation in implementations:
--        for cipher in ["aes128", "aes256", "3des", "rc4"]:
-+        for cipher in ["aes128gcm", "aes128", "aes256", "3des", "rc4"]:
-             if cipher == "3des" and implementation not in ("openssl", "pycrypto"):
-                 continue
-+            if cipher == "aes128gcm" and implementation not in ("pycrypto", "python"):
-+                continue
- 
-             print("Test 23:", end=' ')
-             connection = connect()
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 7ee70be..e5b88af 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -175,6 +175,9 @@ class CipherSuite:
-     TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
-     TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
- 
-+    TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
-+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
-+
-     tripleDESSuites = []
-     tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-     tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-@@ -199,6 +202,10 @@ class CipherSuite:
-     aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-     aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
- 
-+    aes128GcmSuites = []
-+    aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-+    aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-+
-     rc4Suites = []
-     rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
-     rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5)
-@@ -225,25 +232,35 @@ class CipherSuite:
-     sha256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-     sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-     sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-+    sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-+    sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-+
-+    aeadSuites = aes128GcmSuites
- 
- 
-     md5Suites = []
-     md5Suites.append(TLS_RSA_WITH_RC4_128_MD5)
- 
-     @staticmethod
--    def _filterSuites(suites, settings):
-+    def _filterSuites(suites, settings, version=None):
-+        if version is None:
-+            version = settings.maxVersion
-         macNames = settings.macNames
-         cipherNames = settings.cipherNames
-         keyExchangeNames = settings.keyExchangeNames
-         macSuites = []
-         if "sha" in macNames:
-             macSuites += CipherSuite.shaSuites
--        if "sha256" in macNames:
-+        if "sha256" in macNames and version >= (3,3):
-             macSuites += CipherSuite.sha256Suites
-         if "md5" in macNames:
-             macSuites += CipherSuite.md5Suites
-+        if "aead" in macNames and version >= (3,3):
-+            macSuites += CipherSuite.aeadSuites
- 
-         cipherSuites = []
-+        if "aes128gcm" in cipherNames and version >= (3,3):
-+            cipherSuites += CipherSuite.aes128GcmSuites
-         if "aes128" in cipherNames:
-             cipherSuites += CipherSuite.aes128Suites
-         if "aes256" in cipherNames:
-@@ -274,8 +291,8 @@ class CipherSuite:
-     srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-     
-     @staticmethod
--    def getSrpSuites(settings):
--        return CipherSuite._filterSuites(CipherSuite.srpSuites, settings)
-+    def getSrpSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.srpSuites, settings, version)
- 
-     srpCertSuites = []
-     srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
-@@ -283,16 +300,17 @@ class CipherSuite:
-     srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-     
-     @staticmethod
--    def getSrpCertSuites(settings):
--        return CipherSuite._filterSuites(CipherSuite.srpCertSuites, settings)
-+    def getSrpCertSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.srpCertSuites, settings, version)
- 
-     srpAllSuites = srpSuites + srpCertSuites
- 
-     @staticmethod
--    def getSrpAllSuites(settings):
--        return CipherSuite._filterSuites(CipherSuite.srpAllSuites, settings)
-+    def getSrpAllSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.srpAllSuites, settings, version)
- 
-     certSuites = []
-+    certSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-     certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-     certSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-     certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
-@@ -302,10 +320,11 @@ class CipherSuite:
-     certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
-     
-     @staticmethod
--    def getCertSuites(settings):
--        return CipherSuite._filterSuites(CipherSuite.certSuites, settings)
-+    def getCertSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.certSuites, settings, version)
- 
-     dheCertSuites = []
-+    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-     dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-     dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-     dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-@@ -313,8 +332,8 @@ class CipherSuite:
-     dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
- 
-     @staticmethod
--    def getDheCertSuites(settings):
--        return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings)
-+    def getDheCertSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, version)
- 
-     certAllSuites = srpCertSuites + certSuites + dheCertSuites
- 
-@@ -323,8 +342,8 @@ class CipherSuite:
-     anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-     
-     @staticmethod
--    def getAnonSuites(settings):
--        return CipherSuite._filterSuites(CipherSuite.anonSuites, settings)
-+    def getAnonSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, version)
- 
-     dhAllSuites = dheCertSuites + anonSuites
- 
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index 2e9e06d..2f11aaa 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -11,11 +11,9 @@ from .constants import CertificateType
- from .utils import cryptomath
- from .utils import cipherfactory
- 
--# RC4 is preferred as faster in Python, works in SSL3, and immune to CBC
--# issues such as timing attacks
--CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"]
--MAC_NAMES = ["sha", "sha256"] # Don't allow "md5" by default.
--ALL_MAC_NAMES = ["sha", "sha256", "md5"]
-+CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"]
-+MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default.
-+ALL_MAC_NAMES = MAC_NAMES + ["md5"]
- KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
- CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
- CERTIFICATE_TYPES = ["x509"]
-@@ -42,7 +40,7 @@ class HandshakeSettings(object):
-     The default is 8193.
- 
-     @type cipherNames: list
--    @ivar cipherNames: The allowed ciphers, in order of preference.
-+    @ivar cipherNames: The allowed ciphers.
- 
-     The allowed values in this list are 'aes256', 'aes128', '3des', and
-     'rc4'.  If these settings are used with a client handshake, they
-@@ -68,8 +66,7 @@ class HandshakeSettings(object):
- 
- 
-     @type certificateTypes: list
--    @ivar certificateTypes: The allowed certificate types, in order of
--    preference.
-+    @ivar certificateTypes: The allowed certificate types.
- 
-     The only allowed certificate type is 'x509'.  This list is only used with a
-     client handshake.  The client will advertise to the server which certificate
-@@ -197,10 +194,6 @@ class HandshakeSettings(object):
-         if not other.maxVersion in ((3,0), (3,1), (3,2), (3,3)):
-             raise ValueError("maxVersion set incorrectly")
- 
--        if other.maxVersion < (3,3):
--            # No sha256 pre TLS 1.2
--            other.macNames = [e for e in self.macNames if e != "sha256"]
--
-         return other
- 
-     def _getCertificateTypes(self):
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 3d97e97..0e13a78 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1385,21 +1385,6 @@ class TLSConnection(TLSRecordLayer):
- 
-     def _serverGetClientHello(self, settings, certChain, verifierDB,
-                                 sessionCache, anon, fallbackSCSV):
--        #Initialize acceptable cipher suites
--        cipherSuites = []
--        if verifierDB:
--            if certChain:
--                cipherSuites += \
--                    CipherSuite.getSrpCertSuites(settings)
--            cipherSuites += CipherSuite.getSrpSuites(settings)
--        elif certChain:
--            cipherSuites += CipherSuite.getDheCertSuites(settings)
--            cipherSuites += CipherSuite.getCertSuites(settings)
--        elif anon:
--            cipherSuites += CipherSuite.getAnonSuites(settings)
--        else:
--            assert(False)
--
-         #Tentatively set version to most-desirable version, so if an error
-         #occurs parsing the ClientHello, this is what we'll use for the
-         #error alert
-@@ -1451,7 +1436,22 @@ class TLSConnection(TLSRecordLayer):
- 
-         else:
-             #Set the version to the client's version
--            self.version = clientHello.client_version  
-+            self.version = clientHello.client_version
-+
-+        #Initialize acceptable cipher suites
-+        cipherSuites = []
-+        if verifierDB:
-+            if certChain:
-+                cipherSuites += \
-+                    CipherSuite.getSrpCertSuites(settings, self.version)
-+            cipherSuites += CipherSuite.getSrpSuites(settings, self.version)
-+        elif certChain:
-+            cipherSuites += CipherSuite.getDheCertSuites(settings, self.version)
-+            cipherSuites += CipherSuite.getCertSuites(settings, self.version)
-+        elif anon:
-+            cipherSuites += CipherSuite.getAnonSuites(settings, self.version)
-+        else:
-+            assert(False)
- 
-         #If resumption was requested and we have a session cache...
-         if clientHello.session_id and sessionCache:
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index a09499d..c3bcd8c 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -11,7 +11,8 @@ from __future__ import generators
- 
- from .utils.compat import *
- from .utils.cryptomath import *
--from .utils.cipherfactory import createAES, createRC4, createTripleDES
-+from .utils.cipherfactory import createAESGCM, createAES, createRC4, \
-+     createTripleDES
- from .utils.codec import *
- from .errors import *
- from .messages import *
-@@ -592,10 +593,30 @@ class TLSRecordLayer(object):
-             if self.fault == Fault.badMAC:
-                 macBytes[0] = (macBytes[0]+1) % 256
- 
--        #Encrypt for Block or Stream Cipher
-+        #Encrypt for non-NULL cipher.
-         if self._writeState.encContext:
-+            #Seal (for AEAD)
-+            if self._writeState.encContext.isAEAD:
-+                #Assemble the authenticated data.
-+                seqNumBytes = self._writeState.getSeqNumBytes()
-+                authData = seqNumBytes + bytearray([contentType,
-+                                                    self.version[0],
-+                                                    self.version[1],
-+                                                    len(b)//256,
-+                                                    len(b)%256])
-+
-+                #The nonce is always the fixed nonce and the sequence number.
-+                nonce = self._writeState.fixedNonce + seqNumBytes
-+                assert len(nonce) == self._writeState.encContext.nonceLength
-+
-+                b = self._writeState.encContext.seal(nonce, b, authData)
-+
-+                #The only AEAD supported, AES-GCM, has an explicit variable
-+                #nonce.
-+                b = seqNumBytes + b
-+
-             #Add padding and encrypt (for Block Cipher):
--            if self._writeState.encContext.isBlockCipher:
-+            elif self._writeState.encContext.isBlockCipher:
- 
-                 #Add TLS 1.1 fixed block
-                 if self.version >= (3,2):
-@@ -967,6 +988,43 @@ class TLSRecordLayer(object):
- 
-     def _decryptRecord(self, recordType, b):
-         if self._readState.encContext:
-+            #Open if it's an AEAD.
-+            if self._readState.encContext.isAEAD:
-+                #The only AEAD supported, AES-GCM, has an explicit variable
-+                #nonce.
-+                explicitNonceLength = 8
-+                if explicitNonceLength > len(b):
-+                    #Publicly invalid.
-+                    for result in self._sendError(
-+                            AlertDescription.bad_record_mac,
-+                            "MAC failure (or padding failure)"):
-+                        yield result
-+                nonce = self._readState.fixedNonce + b[:explicitNonceLength]
-+                b = b[8:]
-+
-+                if self._readState.encContext.tagLength > len(b):
-+                    #Publicly invalid.
-+                    for result in self._sendError(
-+                            AlertDescription.bad_record_mac,
-+                            "MAC failure (or padding failure)"):
-+                        yield result
-+
-+                #Assemble the authenticated data.
-+                seqnumBytes = self._readState.getSeqNumBytes()
-+                plaintextLen = len(b) - self._readState.encContext.tagLength
-+                authData = seqnumBytes + bytearray([recordType, self.version[0],
-+                                                    self.version[1],
-+                                                    plaintextLen//256,
-+                                                    plaintextLen%256])
-+
-+                b = self._readState.encContext.open(nonce, b, authData)
-+                if b is None:
-+                    for result in self._sendError(
-+                            AlertDescription.bad_record_mac,
-+                            "MAC failure (or padding failure)"):
-+                        yield result
-+                yield b
-+                return
- 
-             #Decrypt if it's a block cipher
-             if self._readState.encContext.isBlockCipher:
-@@ -1064,7 +1122,11 @@ class TLSRecordLayer(object):
- 
-     def _calcPendingStates(self, cipherSuite, masterSecret,
-             clientRandom, serverRandom, implementations):
--        if cipherSuite in CipherSuite.aes128Suites:
-+        if cipherSuite in CipherSuite.aes128GcmSuites:
-+            keyLength = 16
-+            ivLength = 4
-+            createCipherFunc = createAESGCM
-+        elif cipherSuite in CipherSuite.aes128Suites:
-             keyLength = 16
-             ivLength = 16
-             createCipherFunc = createAES
-@@ -1083,7 +1145,10 @@ class TLSRecordLayer(object):
-         else:
-             raise AssertionError()
-             
--        if cipherSuite in CipherSuite.shaSuites:
-+        if cipherSuite in CipherSuite.aeadSuites:
-+            macLength = 0
-+            digestmod = None
-+        elif cipherSuite in CipherSuite.shaSuites:
-             macLength = 20
-             digestmod = hashlib.sha1        
-         elif cipherSuite in CipherSuite.sha256Suites:
-@@ -1092,8 +1157,12 @@ class TLSRecordLayer(object):
-         elif cipherSuite in CipherSuite.md5Suites:
-             macLength = 16
-             digestmod = hashlib.md5
-+        else:
-+            raise AssertionError()
- 
--        if self.version == (3,0):
-+        if not digestmod:
-+            createMACFunc = None
-+        elif self.version == (3,0):
-             createMACFunc = createMAC_SSL
-         elif self.version in ((3,1), (3,2), (3,3)):
-             createMACFunc = createHMAC
-@@ -1128,16 +1197,28 @@ class TLSRecordLayer(object):
-         serverKeyBlock = p.getFixBytes(keyLength)
-         clientIVBlock  = p.getFixBytes(ivLength)
-         serverIVBlock  = p.getFixBytes(ivLength)
--        clientPendingState.macContext = createMACFunc(
--            compatHMAC(clientMACBlock), digestmod=digestmod)
--        serverPendingState.macContext = createMACFunc(
--            compatHMAC(serverMACBlock), digestmod=digestmod)
--        clientPendingState.encContext = createCipherFunc(clientKeyBlock,
--                                                         clientIVBlock,
--                                                         implementations)
--        serverPendingState.encContext = createCipherFunc(serverKeyBlock,
--                                                         serverIVBlock,
--                                                         implementations)
-+        if digestmod:
-+            # Legacy cipher.
-+            clientPendingState.macContext = createMACFunc(
-+                compatHMAC(clientMACBlock), digestmod=digestmod)
-+            serverPendingState.macContext = createMACFunc(
-+                compatHMAC(serverMACBlock), digestmod=digestmod)
-+            clientPendingState.encContext = createCipherFunc(clientKeyBlock,
-+                                                             clientIVBlock,
-+                                                             implementations)
-+            serverPendingState.encContext = createCipherFunc(serverKeyBlock,
-+                                                             serverIVBlock,
-+                                                             implementations)
-+        else:
-+            # AEAD.
-+            clientPendingState.macContext = None
-+            serverPendingState.macContext = None
-+            clientPendingState.encContext = createCipherFunc(clientKeyBlock,
-+                                                             implementations)
-+            serverPendingState.encContext = createCipherFunc(serverKeyBlock,
-+                                                             implementations)
-+            clientPendingState.fixedNonce = clientIVBlock
-+            serverPendingState.fixedNonce = serverIVBlock
- 
-         #Assign new connection states to pending states
-         if self._client:
-diff --git a/third_party/tlslite/tlslite/utils/aes.py b/third_party/tlslite/tlslite/utils/aes.py
-index 95afaa3..5a038fb 100644
---- a/third_party/tlslite/tlslite/utils/aes.py
-+++ b/third_party/tlslite/tlslite/utils/aes.py
-@@ -12,6 +12,7 @@ class AES(object):
-         if len(IV) != 16:
-             raise AssertionError()
-         self.isBlockCipher = True
-+        self.isAEAD = False
-         self.block_size = 16
-         self.implementation = implementation
-         if len(key)==16:
-@@ -31,4 +32,4 @@ class AES(object):
-     #CBC-Mode decryption, returns plaintext
-     #WARNING: *MAY* modify the input as well
-     def decrypt(self, ciphertext):
--        assert(len(ciphertext) % 16 == 0)
-\ No newline at end of file
-+        assert(len(ciphertext) % 16 == 0)
-diff --git a/third_party/tlslite/tlslite/utils/aesgcm.py b/third_party/tlslite/tlslite/utils/aesgcm.py
-new file mode 100644
-index 0000000..7319c26
---- /dev/null
-+++ b/third_party/tlslite/tlslite/utils/aesgcm.py
-@@ -0,0 +1,193 @@
-+# Author: Google
-+# See the LICENSE file for legal information regarding use of this file.
-+
-+# GCM derived from Go's implementation in crypto/cipher.
-+#
-+# https://golang.org/src/crypto/cipher/gcm.go
-+
-+# GCM works over elements of the field GF(2^128), each of which is a 128-bit
-+# polynomial. Throughout this implementation, polynomials are represented as
-+# Python integers with the low-order terms at the most significant bits. So a
-+# 128-bit polynomial is an integer from 0 to 2^128-1 with the most significant
-+# bit representing the x^0 term and the least significant bit representing the
-+# x^127 term. This bit reversal also applies to polynomials used as indices in a
-+# look-up table.
-+
-+from .cryptomath import bytesToNumber, numberToByteArray
-+
-+class AESGCM(object):
-+    """
-+    AES-GCM implementation. Note: this implementation does not attempt
-+    to be side-channel resistant. It's also rather slow.
-+    """
-+
-+    def __init__(self, key, implementation, rawAesEncrypt):
-+        self.isBlockCipher = False
-+        self.isAEAD = True
-+        self.nonceLength = 12
-+        self.tagLength = 16
-+        self.implementation = implementation
-+        if len(key) == 16:
-+            self.name = "aes128gcm"
-+        elif len(key) == 32:
-+            self.name = "aes256gcm"
-+        else:
-+            raise AssertionError()
-+
-+        self._rawAesEncrypt = rawAesEncrypt
-+
-+        # The GCM key is AES(0).
-+        h = bytesToNumber(self._rawAesEncrypt(bytearray(16)))
-+
-+        # Pre-compute all 4-bit multiples of h. Note that bits are reversed
-+        # because our polynomial representation places low-order terms at the
-+        # most significant bit. Thus x^0 * h = h is at index 0b1000 = 8 and
-+        # x^1 * h is at index 0b0100 = 4.
-+        self._productTable = [0] * 16
-+        self._productTable[_reverseBits(1)] = h
-+        for i in range(2, 16, 2):
-+            self._productTable[_reverseBits(i)] = \
-+                _gcmShift(self._productTable[_reverseBits(i/2)])
-+            self._productTable[_reverseBits(i+1)] = \
-+                _gcmAdd(self._productTable[_reverseBits(i)], h)
-+
-+    def _rawAesCtrEncrypt(self, counter, inp):
-+        """
-+        Encrypts (or decrypts) plaintext with AES-CTR. counter is modified.
-+        """
-+        out = bytearray(len(inp))
-+        for i in range(0, len(out), 16):
-+            mask = self._rawAesEncrypt(counter)
-+            for j in range(i, min(len(out), i + 16)):
-+                out[j] = inp[j] ^ mask[j-i]
-+            _inc32(counter)
-+        return out
-+
-+    def _auth(self, ciphertext, ad, tagMask):
-+        y = 0
-+        y = self._update(y, ad)
-+        y = self._update(y, ciphertext)
-+        y ^= (len(ad) << (3 + 64)) | (len(ciphertext) << 3)
-+        y = self._mul(y)
-+        y ^= bytesToNumber(tagMask)
-+        return numberToByteArray(y, 16)
-+
-+    def _update(self, y, data):
-+        for i in range(0, len(data) // 16):
-+            y ^= bytesToNumber(data[16*i:16*i+16])
-+            y = self._mul(y)
-+        extra = len(data) % 16
-+        if extra != 0:
-+            block = bytearray(16)
-+            block[:extra] = data[-extra:]
-+            y ^= bytesToNumber(block)
-+            y = self._mul(y)
-+        return y
-+
-+    def _mul(self, y):
-+        """ Returns y*H, where H is the GCM key. """
-+        ret = 0
-+        # Multiply H by y 4 bits at a time, starting with the highest power
-+        # terms.
-+        for i in range(0, 128, 4):
-+            # Multiply by x^4. The reduction for the top four terms is
-+            # precomputed.
-+            retHigh = ret & 0xf
-+            ret >>= 4
-+            ret ^= (_gcmReductionTable[retHigh] << (128-16))
-+
-+            # Add in y' * H where y' are the next four terms of y, shifted down
-+            # to the x^0..x^4. This is one of the pre-computed multiples of
-+            # H. The multiplication by x^4 shifts them back into place.
-+            ret ^= self._productTable[y & 0xf]
-+            y >>= 4
-+        assert y == 0
-+        return ret
-+
-+    def seal(self, nonce, plaintext, data):
-+        """
-+        Encrypts and authenticates plaintext using nonce and data. Returns the
-+        ciphertext, consisting of the encrypted plaintext and tag concatenated.
-+        """
-+
-+        if len(nonce) != 12:
-+            raise ValueError("Bad nonce length")
-+
-+        # The initial counter value is the nonce, followed by a 32-bit counter
-+        # that starts at 1. It's used to compute the tag mask.
-+        counter = bytearray(16)
-+        counter[:12] = nonce
-+        counter[-1] = 1
-+        tagMask = self._rawAesEncrypt(counter)
-+
-+        # The counter starts at 2 for the actual encryption.
-+        counter[-1] = 2
-+        ciphertext = self._rawAesCtrEncrypt(counter, plaintext)
-+
-+        tag = self._auth(ciphertext, data, tagMask)
-+
-+        return ciphertext + tag
-+
-+    def open(self, nonce, ciphertext, data):
-+        """
-+        Decrypts and authenticates ciphertext using nonce and data. If the
-+        tag is valid, the plaintext is returned. If the tag is invalid,
-+        returns None.
-+        """
-+
-+        if len(nonce) != 12:
-+            raise ValueError("Bad nonce length")
-+        if len(ciphertext) < 16:
-+            return None
-+
-+        tag = ciphertext[-16:]
-+        ciphertext = ciphertext[:-16]
-+
-+        # The initial counter value is the nonce, followed by a 32-bit counter
-+        # that starts at 1. It's used to compute the tag mask.
-+        counter = bytearray(16)
-+        counter[:12] = nonce
-+        counter[-1] = 1
-+        tagMask = self._rawAesEncrypt(counter)
-+
-+        if tag != self._auth(ciphertext, data, tagMask):
-+            return None
-+
-+        # The counter starts at 2 for the actual decryption.
-+        counter[-1] = 2
-+        return self._rawAesCtrEncrypt(counter, ciphertext)
-+
-+def _reverseBits(i):
-+    assert i < 16
-+    i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
-+    i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
-+    return i
-+
-+def _gcmAdd(x, y):
-+    return x ^ y
-+
-+def _gcmShift(x):
-+    # Multiplying by x is a right shift, due to bit order.
-+    highTermSet = x & 1
-+    x >>= 1
-+    if highTermSet:
-+        # The x^127 term was shifted up to x^128, so subtract a 1+x+x^2+x^7
-+        # term. This is 0b11100001 or 0xe1 when represented as an 8-bit
-+        # polynomial.
-+        x ^= 0xe1 << (128-8)
-+    return x
-+
-+def _inc32(counter):
-+    for i in range(len(counter)-1, len(counter)-5, -1):
-+        counter[i] = (counter[i] + 1) % 256
-+        if counter[i] != 0:
-+            break
-+    return counter
-+
-+# _gcmReductionTable[i] is i * (1+x+x^2+x^7) for all 4-bit polynomials i. The
-+# result is stored as a 16-bit polynomial. This is used in the reduction step to
-+# multiply elements of GF(2^128) by x^4.
-+_gcmReductionTable = [
-+    0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
-+    0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
-+]
-diff --git a/third_party/tlslite/tlslite/utils/cipherfactory.py b/third_party/tlslite/tlslite/utils/cipherfactory.py
-index 20e20f1..d525644 100644
---- a/third_party/tlslite/tlslite/utils/cipherfactory.py
-+++ b/third_party/tlslite/tlslite/utils/cipherfactory.py
-@@ -6,6 +6,7 @@
- import os
- 
- from tlslite.utils import python_aes
-+from tlslite.utils import python_aesgcm
- from tlslite.utils import python_rc4
- 
- from tlslite.utils import cryptomath
-@@ -20,6 +21,7 @@ if cryptomath.m2cryptoLoaded:
- 
- if cryptomath.pycryptoLoaded:
-     from tlslite.utils import pycrypto_aes
-+    from tlslite.utils import pycrypto_aesgcm
-     from tlslite.utils import pycrypto_rc4
-     from tlslite.utils import pycrypto_tripledes
-     tripleDESPresent = True
-@@ -52,6 +54,25 @@ def createAES(key, IV, implList=None):
-             return python_aes.new(key, 2, IV)
-     raise NotImplementedError()
- 
-+def createAESGCM(key, implList=None):
-+    """Create a new AESGCM object.
-+
-+    @type key: bytearray
-+    @param key: A 16 or 32 byte byte array.
-+
-+    @rtype: L{tlslite.utils.AESGCM}
-+    @return: An AESGCM object.
-+    """
-+    if implList == None:
-+        implList = ["pycrypto", "python"]
-+
-+    for impl in implList:
-+        if impl == "pycrypto" and cryptomath.pycryptoLoaded:
-+            return pycrypto_aesgcm.new(key)
-+        if impl == "python":
-+            return python_aesgcm.new(key)
-+    raise NotImplementedError()
-+
- def createRC4(key, IV, implList=None):
-     """Create a new RC4 object.
- 
-@@ -99,4 +120,4 @@ def createTripleDES(key, IV, implList=None):
-             return openssl_tripledes.new(key, 2, IV)
-         elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
-             return pycrypto_tripledes.new(key, 2, IV)
--    raise NotImplementedError()
-\ No newline at end of file
-+    raise NotImplementedError()
-diff --git a/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py b/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
-new file mode 100644
-index 0000000..ee187ee
---- /dev/null
-+++ b/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
-@@ -0,0 +1,16 @@
-+# Author: Google
-+# See the LICENSE file for legal information regarding use of this file.
-+
-+"""PyCrypto AES-GCM implementation."""
-+
-+from .cryptomath import *
-+from .aesgcm import AESGCM
-+
-+if pycryptoLoaded:
-+    import Crypto.Cipher.AES
-+
-+    def new(key):
-+        cipher = Crypto.Cipher.AES.new(bytes(key))
-+        def encrypt(plaintext):
-+            return bytearray(cipher.encrypt(bytes(plaintext)))
-+        return AESGCM(key, "pycrypto", encrypt)
-diff --git a/third_party/tlslite/tlslite/utils/python_aesgcm.py b/third_party/tlslite/tlslite/utils/python_aesgcm.py
-new file mode 100644
-index 0000000..80a5fd5
---- /dev/null
-+++ b/third_party/tlslite/tlslite/utils/python_aesgcm.py
-@@ -0,0 +1,10 @@
-+# Author: Google
-+# See the LICENSE file for legal information regarding use of this file.
-+
-+"""Pure-Python AES-GCM implementation."""
-+
-+from .aesgcm import AESGCM
-+from .rijndael import rijndael
-+
-+def new(key):
-+    return AESGCM(key, "python", rijndael(key, 16).encrypt)
-diff --git a/third_party/tlslite/tlslite/utils/rc4.py b/third_party/tlslite/tlslite/utils/rc4.py
-index 809026a..3853f5b 100644
---- a/third_party/tlslite/tlslite/utils/rc4.py
-+++ b/third_party/tlslite/tlslite/utils/rc4.py
-@@ -9,6 +9,7 @@ class RC4(object):
-         if len(keyBytes) < 16 or len(keyBytes) > 256:
-             raise ValueError()
-         self.isBlockCipher = False
-+        self.isAEAD = False
-         self.name = "rc4"
-         self.implementation = implementation
- 
-@@ -16,4 +17,4 @@ class RC4(object):
-         raise NotImplementedError()
- 
-     def decrypt(self, ciphertext):
--        raise NotImplementedError()
-\ No newline at end of file
-+        raise NotImplementedError()
-diff --git a/third_party/tlslite/tlslite/utils/tripledes.py b/third_party/tlslite/tlslite/utils/tripledes.py
-index 0b4d075..ddcdcad 100644
---- a/third_party/tlslite/tlslite/utils/tripledes.py
-+++ b/third_party/tlslite/tlslite/utils/tripledes.py
-@@ -12,6 +12,7 @@ class TripleDES(object):
-         if len(IV) != 8:
-             raise ValueError()
-         self.isBlockCipher = True
-+        self.isAEAD = False
-         self.block_size = 8
-         self.implementation = implementation
-         self.name = "3des"
diff --git a/third_party/tlslite/patches/alert_after_handshake.patch b/third_party/tlslite/patches/alert_after_handshake.patch
deleted file mode 100644
index c0650b1..0000000
--- a/third_party/tlslite/patches/alert_after_handshake.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index 2f11aaa..e752834 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -107,6 +107,10 @@ class HandshakeSettings(object):
-     
-     @type useExperimentalTackExtension: bool
-     @ivar useExperimentalTackExtension: Whether to enabled TACK support.
-+
-+    @type alertAfterHandshake: bool
-+    @ivar alertAfterHandshake: If true, the server will send a fatal
-+    alert immediately after the handshake completes.
-     
-     Note that TACK support is not standardized by IETF and uses a temporary
-     TLS Extension number, so should NOT be used in production software.
-@@ -124,6 +128,7 @@ class HandshakeSettings(object):
-         self.tlsIntolerant = None
-         self.tlsIntoleranceType = 'alert'
-         self.useExperimentalTackExtension = False
-+        self.alertAfterHandshake = False
- 
-     # Validates the min/max fields, and certificateTypes
-     # Filters out unsupported cipherNames and cipherImplementations
-@@ -140,6 +145,7 @@ class HandshakeSettings(object):
-         other.maxVersion = self.maxVersion
-         other.tlsIntolerant = self.tlsIntolerant
-         other.tlsIntoleranceType = self.tlsIntoleranceType
-+        other.alertAfterHandshake = self.alertAfterHandshake
- 
-         if not cipherfactory.tripleDESPresent:
-             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 0e13a78..eb850e9 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1221,6 +1221,10 @@ class TLSConnection(TLSRecordLayer):
-             ocspResponse=ocspResponse)
-         for result in self._handshakeWrapperAsync(handshaker, checker):
-             yield result
-+        if settings and settings.alertAfterHandshake:
-+            for result in self._sendError(AlertDescription.internal_error,
-+                                          "Spurious alert"):
-+                yield result
- 
- 
-     def _handshakeServerAsyncHelper(self, verifierDB,
diff --git a/third_party/tlslite/patches/alpn.patch b/third_party/tlslite/patches/alpn.patch
deleted file mode 100644
index 33d47d6..0000000
--- a/third_party/tlslite/patches/alpn.patch
+++ /dev/null
@@ -1,331 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 715def9..e9743e4 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -54,6 +54,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     status_request = 5  # RFC 6066 / 4366
-     srp = 12            # RFC 5054  
-     cert_type = 9       # RFC 6091
-+    alpn = 16           # RFC 7301
-     signed_cert_timestamps = 18  # RFC 6962
-     extended_master_secret = 23  # RFC 7627
-     token_binding = 24           # draft-ietf-tokbind-negotiation
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index d7be5b3..69fc6f4 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -128,6 +128,12 @@ class HandshakeSettings(object):
-     
-     Note that TACK support is not standardized by IETF and uses a temporary
-     TLS Extension number, so should NOT be used in production software.
-+
-+    @type alpnProtos: list of strings.
-+    @param alpnProtos: A list of supported upper layer protocols to use in the
-+    Application-Layer Protocol Negotiation Extension (RFC 7301).  For the
-+    client, the order does not matter.  For the server, the list is in
-+    decreasing order of preference.
-     """
-     def __init__(self):
-         self.minKeySize = 1023
-@@ -146,6 +152,7 @@ class HandshakeSettings(object):
-         self.enableChannelID = True
-         self.enableExtendedMasterSecret = True
-         self.supportedTokenBindingParams = []
-+        self.alpnProtos = None
- 
-     # Validates the min/max fields, and certificateTypes
-     # Filters out unsupported cipherNames and cipherImplementations
-@@ -166,6 +173,7 @@ class HandshakeSettings(object):
-         other.enableChannelID = self.enableChannelID
-         other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
-         other.supportedTokenBindingParams = self.supportedTokenBindingParams
-+        other.alpnProtos = self.alpnProtos;
- 
-         if not cipherfactory.tripleDESPresent:
-             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 5762ac6..1ce9320 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -18,6 +18,27 @@ from .x509 import X509
- from .x509certchain import X509CertChain
- from .utils.tackwrapper import *
- 
-+def parse_next_protos(b):
-+    protos = []
-+    while True:
-+        if len(b) == 0:
-+            break
-+        l = b[0]
-+        b = b[1:]
-+        if len(b) < l:
-+            raise BadNextProtos(len(b))
-+        protos.append(b[:l])
-+        b = b[l:]
-+    return protos
-+
-+def next_protos_encoded(protocol_list):
-+    b = bytearray()
-+    for e in protocol_list:
-+        if len(e) > 255 or len(e) == 0:
-+            raise BadNextProtos(len(e))
-+        b += bytearray( [len(e)] ) + bytearray(e)
-+    return b
-+
- class RecordHeader3(object):
-     def __init__(self):
-         self.type = 0
-@@ -111,6 +132,7 @@ class ClientHello(HandshakeMsg):
-         self.compression_methods = []   # a list of 8-bit values
-         self.srp_username = None        # a string
-         self.tack = False
-+        self.alpn_protos_advertised = None
-         self.supports_npn = False
-         self.server_name = bytearray(0)
-         self.channel_id = False
-@@ -121,7 +143,8 @@ class ClientHello(HandshakeMsg):
- 
-     def create(self, version, random, session_id, cipher_suites,
-                certificate_types=None, srpUsername=None,
--               tack=False, supports_npn=False, serverName=None):
-+               tack=False, alpn_protos_advertised=None,
-+               supports_npn=False, serverName=None):
-         self.client_version = version
-         self.random = random
-         self.session_id = session_id
-@@ -131,6 +154,7 @@ class ClientHello(HandshakeMsg):
-         if srpUsername:
-             self.srp_username = bytearray(srpUsername, "utf-8")
-         self.tack = tack
-+        self.alpn_protos_advertised = alpn_protos_advertised
-         self.supports_npn = supports_npn
-         if serverName:
-             self.server_name = bytearray(serverName, "utf-8")
-@@ -171,6 +195,11 @@ class ClientHello(HandshakeMsg):
-                         self.certificate_types = p.getVarList(1, 1)
-                     elif extType == ExtensionType.tack:
-                         self.tack = True
-+                    elif extType == ExtensionType.alpn:
-+                        structLength = p.get(2)
-+                        if structLength + 2 != extLength:
-+                            raise SyntaxError()
-+                        self.alpn_protos_advertised = parse_next_protos(p.getFixBytes(structLength))
-                     elif extType == ExtensionType.supports_npn:
-                         self.supports_npn = True
-                     elif extType == ExtensionType.server_name:
-@@ -243,6 +272,12 @@ class ClientHello(HandshakeMsg):
-             w2.add(ExtensionType.srp, 2)
-             w2.add(len(self.srp_username)+1, 2)
-             w2.addVarSeq(self.srp_username, 1, 1)
-+        if self.alpn_protos_advertised is not None:
-+            encoded_alpn_protos_advertised = next_protos_encoded(self.alpn_protos_advertised)
-+            w2.add(ExtensionType.alpn, 2)
-+            w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
-+            w2.add(len(encoded_alpn_protos_advertised), 2)
-+            w2.addFixSeq(encoded_alpn_protos_advertised, 1)
-         if self.supports_npn:
-             w2.add(ExtensionType.supports_npn, 2)
-             w2.add(0, 2)
-@@ -267,6 +302,13 @@ class BadNextProtos(Exception):
-     def __str__(self):
-         return 'Cannot encode a list of next protocols because it contains an element with invalid length %d. Element lengths must be 0 < x < 256' % self.length
- 
-+class InvalidALPNResponse(Exception):
-+    def __init__(self, l):
-+        self.length = l
-+
-+    def __str__(self):
-+        return 'ALPN server response protocol list has invalid length %d.  It must be of length one.' % self.length
-+
- class ServerHello(HandshakeMsg):
-     def __init__(self):
-         HandshakeMsg.__init__(self, HandshakeType.server_hello)
-@@ -277,6 +319,7 @@ class ServerHello(HandshakeMsg):
-         self.certificate_type = CertificateType.x509
-         self.compression_method = 0
-         self.tackExt = None
-+        self.alpn_proto_selected = None
-         self.next_protos_advertised = None
-         self.next_protos = None
-         self.channel_id = False
-@@ -286,7 +329,8 @@ class ServerHello(HandshakeMsg):
-         self.status_request = False
- 
-     def create(self, version, random, session_id, cipher_suite,
--               certificate_type, tackExt, next_protos_advertised):
-+               certificate_type, tackExt, alpn_proto_selected,
-+               next_protos_advertised):
-         self.server_version = version
-         self.random = random
-         self.session_id = session_id
-@@ -294,6 +338,7 @@ class ServerHello(HandshakeMsg):
-         self.certificate_type = certificate_type
-         self.compression_method = 0
-         self.tackExt = tackExt
-+        self.alpn_proto_selected = alpn_proto_selected
-         self.next_protos_advertised = next_protos_advertised
-         return self
- 
-@@ -316,35 +361,22 @@ class ServerHello(HandshakeMsg):
-                     self.certificate_type = p.get(1)
-                 elif extType == ExtensionType.tack and tackpyLoaded:
-                     self.tackExt = TackExtension(p.getFixBytes(extLength))
-+                elif extType == ExtensionType.alpn:
-+                    structLength = p.get(2)
-+                    if structLength + 2 != extLength:
-+                        raise SyntaxError()
-+                    alpn_protos = parse_next_protos(p.getFixBytes(structLength))
-+                    if len(alpn_protos) != 1:
-+                        raise InvalidALPNResponse(len(alpn_protos));
-+                    self.alpn_proto_selected = alpn_protos[0]
-                 elif extType == ExtensionType.supports_npn:
--                    self.next_protos = self.__parse_next_protos(p.getFixBytes(extLength))
-+                    self.next_protos = parse_next_protos(p.getFixBytes(extLength))
-                 else:
-                     p.getFixBytes(extLength)
-                 soFar += 4 + extLength
-         p.stopLengthCheck()
-         return self
- 
--    def __parse_next_protos(self, b):
--        protos = []
--        while True:
--            if len(b) == 0:
--                break
--            l = b[0]
--            b = b[1:]
--            if len(b) < l:
--                raise BadNextProtos(len(b))
--            protos.append(b[:l])
--            b = b[l:]
--        return protos
--
--    def __next_protos_encoded(self):
--        b = bytearray()
--        for e in self.next_protos_advertised:
--            if len(e) > 255 or len(e) == 0:
--                raise BadNextProtos(len(e))
--            b += bytearray( [len(e)] ) + bytearray(e)
--        return b
--
-     def write(self):
-         w = Writer()
-         w.add(self.server_version[0], 1)
-@@ -365,8 +397,15 @@ class ServerHello(HandshakeMsg):
-             w2.add(ExtensionType.tack, 2)
-             w2.add(len(b), 2)
-             w2.bytes += b
-+        if self.alpn_proto_selected is not None:
-+            alpn_protos_single_element_list = [self.alpn_proto_selected]
-+            encoded_alpn_protos_advertised = next_protos_encoded(alpn_protos_single_element_list)
-+            w2.add(ExtensionType.alpn, 2)
-+            w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
-+            w2.add(len(encoded_alpn_protos_advertised), 2)
-+            w2.addFixSeq(encoded_alpn_protos_advertised, 1)
-         if self.next_protos_advertised is not None:
--            encoded_next_protos_advertised = self.__next_protos_encoded()
-+            encoded_next_protos_advertised = next_protos_encoded(self.next_protos_advertised)
-             w2.add(ExtensionType.supports_npn, 2)
-             w2.add(len(encoded_next_protos_advertised), 2)
-             w2.addFixSeq(encoded_next_protos_advertised, 1)
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 41aab85..de5d580 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -495,6 +495,10 @@ class TLSConnection(TLSRecordLayer):
-             settings = HandshakeSettings()
-         settings = settings._filter()
- 
-+        if settings.alpnProtos is not None:
-+            if len(settings.alpnProtos) == 0:
-+                raise ValueError("Caller passed no alpnProtos")
-+
-         if clientCertChain:
-             if not isinstance(clientCertChain, X509CertChain):
-                 raise ValueError("Unrecognized certificate type")
-@@ -651,7 +655,8 @@ class TLSConnection(TLSRecordLayer):
-                                    session.sessionID, cipherSuites,
-                                    certificateTypes, 
-                                    session.srpUsername,
--                                   reqTack, nextProtos is not None,
-+                                   reqTack, settings.alpnProtos,
-+                                   nextProtos is not None,
-                                    session.serverName)
- 
-         #Or send ClientHello (without)
-@@ -661,7 +666,8 @@ class TLSConnection(TLSRecordLayer):
-                                bytearray(0), cipherSuites,
-                                certificateTypes, 
-                                srpUsername,
--                               reqTack, nextProtos is not None, 
-+                               reqTack, settings.alpnProtos,
-+                               nextProtos is not None,
-                                serverName)
-         for result in self._sendMsg(clientHello):
-             yield result
-@@ -714,6 +720,16 @@ class TLSConnection(TLSRecordLayer):
-                     AlertDescription.illegal_parameter,
-                     "Server responded with unrequested Tack Extension"):
-                     yield result
-+        if serverHello.alpn_proto_selected and not clientHello.alpn_protos_advertised:
-+            for result in self._sendError(\
-+                AlertDescription.illegal_parameter,
-+                "Server responded with unrequested ALPN Extension"):
-+                yield result
-+        if serverHello.alpn_proto_selected and serverHello.next_protos:
-+            for result in self._sendError(\
-+                AlertDescription.illegal_parameter,
-+                "Server responded with both ALPN and NPN extension"):
-+                yield result
-         if serverHello.next_protos and not clientHello.supports_npn:
-             for result in self._sendError(\
-                 AlertDescription.illegal_parameter,
-@@ -1315,6 +1331,15 @@ class TLSConnection(TLSRecordLayer):
-         else:
-             sessionID = bytearray(0)
-         
-+        alpn_proto_selected = None
-+        if (clientHello.alpn_protos_advertised is not None
-+                and settings.alpnProtos is not None):
-+            for proto in settings.alpnProtos:
-+                if proto in clientHello.alpn_protos_advertised:
-+                    alpn_proto_selected = proto
-+                    nextProtos = None
-+                    break;
-+
-         if not clientHello.supports_npn:
-             nextProtos = None
- 
-@@ -1330,6 +1355,7 @@ class TLSConnection(TLSRecordLayer):
-         serverHello = ServerHello()
-         serverHello.create(self.version, getRandomBytes(32), sessionID, \
-                             cipherSuite, CertificateType.x509, tackExt,
-+                            alpn_proto_selected,
-                             nextProtos)
-         serverHello.channel_id = \
-             clientHello.channel_id and settings.enableChannelID
-@@ -1500,6 +1526,14 @@ class TLSConnection(TLSRecordLayer):
-         else:
-             assert(False)
- 
-+        alpn_proto_selected = None
-+        if (clientHello.alpn_protos_advertised is not None
-+                and settings.alpnProtos is not None):
-+            for proto in settings.alpnProtos:
-+                if proto in clientHello.alpn_protos_advertised:
-+                    alpn_proto_selected = proto
-+                    break;
-+
-         #If resumption was requested and we have a session cache...
-         if clientHello.session_id and sessionCache:
-             session = None
-@@ -1540,7 +1574,8 @@ class TLSConnection(TLSRecordLayer):
-                 serverHello = ServerHello()
-                 serverHello.create(self.version, getRandomBytes(32),
-                                    session.sessionID, session.cipherSuite,
--                                   CertificateType.x509, None, None)
-+                                   CertificateType.x509, None,
-+                                   alpn_proto_selected, None)
-                 serverHello.extended_master_secret = \
-                     clientHello.extended_master_secret and \
-                     settings.enableExtendedMasterSecret
diff --git a/third_party/tlslite/patches/certificate_request.patch b/third_party/tlslite/patches/certificate_request.patch
deleted file mode 100644
index cdfa72b..0000000
--- a/third_party/tlslite/patches/certificate_request.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index e1be195..f2e2cfc 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -460,7 +460,7 @@ class CertificateRequest(HandshakeMsg):
-         self.version = version
-         self.supported_signature_algs = []
- 
--    def create(self, certificate_types, certificate_authorities, sig_algs=()):
-+    def create(self, certificate_types, certificate_authorities, sig_algs):
-         self.certificate_types = certificate_types
-         self.certificate_authorities = certificate_authorities
-         self.supported_signature_algs = sig_algs
-@@ -470,7 +470,8 @@ class CertificateRequest(HandshakeMsg):
-         p.startLengthCheck(3)
-         self.certificate_types = p.getVarList(1, 1)
-         if self.version >= (3,3):
--            self.supported_signature_algs = p.getVarList(2, 2)
-+            self.supported_signature_algs = \
-+                [(b >> 8, b & 0xff) for b in p.getVarList(2, 2)]
-         ca_list_length = p.get(2)
-         index = 0
-         self.certificate_authorities = []
-@@ -485,7 +486,10 @@ class CertificateRequest(HandshakeMsg):
-         w = Writer()
-         w.addVarSeq(self.certificate_types, 1, 1)
-         if self.version >= (3,3):
--            w.addVarSeq(self.supported_signature_algs, 2, 2)
-+            w.add(2 * len(self.supported_signature_algs), 2)
-+            for (hash, signature) in self.supported_signature_algs:
-+                w.add(hash, 1)
-+                w.add(signature, 1)
-         caLength = 0
-         #determine length
-         for ca_dn in self.certificate_authorities:
-@@ -646,22 +650,30 @@ class ClientKeyExchange(HandshakeMsg):
-         return self.postWrite(w)
- 
- class CertificateVerify(HandshakeMsg):
--    def __init__(self):
-+    def __init__(self, version):
-         HandshakeMsg.__init__(self, HandshakeType.certificate_verify)
-+        self.version = version
-+        self.signature_algorithm = None
-         self.signature = bytearray(0)
- 
--    def create(self, signature):
-+    def create(self, signature_algorithm, signature):
-+        self.signature_algorithm = signature_algorithm
-         self.signature = signature
-         return self
- 
-     def parse(self, p):
-         p.startLengthCheck(3)
-+        if self.version >= (3,3):
-+            self.signature_algorithm = (p.get(1), p.get(1))
-         self.signature = p.getVarBytes(2)
-         p.stopLengthCheck()
-         return self
- 
-     def write(self):
-         w = Writer()
-+        if self.version >= (3,3):
-+            w.add(self.signature_algorithm[0], 1)
-+            w.add(self.signature_algorithm[1], 1)
-         w.addVarSeq(self.signature, 1, 2)
-         return self.postWrite(w)
- 
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index cb743fe..3d97e97 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -956,6 +956,7 @@ class TLSConnection(TLSRecordLayer):
-         #If client authentication was requested and we have a
-         #private key, send CertificateVerify
-         if certificateRequest and privateKey:
-+            signatureAlgorithm = None
-             if self.version == (3,0):
-                 masterSecret = calcMasterSecret(self.version,
-                                          premasterSecret,
-@@ -966,12 +967,15 @@ class TLSConnection(TLSRecordLayer):
-                 verifyBytes = self._handshake_md5.digest() + \
-                                 self._handshake_sha.digest()
-             elif self.version == (3,3):
--                verifyBytes = self._handshake_sha256.digest()
-+                # TODO: Signature algorithm negotiation not supported.
-+                signatureAlgorithm = (HashAlgorithm.sha1, SignatureAlgorithm.rsa)
-+                verifyBytes = self._handshake_sha.digest()
-+                verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes)
-             if self.fault == Fault.badVerifyMessage:
-                 verifyBytes[0] = ((verifyBytes[0]+1) % 256)
-             signedBytes = privateKey.sign(verifyBytes)
--            certificateVerify = CertificateVerify()
--            certificateVerify.create(signedBytes)
-+            certificateVerify = CertificateVerify(self.version)
-+            certificateVerify.create(signatureAlgorithm, signedBytes)
-             for result in self._sendMsg(certificateVerify):
-                 yield result
-         yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
-@@ -1640,8 +1644,11 @@ class TLSConnection(TLSRecordLayer):
-             #Apple's Secure Transport library rejects empty certificate_types,
-             #so default to rsa_sign.
-             reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
-+            #Only SHA-1 + RSA is supported.
-+            sigAlgs = [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)]
-             msgs.append(CertificateRequest(self.version).create(reqCertTypes,
--                                                                reqCAs))
-+                                                                reqCAs,
-+                                                                sigAlgs))
-         msgs.append(ServerHelloDone())
-         for result in self._sendMsgs(msgs):
-             yield result
-@@ -1713,7 +1720,8 @@ class TLSConnection(TLSRecordLayer):
-                 verifyBytes = self._handshake_md5.digest() + \
-                                 self._handshake_sha.digest()
-             elif self.version == (3,3):
--                verifyBytes = self._handshake_sha256.digest()
-+                verifyBytes = self._handshake_sha.digest()
-+                verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes)
-             for result in self._getMsg(ContentType.handshake,
-                                       HandshakeType.certificate_verify):
-                 if result in (0,1): yield result
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index eda11e6..a09499d 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -804,7 +804,7 @@ class TLSRecordLayer(object):
-                 elif subType == HandshakeType.certificate_request:
-                     yield CertificateRequest(self.version).parse(p)
-                 elif subType == HandshakeType.certificate_verify:
--                    yield CertificateVerify().parse(p)
-+                    yield CertificateVerify(self.version).parse(p)
-                 elif subType == HandshakeType.server_key_exchange:
-                     yield ServerKeyExchange(constructorType,
-                                             self.version).parse(p)
diff --git a/third_party/tlslite/patches/channel_id.patch b/third_party/tlslite/patches/channel_id.patch
deleted file mode 100644
index 1ba9287..0000000
--- a/third_party/tlslite/patches/channel_id.patch
+++ /dev/null
@@ -1,173 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 4165de0..6429c66 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -32,6 +32,7 @@ class HandshakeType:
-     client_key_exchange = 16
-     finished = 20
-     next_protocol = 67
-+    encrypted_extensions = 203
- 
- class ContentType:
-     change_cipher_spec = 20
-@@ -46,6 +47,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     cert_type = 9       # RFC 6091
-     tack = 0xF300
-     supports_npn = 13172
-+    channel_id = 30032
-     
- class NameType:
-     host_name = 0
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 2b3e518..4fa9d96 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -113,6 +113,7 @@ class ClientHello(HandshakeMsg):
-         self.tack = False
-         self.supports_npn = False
-         self.server_name = bytearray(0)
-+        self.channel_id = False
- 
-     def create(self, version, random, session_id, cipher_suites,
-                certificate_types=None, srpUsername=None,
-@@ -180,6 +181,8 @@ class ClientHello(HandshakeMsg):
-                             if name_type == NameType.host_name:
-                                 self.server_name = hostNameBytes
-                                 break
-+                    elif extType == ExtensionType.channel_id:
-+                        self.channel_id = True
-                     else:
-                         _ = p.getFixBytes(extLength)
-                     index2 = p.index
-@@ -244,6 +247,7 @@ class ServerHello(HandshakeMsg):
-         self.tackExt = None
-         self.next_protos_advertised = None
-         self.next_protos = None
-+        self.channel_id = False
- 
-     def create(self, version, random, session_id, cipher_suite,
-                certificate_type, tackExt, next_protos_advertised):
-@@ -330,6 +334,9 @@ class ServerHello(HandshakeMsg):
-             w2.add(ExtensionType.supports_npn, 2)
-             w2.add(len(encoded_next_protos_advertised), 2)
-             w2.addFixSeq(encoded_next_protos_advertised, 1)
-+        if self.channel_id:
-+            w2.add(ExtensionType.channel_id, 2)
-+            w2.add(0, 2)
-         if len(w2.bytes):
-             w.add(len(w2.bytes), 2)
-             w.bytes += w2.bytes        
-@@ -665,6 +672,28 @@ class Finished(HandshakeMsg):
-         w.addFixSeq(self.verify_data, 1)
-         return self.postWrite(w)
- 
-+class EncryptedExtensions(HandshakeMsg):
-+    def __init__(self):
-+        self.channel_id_key = None
-+        self.channel_id_proof = None
-+
-+    def parse(self, p):
-+        p.startLengthCheck(3)
-+        soFar = 0
-+        while soFar != p.lengthCheck:
-+            extType = p.get(2)
-+            extLength = p.get(2)
-+            if extType == ExtensionType.channel_id:
-+                if extLength != 32*4:
-+                    raise SyntaxError()
-+                self.channel_id_key = p.getFixBytes(64)
-+                self.channel_id_proof = p.getFixBytes(64)
-+            else:
-+                p.getFixBytes(extLength)
-+            soFar += 4 + extLength
-+        p.stopLengthCheck()
-+        return self
-+
- class ApplicationData(object):
-     def __init__(self):
-         self.contentType = ContentType.application_data
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 0e78753..b0400f8 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1158,6 +1158,7 @@ class TLSConnection(TLSRecordLayer):
-         serverHello.create(self.version, getRandomBytes(32), sessionID, \
-                             cipherSuite, CertificateType.x509, tackExt,
-                             nextProtos)
-+        serverHello.channel_id = clientHello.channel_id
- 
-         # Perform the SRP key exchange
-         clientCertChain = None
-@@ -1194,7 +1195,7 @@ class TLSConnection(TLSRecordLayer):
-         for result in self._serverFinished(premasterSecret, 
-                                 clientHello.random, serverHello.random,
-                                 cipherSuite, settings.cipherImplementations,
--                                nextProtos):
-+                                nextProtos, clientHello.channel_id):
-                 if result in (0,1): yield result
-                 else: break
-         masterSecret = result
-@@ -1614,7 +1615,8 @@ class TLSConnection(TLSRecordLayer):
- 
- 
-     def _serverFinished(self,  premasterSecret, clientRandom, serverRandom,
--                        cipherSuite, cipherImplementations, nextProtos):
-+                        cipherSuite, cipherImplementations, nextProtos,
-+                        doingChannelID):
-         masterSecret = calcMasterSecret(self.version, premasterSecret,
-                                       clientRandom, serverRandom)
-         
-@@ -1625,7 +1627,8 @@ class TLSConnection(TLSRecordLayer):
- 
-         #Exchange ChangeCipherSpec and Finished messages
-         for result in self._getFinished(masterSecret, 
--                        expect_next_protocol=nextProtos is not None):
-+                        expect_next_protocol=nextProtos is not None,
-+                        expect_channel_id=doingChannelID):
-             yield result
- 
-         for result in self._sendFinished(masterSecret):
-@@ -1662,7 +1665,8 @@ class TLSConnection(TLSRecordLayer):
-         for result in self._sendMsg(finished):
-             yield result
- 
--    def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None):
-+    def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None,
-+                     expect_channel_id=False):
-         #Get and check ChangeCipherSpec
-         for result in self._getMsg(ContentType.change_cipher_spec):
-             if result in (0,1):
-@@ -1695,6 +1699,20 @@ class TLSConnection(TLSRecordLayer):
-         if nextProto:
-             self.next_proto = nextProto
- 
-+        #Server Finish - Are we waiting for a EncryptedExtensions?
-+        if expect_channel_id:
-+            for result in self._getMsg(ContentType.handshake, HandshakeType.encrypted_extensions):
-+                if result in (0,1):
-+                    yield result
-+            if result is None:
-+                for result in self._sendError(AlertDescription.unexpected_message,
-+                                             "Didn't get EncryptedExtensions message"):
-+                    yield result
-+            encrypted_extensions = result
-+            self.channel_id = result.channel_id_key
-+        else:
-+            self.channel_id = None
-+
-         #Calculate verification data
-         verifyData = self._calcFinished(masterSecret, False)
- 
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index 5fe7410..f18fcf5 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -806,6 +806,8 @@ class TLSRecordLayer(object):
-                     yield Finished(self.version).parse(p)
-                 elif subType == HandshakeType.next_protocol:
-                     yield NextProtocol().parse(p)
-+                elif subType == HandshakeType.encrypted_extensions:
-+                    yield EncryptedExtensions().parse(p)
-                 else:
-                     raise AssertionError()
- 
diff --git a/third_party/tlslite/patches/dhe_rsa.patch b/third_party/tlslite/patches/dhe_rsa.patch
deleted file mode 100644
index 5bb12f0..0000000
--- a/third_party/tlslite/patches/dhe_rsa.patch
+++ /dev/null
@@ -1,561 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 1a1ace9..d2d50c5 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -54,6 +54,20 @@ class ExtensionType:    # RFC 6066 / 4366
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
-+
-+class HashAlgorithm:
-+    none = 0
-+    md5 = 1
-+    sha1 = 2
-+    sha224 = 3
-+    sha256 = 4
-+    sha384 = 5
-+
-+class SignatureAlgorithm:
-+    anonymous = 0
-+    rsa = 1
-+    dsa = 2
-+    ecdsa = 3
-     
- class NameType:
-     host_name = 0
-@@ -144,30 +158,42 @@ class CipherSuite:
-     
-     TLS_RSA_WITH_RC4_128_MD5 = 0x0004
- 
-+    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016
-+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
-+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
-+
-     TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034
-     TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A
- 
-     TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C
-     TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D
- 
-+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
-+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
-+
-     tripleDESSuites = []
-     tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-     tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-     tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
-+    tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
- 
-     aes128Suites = []
-     aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
-     aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
-     aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
-+    aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
-     aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-     aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-+    aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
- 
-     aes256Suites = []
-     aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
-     aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
-     aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
-     aes256Suites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-+    aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-     aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-+    aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
- 
-     rc4Suites = []
-     rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
-@@ -184,12 +210,18 @@ class CipherSuite:
-     shaSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
-     shaSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
-     shaSuites.append(TLS_RSA_WITH_RC4_128_SHA)
-+    shaSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
-+    shaSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
-+    shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-     shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-     shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-     
-     sha256Suites = []
-     sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-     sha256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-+    sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-+    sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-+
- 
-     md5Suites = []
-     md5Suites.append(TLS_RSA_WITH_RC4_128_MD5)
-@@ -198,6 +230,7 @@ class CipherSuite:
-     def _filterSuites(suites, settings):
-         macNames = settings.macNames
-         cipherNames = settings.cipherNames
-+        keyExchangeNames = settings.keyExchangeNames
-         macSuites = []
-         if "sha" in macNames:
-             macSuites += CipherSuite.shaSuites
-@@ -216,7 +249,20 @@ class CipherSuite:
-         if "rc4" in cipherNames:
-             cipherSuites += CipherSuite.rc4Suites
- 
--        return [s for s in suites if s in macSuites and s in cipherSuites]
-+        keyExchangeSuites = []
-+        if "rsa" in keyExchangeNames:
-+            keyExchangeSuites += CipherSuite.certSuites
-+        if "dhe_rsa" in keyExchangeNames:
-+            keyExchangeSuites += CipherSuite.dheCertSuites
-+        if "srp_sha" in keyExchangeNames:
-+            keyExchangeSuites += CipherSuite.srpSuites
-+        if "srp_sha_rsa" in keyExchangeNames:
-+            keyExchangeSuites += CipherSuite.srpCertSuites
-+        if "dh_anon" in keyExchangeNames:
-+            keyExchangeSuites += CipherSuite.anonSuites
-+
-+        return [s for s in suites if s in macSuites and
-+                s in cipherSuites and s in keyExchangeSuites]
- 
-     srpSuites = []
-     srpSuites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
-@@ -250,12 +296,24 @@ class CipherSuite:
-     certSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
-     certSuites.append(TLS_RSA_WITH_RC4_128_SHA)
-     certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
--    certAllSuites = srpCertSuites + certSuites
-     
-     @staticmethod
-     def getCertSuites(settings):
-         return CipherSuite._filterSuites(CipherSuite.certSuites, settings)
- 
-+    dheCertSuites = []
-+    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-+    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-+    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-+    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
-+    dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
-+
-+    @staticmethod
-+    def getDheCertSuites(settings):
-+        return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings)
-+
-+    certAllSuites = srpCertSuites + certSuites + dheCertSuites
-+
-     anonSuites = []
-     anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-     anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-@@ -264,6 +322,8 @@ class CipherSuite:
-     def getAnonSuites(settings):
-         return CipherSuite._filterSuites(CipherSuite.anonSuites, settings)
- 
-+    dhAllSuites = dheCertSuites + anonSuites
-+
-     @staticmethod
-     def canonicalCipherName(ciphersuite):
-         "Return the canonical name of the cipher whose number is provided."
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index ee37c30..7998e2e 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -14,7 +14,9 @@ from .utils import cipherfactory
- # RC4 is preferred as faster in Python, works in SSL3, and immune to CBC
- # issues such as timing attacks
- CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"]
--MAC_NAMES = ["sha", "sha256"] # "md5" is allowed
-+MAC_NAMES = ["sha", "sha256"] # Don't allow "md5" by default.
-+ALL_MAC_NAMES = ["sha", "sha256", "md5"]
-+KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
- CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
- CERTIFICATE_TYPES = ["x509"]
- 
-@@ -101,6 +103,7 @@ class HandshakeSettings(object):
-         self.maxKeySize = 8193
-         self.cipherNames = CIPHER_NAMES
-         self.macNames = MAC_NAMES
-+        self.keyExchangeNames = KEY_EXCHANGE_NAMES
-         self.cipherImplementations = CIPHER_IMPLEMENTATIONS
-         self.certificateTypes = CERTIFICATE_TYPES
-         self.minVersion = (3,1)
-@@ -115,6 +118,7 @@ class HandshakeSettings(object):
-         other.maxKeySize = self.maxKeySize
-         other.cipherNames = self.cipherNames
-         other.macNames = self.macNames
-+        other.keyExchangeNames = self.keyExchangeNames
-         other.cipherImplementations = self.cipherImplementations
-         other.certificateTypes = self.certificateTypes
-         other.minVersion = self.minVersion
-@@ -147,6 +151,12 @@ class HandshakeSettings(object):
-         for s in other.cipherNames:
-             if s not in CIPHER_NAMES:
-                 raise ValueError("Unknown cipher name: '%s'" % s)
-+        for s in other.macNames:
-+            if s not in ALL_MAC_NAMES:
-+                raise ValueError("Unknown MAC name: '%s'" % s)
-+        for s in other.keyExchangeNames:
-+            if s not in KEY_EXCHANGE_NAMES:
-+                raise ValueError("Unknown key exchange name: '%s'" % s)
-         for s in other.cipherImplementations:
-             if s not in CIPHER_IMPLEMENTATIONS:
-                 raise ValueError("Unknown cipher implementation: '%s'" % s)
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 9a8e5f6..8b77ee6 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -500,9 +500,10 @@ class CertificateRequest(HandshakeMsg):
-         return self.postWrite(w)
- 
- class ServerKeyExchange(HandshakeMsg):
--    def __init__(self, cipherSuite):
-+    def __init__(self, cipherSuite, version):
-         HandshakeMsg.__init__(self, HandshakeType.server_key_exchange)
-         self.cipherSuite = cipherSuite
-+        self.version = version
-         self.srp_N = 0
-         self.srp_g = 0
-         self.srp_s = bytearray(0)
-@@ -542,31 +543,38 @@ class ServerKeyExchange(HandshakeMsg):
-         p.stopLengthCheck()
-         return self
- 
--    def write(self):
-+    def write_params(self):
-         w = Writer()
-         if self.cipherSuite in CipherSuite.srpAllSuites:
-             w.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
-             w.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
-             w.addVarSeq(self.srp_s, 1, 1)
-             w.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
--            if self.cipherSuite in CipherSuite.srpCertSuites:
--                w.addVarSeq(self.signature, 1, 2)
--        elif self.cipherSuite in CipherSuite.anonSuites:
-+        elif self.cipherSuite in CipherSuite.dhAllSuites:
-             w.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
-             w.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
-             w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
--            if self.cipherSuite in []: # TODO support for signed_params
--                w.addVarSeq(self.signature, 1, 2)
-+        else:
-+            assert(False)
-+        return w.bytes
-+
-+    def write(self):
-+        w = Writer()
-+        w.bytes += self.write_params()
-+        if self.cipherSuite in CipherSuite.certAllSuites:
-+            if self.version >= (3,3):
-+                # TODO: Signature algorithm negotiation not supported.
-+                w.add(HashAlgorithm.sha1, 1)
-+                w.add(SignatureAlgorithm.rsa, 1)
-+            w.addVarSeq(self.signature, 1, 2)
-         return self.postWrite(w)
- 
-     def hash(self, clientRandom, serverRandom):
--        oldCipherSuite = self.cipherSuite
--        self.cipherSuite = None
--        try:
--            bytes = clientRandom + serverRandom + self.write()[4:]
--            return MD5(bytes) + SHA1(bytes)
--        finally:
--            self.cipherSuite = oldCipherSuite
-+        bytes = clientRandom + serverRandom + self.write_params()
-+        if self.version >= (3,3):
-+            # TODO: Signature algorithm negotiation not supported.
-+            return SHA1(bytes)
-+        return MD5(bytes) + SHA1(bytes)
- 
- class ServerHelloDone(HandshakeMsg):
-     def __init__(self):
-@@ -616,7 +624,7 @@ class ClientKeyExchange(HandshakeMsg):
-                     p.getFixBytes(len(p.bytes)-p.index)
-             else:
-                 raise AssertionError()
--        elif self.cipherSuite in CipherSuite.anonSuites:
-+        elif self.cipherSuite in CipherSuite.dhAllSuites:
-             self.dh_Yc = bytesToNumber(p.getVarBytes(2))            
-         else:
-             raise AssertionError()
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 5d508ed..f6d13d4 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -23,7 +23,109 @@ from .messages import *
- from .mathtls import *
- from .handshakesettings import HandshakeSettings
- from .utils.tackwrapper import *
-+from .utils.rsakey import RSAKey
- 
-+class KeyExchange(object):
-+    def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
-+        """
-+        Initializes the KeyExchange. privateKey is the signing private key.
-+        """
-+        self.cipherSuite = cipherSuite
-+        self.clientHello = clientHello
-+        self.serverHello = serverHello
-+        self.privateKey = privateKey
-+
-+    def makeServerKeyExchange():
-+        """
-+        Returns a ServerKeyExchange object for the server's initial leg in the
-+        handshake. If the key exchange method does not send ServerKeyExchange
-+        (e.g. RSA), it returns None.
-+        """
-+        raise NotImplementedError()
-+
-+    def processClientKeyExchange(clientKeyExchange):
-+        """
-+        Processes the client's ClientKeyExchange message and returns the
-+        premaster secret. Raises TLSLocalAlert on error.
-+        """
-+        raise NotImplementedError()
-+
-+class RSAKeyExchange(KeyExchange):
-+    def makeServerKeyExchange(self):
-+        return None
-+
-+    def processClientKeyExchange(self, clientKeyExchange):
-+        premasterSecret = self.privateKey.decrypt(\
-+            clientKeyExchange.encryptedPreMasterSecret)
-+
-+        # On decryption failure randomize premaster secret to avoid
-+        # Bleichenbacher's "million message" attack
-+        randomPreMasterSecret = getRandomBytes(48)
-+        if not premasterSecret:
-+            premasterSecret = randomPreMasterSecret
-+        elif len(premasterSecret)!=48:
-+            premasterSecret = randomPreMasterSecret
-+        else:
-+            versionCheck = (premasterSecret[0], premasterSecret[1])
-+            if versionCheck != self.clientHello.client_version:
-+                #Tolerate buggy IE clients
-+                if versionCheck != self.serverHello.server_version:
-+                    premasterSecret = randomPreMasterSecret
-+        return premasterSecret
-+
-+def _hexStringToNumber(s):
-+    s = s.replace(" ", "").replace("\n", "")
-+    if len(s) % 2 != 0:
-+        raise ValueError("Length is not even")
-+    return bytesToNumber(bytearray.fromhex(s))
-+
-+class DHE_RSAKeyExchange(KeyExchange):
-+    # 2048-bit MODP Group (RFC 3526, Section 3)
-+    dh_p = _hexStringToNumber("""
-+FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
-+29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
-+EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
-+E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
-+EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
-+C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
-+83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
-+670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
-+E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
-+DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
-+15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""")
-+    dh_g = 2
-+
-+    # RFC 3526, Section 8.
-+    strength = 160
-+
-+    def makeServerKeyExchange(self):
-+        # Per RFC 3526, Section 1, the exponent should have double the entropy
-+        # of the strength of the curve.
-+        self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8))
-+        dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
-+
-+        version = self.serverHello.server_version
-+        serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
-+        serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
-+        hashBytes = serverKeyExchange.hash(self.clientHello.random,
-+                                           self.serverHello.random)
-+        if version >= (3,3):
-+            # TODO: Signature algorithm negotiation not supported.
-+            hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes)
-+        serverKeyExchange.signature = self.privateKey.sign(hashBytes)
-+        return serverKeyExchange
-+
-+    def processClientKeyExchange(self, clientKeyExchange):
-+        dh_Yc = clientKeyExchange.dh_Yc
-+
-+        # First half of RFC 2631, Section 2.1.5. Validate the client's public
-+        # key.
-+        if not 2 <= dh_Yc <= self.dh_p - 1:
-+            raise TLSLocalAlert(AlertDescription.illegal_parameter,
-+                                "Invalid dh_Yc value")
-+
-+        S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
-+        return numberToByteArray(S)
- 
- class TLSConnection(TLSRecordLayer):
-     """
-@@ -500,6 +602,8 @@ class TLSConnection(TLSRecordLayer):
-         if srpParams:
-             cipherSuites += CipherSuite.getSrpAllSuites(settings)
-         elif certParams:
-+            # TODO: Client DHE_RSA not supported.
-+            # cipherSuites += CipherSuite.getDheCertSuites(settings)
-             cipherSuites += CipherSuite.getCertSuites(settings)
-         elif anonParams:
-             cipherSuites += CipherSuite.getAnonSuites(settings)
-@@ -1207,10 +1311,23 @@ class TLSConnection(TLSRecordLayer):
-                 else: break
-             premasterSecret = result
- 
--        # Perform the RSA key exchange
--        elif cipherSuite in CipherSuite.certSuites:
-+        # Perform the RSA or DHE_RSA key exchange
-+        elif (cipherSuite in CipherSuite.certSuites or
-+              cipherSuite in CipherSuite.dheCertSuites):
-+            if cipherSuite in CipherSuite.certSuites:
-+                keyExchange = RSAKeyExchange(cipherSuite,
-+                                             clientHello,
-+                                             serverHello,
-+                                             privateKey)
-+            elif cipherSuite in CipherSuite.dheCertSuites:
-+                keyExchange = DHE_RSAKeyExchange(cipherSuite,
-+                                                 clientHello,
-+                                                 serverHello,
-+                                                 privateKey)
-+            else:
-+                assert(False)
-             for result in self._serverCertKeyExchange(clientHello, serverHello, 
--                                        certChain, privateKey,
-+                                        certChain, keyExchange,
-                                         reqCert, reqCAs, cipherSuite,
-                                         settings, ocspResponse):
-                 if result in (0,1): yield result
-@@ -1270,6 +1387,7 @@ class TLSConnection(TLSRecordLayer):
-                     CipherSuite.getSrpCertSuites(settings)
-             cipherSuites += CipherSuite.getSrpSuites(settings)
-         elif certChain:
-+            cipherSuites += CipherSuite.getDheCertSuites(settings)
-             cipherSuites += CipherSuite.getCertSuites(settings)
-         elif anon:
-             cipherSuites += CipherSuite.getAnonSuites(settings)
-@@ -1440,7 +1558,7 @@ class TLSConnection(TLSRecordLayer):
-         B = (powMod(g, b, N) + (k*v)) % N
- 
-         #Create ServerKeyExchange, signing it if necessary
--        serverKeyExchange = ServerKeyExchange(cipherSuite)
-+        serverKeyExchange = ServerKeyExchange(cipherSuite, self.version)
-         serverKeyExchange.createSRP(N, g, s, B)
-         if cipherSuite in CipherSuite.srpCertSuites:
-             hashBytes = serverKeyExchange.hash(clientHello.random,
-@@ -1488,11 +1606,11 @@ class TLSConnection(TLSRecordLayer):
- 
- 
-     def _serverCertKeyExchange(self, clientHello, serverHello, 
--                                serverCertChain, privateKey,
-+                                serverCertChain, keyExchange,
-                                 reqCert, reqCAs, cipherSuite,
-                                 settings, ocspResponse):
--        #Send ServerHello, Certificate[, CertificateRequest],
--        #ServerHelloDone
-+        #Send ServerHello, Certificate[, ServerKeyExchange]
-+        #[, CertificateRequest], ServerHelloDone
-         msgs = []
- 
-         # If we verify a client cert chain, return it
-@@ -1502,6 +1620,9 @@ class TLSConnection(TLSRecordLayer):
-         msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
-         if serverHello.status_request:
-             msgs.append(CertificateStatus().create(ocspResponse))
-+        serverKeyExchange = keyExchange.makeServerKeyExchange()
-+        if serverKeyExchange is not None:
-+            msgs.append(serverKeyExchange)
-         if reqCert and reqCAs:
-             msgs.append(CertificateRequest().create(\
-                 [ClientCertificateType.rsa_sign], reqCAs))
-@@ -1560,21 +1681,13 @@ class TLSConnection(TLSRecordLayer):
-             else: break
-         clientKeyExchange = result
- 
--        #Decrypt ClientKeyExchange
--        premasterSecret = privateKey.decrypt(\
--            clientKeyExchange.encryptedPreMasterSecret)
--
--        # On decryption failure randomize premaster secret to avoid
--        # Bleichenbacher's "million message" attack
--        randomPreMasterSecret = getRandomBytes(48)
--        versionCheck = (premasterSecret[0], premasterSecret[1])
--        if not premasterSecret:
--            premasterSecret = randomPreMasterSecret
--        elif len(premasterSecret)!=48:
--            premasterSecret = randomPreMasterSecret
--        elif versionCheck != clientHello.client_version:
--            if versionCheck != self.version: #Tolerate buggy IE clients
--                premasterSecret = randomPreMasterSecret
-+        #Process ClientKeyExchange
-+        try:
-+            premasterSecret = \
-+                keyExchange.processClientKeyExchange(clientKeyExchange)
-+        except alert as TLSLocalAlert:
-+            for result in self._sendError(alert.description, alert.message):
-+                yield result
- 
-         #Get and check CertificateVerify, if relevant
-         if clientCertChain:
-@@ -1622,7 +1735,7 @@ class TLSConnection(TLSRecordLayer):
-         dh_Ys = powMod(dh_g, dh_Xs, dh_p)
- 
-         #Create ServerKeyExchange
--        serverKeyExchange = ServerKeyExchange(cipherSuite)
-+        serverKeyExchange = ServerKeyExchange(cipherSuite, self.version)
-         serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
-         
-         #Send ServerHello[, Certificate], ServerKeyExchange,
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index 01ff3e9..6ef3895 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -796,7 +796,8 @@ class TLSRecordLayer(object):
-                 elif subType == HandshakeType.certificate_verify:
-                     yield CertificateVerify().parse(p)
-                 elif subType == HandshakeType.server_key_exchange:
--                    yield ServerKeyExchange(constructorType).parse(p)
-+                    yield ServerKeyExchange(constructorType,
-+                                            self.version).parse(p)
-                 elif subType == HandshakeType.server_hello_done:
-                     yield ServerHelloDone().parse(p)
-                 elif subType == HandshakeType.client_key_exchange:
-diff --git a/third_party/tlslite/tlslite/utils/rsakey.py b/third_party/tlslite/tlslite/utils/rsakey.py
-index 3f2100e..fb022cc 100644
---- a/third_party/tlslite/tlslite/utils/rsakey.py
-+++ b/third_party/tlslite/tlslite/utils/rsakey.py
-@@ -60,7 +60,7 @@ class RSAKey(object):
-         @return: A PKCS1-SHA1 signature on the passed-in data.
-         """
-         hashBytes = SHA1(bytearray(bytes))
--        prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes)
-+        prefixedHashBytes = self.addPKCS1SHA1Prefix(hashBytes)
-         sigBytes = self.sign(prefixedHashBytes)
-         return sigBytes
- 
-@@ -81,8 +81,8 @@ class RSAKey(object):
-         hashBytes = SHA1(bytearray(bytes))
-         
-         # Try it with/without the embedded NULL
--        prefixedHashBytes1 = self._addPKCS1SHA1Prefix(hashBytes, False)
--        prefixedHashBytes2 = self._addPKCS1SHA1Prefix(hashBytes, True)
-+        prefixedHashBytes1 = self.addPKCS1SHA1Prefix(hashBytes, False)
-+        prefixedHashBytes2 = self.addPKCS1SHA1Prefix(hashBytes, True)
-         result1 = self.verify(sigBytes, prefixedHashBytes1)
-         result2 = self.verify(sigBytes, prefixedHashBytes2)
-         return (result1 or result2)
-@@ -221,7 +221,8 @@ class RSAKey(object):
-     # Helper Functions for RSA Keys
-     # **************************************************************************
- 
--    def _addPKCS1SHA1Prefix(self, bytes, withNULL=True):
-+    @staticmethod
-+    def addPKCS1SHA1Prefix(bytes, withNULL=True):
-         # There is a long history of confusion over whether the SHA1 
-         # algorithmIdentifier should be encoded with a NULL parameter or 
-         # with the parameter omitted.  While the original intention was 
-@@ -229,8 +230,7 @@ class RSAKey(object):
-         # specifies the NULL should be included, and this behavior is also
-         # mandated in recent versions of PKCS #1, and is what tlslite has
-         # always implemented.  Anyways, verification code should probably 
--        # accept both.  However, nothing uses this code yet, so this is 
--        # all fairly moot.
-+        # accept both.
-         if not withNULL:
-             prefixBytes = bytearray(\
-             [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])            
diff --git a/third_party/tlslite/patches/disable_channel_id.patch b/third_party/tlslite/patches/disable_channel_id.patch
deleted file mode 100644
index 339cdd9..0000000
--- a/third_party/tlslite/patches/disable_channel_id.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index 8f25f62..d7be5b3 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -112,6 +112,9 @@ class HandshakeSettings(object):
-     @ivar alertAfterHandshake: If true, the server will send a fatal
-     alert immediately after the handshake completes.
- 
-+    @type enableChannelID: bool
-+    @ivar enableChannelID: If true, the server supports channel ID.
-+
-     @type enableExtendedMasterSecret: bool
-     @ivar enableExtendedMasterSecret: If true, the server supports the extended
-     master secret TLS extension and will negotiated it with supporting clients.
-@@ -140,6 +143,7 @@ class HandshakeSettings(object):
-         self.tlsIntoleranceType = 'alert'
-         self.useExperimentalTackExtension = False
-         self.alertAfterHandshake = False
-+        self.enableChannelID = True
-         self.enableExtendedMasterSecret = True
-         self.supportedTokenBindingParams = []
- 
-@@ -159,6 +163,7 @@ class HandshakeSettings(object):
-         other.tlsIntolerant = self.tlsIntolerant
-         other.tlsIntoleranceType = self.tlsIntoleranceType
-         other.alertAfterHandshake = self.alertAfterHandshake
-+        other.enableChannelID = self.enableChannelID
-         other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
-         other.supportedTokenBindingParams = self.supportedTokenBindingParams
- 
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 06404fe..7363a30 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1326,7 +1326,8 @@ class TLSConnection(TLSRecordLayer):
-         serverHello.create(self.version, getRandomBytes(32), sessionID, \
-                             cipherSuite, CertificateType.x509, tackExt,
-                             nextProtos)
--        serverHello.channel_id = clientHello.channel_id
-+        serverHello.channel_id = \
-+            clientHello.channel_id and settings.enableChannelID
-         serverHello.extended_master_secret = \
-             clientHello.extended_master_secret and \
-             settings.enableExtendedMasterSecret
-@@ -1391,7 +1392,7 @@ class TLSConnection(TLSRecordLayer):
-         for result in self._serverFinished(premasterSecret, 
-                                 clientHello.random, serverHello.random,
-                                 cipherSuite, settings.cipherImplementations,
--                                nextProtos, clientHello.channel_id,
-+                                nextProtos, serverHello.channel_id,
-                                 serverHello.extended_master_secret):
-                 if result in (0,1): yield result
-                 else: break
diff --git a/third_party/tlslite/patches/ecdhe_rsa.patch b/third_party/tlslite/patches/ecdhe_rsa.patch
deleted file mode 100644
index 054a07a0..0000000
--- a/third_party/tlslite/patches/ecdhe_rsa.patch
+++ /dev/null
@@ -1,428 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index e5b88af..6d78a20 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -76,6 +76,14 @@ class SignatureAlgorithm:
- class NameType:
-     host_name = 0
- 
-+class ECCurveType:
-+    explicit_prime = 1
-+    explicit_char2 = 2
-+    named_curve = 3
-+
-+class NamedCurve:
-+    secp256r1 = 23
-+
- class AlertLevel:
-     warning = 1
-     fatal = 2
-@@ -178,11 +186,19 @@ class CipherSuite:
-     TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
-     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
- 
-+    TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xc011
-+    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xc012
-+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013
-+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014
-+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027
-+    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f
-+
-     tripleDESSuites = []
-     tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-     tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-     tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
-     tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
-+    tripleDESSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
- 
-     aes128Suites = []
-     aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
-@@ -192,6 +208,8 @@ class CipherSuite:
-     aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-     aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-     aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-+    aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-+    aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
- 
-     aes256Suites = []
-     aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
-@@ -201,14 +219,17 @@ class CipherSuite:
-     aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-     aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-     aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-+    aes256Suites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
- 
-     aes128GcmSuites = []
-     aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-     aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-+    aes128GcmSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
- 
-     rc4Suites = []
-     rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
-     rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5)
-+    rc4Suites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
-     
-     shaSuites = []
-     shaSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-@@ -226,6 +247,10 @@ class CipherSuite:
-     shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-     shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-     shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-+    shaSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
-+    shaSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
-+    shaSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-+    shaSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-     
-     sha256Suites = []
-     sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-@@ -234,6 +259,9 @@ class CipherSuite:
-     sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-     sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-     sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-+    sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
-+    sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-+
- 
-     aeadSuites = aes128GcmSuites
- 
-@@ -275,6 +303,8 @@ class CipherSuite:
-             keyExchangeSuites += CipherSuite.certSuites
-         if "dhe_rsa" in keyExchangeNames:
-             keyExchangeSuites += CipherSuite.dheCertSuites
-+        if "ecdhe_rsa" in keyExchangeNames:
-+            keyExchangeSuites += CipherSuite.ecdheCertSuites
-         if "srp_sha" in keyExchangeNames:
-             keyExchangeSuites += CipherSuite.srpSuites
-         if "srp_sha_rsa" in keyExchangeNames:
-@@ -335,7 +365,19 @@ class CipherSuite:
-     def getDheCertSuites(settings, version=None):
-         return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, version)
- 
--    certAllSuites = srpCertSuites + certSuites + dheCertSuites
-+    ecdheCertSuites = []
-+    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-+    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
-+    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-+    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-+    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
-+    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
-+
-+    @staticmethod
-+    def getEcdheCertSuites(settings, version=None):
-+        return CipherSuite._filterSuites(CipherSuite.ecdheCertSuites, settings, version)
-+
-+    certAllSuites = srpCertSuites + certSuites + dheCertSuites + ecdheCertSuites
- 
-     anonSuites = []
-     anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-@@ -346,6 +388,7 @@ class CipherSuite:
-         return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, version)
- 
-     dhAllSuites = dheCertSuites + anonSuites
-+    ecdhAllSuites = ecdheCertSuites
- 
-     @staticmethod
-     def canonicalCipherName(ciphersuite):
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index e752834..605ed42 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -14,7 +14,7 @@ from .utils import cipherfactory
- CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"]
- MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default.
- ALL_MAC_NAMES = MAC_NAMES + ["md5"]
--KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
-+KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
- CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
- CERTIFICATE_TYPES = ["x509"]
- TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"]
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index f2e2cfc..9aeff6d 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -509,10 +509,13 @@ class ServerKeyExchange(HandshakeMsg):
-         self.srp_g = 0
-         self.srp_s = bytearray(0)
-         self.srp_B = 0
--        # Anon DH params:
-+        # DH params:
-         self.dh_p = 0
-         self.dh_g = 0
-         self.dh_Ys = 0
-+        # ECDH params:
-+        self.ecdhCurve = 0
-+        self.ecdhPublic = bytearray(0)
-         self.signature = bytearray(0)
- 
-     def createSRP(self, srp_N, srp_g, srp_s, srp_B):
-@@ -528,6 +531,11 @@ class ServerKeyExchange(HandshakeMsg):
-         self.dh_Ys = dh_Ys
-         return self
- 
-+    def createECDH(self, ecdhCurve, ecdhPublic):
-+        self.ecdhCurve = ecdhCurve
-+        self.ecdhPublic = ecdhPublic
-+        return self
-+
-     def parse(self, p):
-         p.startLengthCheck(3)
-         if self.cipherSuite in CipherSuite.srpAllSuites:
-@@ -555,6 +563,10 @@ class ServerKeyExchange(HandshakeMsg):
-             w.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
-             w.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
-             w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
-+        elif self.cipherSuite in CipherSuite.ecdhAllSuites:
-+            w.add(ECCurveType.named_curve, 1)
-+            w.add(self.ecdhCurve, 2)
-+            w.addVarSeq(self.ecdhPublic, 1, 1)
-         else:
-             assert(False)
-         return w.bytes
-@@ -626,7 +638,9 @@ class ClientKeyExchange(HandshakeMsg):
-             else:
-                 raise AssertionError()
-         elif self.cipherSuite in CipherSuite.dhAllSuites:
--            self.dh_Yc = bytesToNumber(p.getVarBytes(2))            
-+            self.dh_Yc = bytesToNumber(p.getVarBytes(2))
-+        elif self.cipherSuite in CipherSuite.ecdhAllSuites:
-+            self.ecdh_Yc = p.getVarBytes(1)
-         else:
-             raise AssertionError()
-         p.stopLengthCheck()
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 0a85d3c..dfac274 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -24,6 +24,7 @@ from .mathtls import *
- from .handshakesettings import HandshakeSettings
- from .utils.tackwrapper import *
- from .utils.rsakey import RSAKey
-+from .utils import p256
- 
- class KeyExchange(object):
-     def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
-@@ -127,6 +128,25 @@ DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
-         S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
-         return numberToByteArray(S)
- 
-+class ECDHE_RSAKeyExchange(KeyExchange):
-+    def makeServerKeyExchange(self):
-+        public, self.private = p256.generatePublicPrivate()
-+
-+        version = self.serverHello.server_version
-+        serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
-+        serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public))
-+        hashBytes = serverKeyExchange.hash(self.clientHello.random,
-+                                           self.serverHello.random)
-+        if version >= (3,3):
-+            # TODO: Signature algorithm negotiation not supported.
-+            hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes)
-+        serverKeyExchange.signature = self.privateKey.sign(hashBytes)
-+        return serverKeyExchange
-+
-+    def processClientKeyExchange(self, clientKeyExchange):
-+        ecdh_Yc = clientKeyExchange.ecdh_Yc
-+        return bytearray(p256.generateSharedValue(bytes(ecdh_Yc), self.private))
-+
- class TLSConnection(TLSRecordLayer):
-     """
-     This class wraps a socket and provides TLS handshaking and data
-@@ -1321,9 +1341,8 @@ class TLSConnection(TLSRecordLayer):
-                 else: break
-             premasterSecret = result
- 
--        # Perform the RSA or DHE_RSA key exchange
--        elif (cipherSuite in CipherSuite.certSuites or
--              cipherSuite in CipherSuite.dheCertSuites):
-+        # Perform a certificate-based key exchange
-+        elif cipherSuite in CipherSuite.certAllSuites:
-             if cipherSuite in CipherSuite.certSuites:
-                 keyExchange = RSAKeyExchange(cipherSuite,
-                                              clientHello,
-@@ -1334,6 +1353,11 @@ class TLSConnection(TLSRecordLayer):
-                                                  clientHello,
-                                                  serverHello,
-                                                  privateKey)
-+            elif cipherSuite in CipherSuite.ecdheCertSuites:
-+                keyExchange = ECDHE_RSAKeyExchange(cipherSuite,
-+                                                   clientHello,
-+                                                   serverHello,
-+                                                   privateKey)
-             else:
-                 assert(False)
-             for result in self._serverCertKeyExchange(clientHello, serverHello, 
-@@ -1450,6 +1474,7 @@ class TLSConnection(TLSRecordLayer):
-                     CipherSuite.getSrpCertSuites(settings, self.version)
-             cipherSuites += CipherSuite.getSrpSuites(settings, self.version)
-         elif certChain:
-+            cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.version)
-             cipherSuites += CipherSuite.getDheCertSuites(settings, self.version)
-             cipherSuites += CipherSuite.getCertSuites(settings, self.version)
-         elif anon:
-diff --git a/third_party/tlslite/tlslite/utils/p256.py b/third_party/tlslite/tlslite/utils/p256.py
-index e69de29..6eb9a77 100644
---- a/third_party/tlslite/tlslite/utils/p256.py
-+++ b/third_party/tlslite/tlslite/utils/p256.py
-@@ -0,0 +1,162 @@
-+# Author: Google
-+# See the LICENSE file for legal information regarding use of this file.
-+
-+import os
-+
-+p = (
-+    115792089210356248762697446949407573530086143415290314195533631308867097853951)
-+order = (
-+    115792089210356248762697446949407573529996955224135760342422259061068512044369)
-+p256B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
-+
-+baseX = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
-+baseY = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
-+basePoint = (baseX, baseY)
-+
-+
-+def _pointAdd(a, b):
-+    Z1Z1 = (a[2] * a[2]) % p
-+    Z2Z2 = (b[2] * b[2]) % p
-+    U1 = (a[0] * Z2Z2) % p
-+    U2 = (b[0] * Z1Z1) % p
-+    S1 = (a[1] * b[2] * Z2Z2) % p
-+    S2 = (b[1] * a[2] * Z1Z1) % p
-+    if U1 == U2 and S1 == S2:
-+        return pointDouble(a)
-+    H = (U2 - U1) % p
-+    I = (4 * H * H) % p
-+    J = (H * I) % p
-+    r = (2 * (S2 - S1)) % p
-+    V = (U1 * I) % p
-+    X3 = (r * r - J - 2 * V) % p
-+    Y3 = (r * (V - X3) - 2 * S1 * J) % p
-+    Z3 = (((a[2] + b[2]) * (a[2] + b[2]) - Z1Z1 - Z2Z2) * H) % p
-+
-+    return (X3, Y3, Z3)
-+
-+
-+def _pointDouble(a):
-+    delta = (a[2] * a[2]) % p
-+    gamma = (a[1] * a[1]) % p
-+    beta = (a[0] * gamma) % p
-+    alpha = (3 * (a[0] - delta) * (a[0] + delta)) % p
-+    X3 = (alpha * alpha - 8 * beta) % p
-+    Z3 = ((a[1] + a[2]) * (a[1] + a[2]) - gamma - delta) % p
-+    Y3 = (alpha * (4 * beta - X3) - 8 * gamma * gamma) % p
-+
-+    return (X3, Y3, Z3)
-+
-+
-+def _square(n):
-+    return (n * n)
-+
-+
-+def _modpow(a, n, p):
-+    if n == 0:
-+        return 1
-+    if n == 1:
-+        return a
-+    r = _square(_modpow(a, n >> 1, p)) % p
-+    if n & 1 == 1:
-+        r = (r * a) % p
-+    return r
-+
-+
-+def _scalarMult(k, point):
-+    accum = (0, 0, 0)
-+    accumIsInfinity = True
-+    jacobianPoint = (point[0], point[1], 1)
-+
-+    for bit in range(255, -1, -1):
-+        if not accumIsInfinity:
-+            accum = _pointDouble(accum)
-+
-+        if (k >> bit) & 1 == 1:
-+            if accumIsInfinity:
-+                accum = jacobianPoint
-+                accumIsInfinity = False
-+            else:
-+                accum = _pointAdd(accum, jacobianPoint)
-+
-+    if accumIsInfinity:
-+        return (0, 0)
-+
-+    zInv = _modpow(accum[2], p - 2, p)
-+    return ((accum[0] * zInv * zInv) % p, (accum[1] * zInv * zInv * zInv) % p)
-+
-+
-+def _scalarBaseMult(k):
-+    return _scalarMult(k, basePoint)
-+
-+
-+def _decodeBigEndian(b):
-+    return sum([ord(b[len(b) - i - 1]) << 8 * i for i in range(len(b))])
-+
-+
-+def _encodeBigEndian(n):
-+    b = []
-+    while n != 0:
-+        b.append(chr(n & 0xff))
-+        n >>= 8
-+
-+    if len(b) == 0:
-+        b.append(0)
-+    b.reverse()
-+
-+    return "".join(b)
-+
-+
-+def _zeroPad(b, length):
-+    if len(b) < length:
-+        return ("\x00" * (length - len(b))) + b
-+    return b
-+
-+
-+def _encodePoint(point):
-+    x = point[0]
-+    y = point[1]
-+    if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
-+        raise "point not on curve"
-+    return "\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad(
-+        _encodeBigEndian(point[1]), 32)
-+
-+
-+def _decodePoint(b):
-+    if len(b) != 1 + 32 + 32 or ord(b[0]) != 4:
-+        raise "invalid encoded ec point"
-+    x = _decodeBigEndian(b[1:33])
-+    y = _decodeBigEndian(b[33:65])
-+    if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
-+        raise "point not on curve"
-+    return (x, y)
-+
-+
-+def generatePublicPrivate():
-+    """generatePublicPrivate returns a tuple of (X9.62 encoded public point,
-+    private value), where the private value is generated from os.urandom."""
-+    private = _decodeBigEndian(os.urandom(40)) % order
-+    return _encodePoint(_scalarBaseMult(private)), private
-+
-+
-+def generateSharedValue(theirPublic, private):
-+    """generateSharedValue returns the encoded x-coordinate of the
-+    multiplication of a peer's X9.62 encoded point and a private value."""
-+    return _zeroPad(
-+        _encodeBigEndian(_scalarMult(private, _decodePoint(theirPublic))[0]),
-+        32)
-+
-+if __name__ == "__main__":
-+    alice, alicePrivate = generatePublicPrivate()
-+    bob, bobPrivate = generatePublicPrivate()
-+
-+    if generateSharedValue(alice, bobPrivate) != generateSharedValue(
-+        bob, alicePrivate):
-+        raise "simple DH test failed"
-+
-+    (x, _) = _scalarBaseMult(1)
-+
-+    for i in range(1000):
-+        (x, _) = _scalarBaseMult(x)
-+
-+    if x != 2428281965257598569040586318034812501729437946720808289049534492833635302706:
-+        raise "loop test failed"
diff --git a/third_party/tlslite/patches/exported_keying_material.patch b/third_party/tlslite/patches/exported_keying_material.patch
deleted file mode 100644
index 9d4ed9c..0000000
--- a/third_party/tlslite/patches/exported_keying_material.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 7363a30..e42b362 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -181,6 +181,8 @@ class TLSConnection(TLSRecordLayer):
-         @type sock: L{socket.socket}
-         """
-         TLSRecordLayer.__init__(self, sock)
-+        self.clientRandom = b""
-+        self.serverRandom = b""
- 
-     #*********************************************************
-     # Client Handshake Functions
-@@ -606,6 +608,9 @@ class TLSConnection(TLSRecordLayer):
-                 else: break
-         masterSecret = result
-         
-+        self.clientRandom = clientHello.random
-+        self.serverRandom = serverHello.random
-+
-         # Create the session object which is used for resumptions
-         self.session = Session()
-         self.session.create(masterSecret, serverHello.session_id, cipherSuite,
-@@ -1398,6 +1403,9 @@ class TLSConnection(TLSRecordLayer):
-                 else: break
-         masterSecret = result
- 
-+        self.clientRandom = clientHello.random
-+        self.serverRandom = serverHello.random
-+
-         #Create the session object
-         self.session = Session()
-         if cipherSuite in CipherSuite.certAllSuites:        
-@@ -2013,3 +2025,22 @@ class TLSConnection(TLSRecordLayer):
-             except:
-                 self._shutdown(False)
-                 raise
-+
-+
-+    def exportKeyingMaterial(self, label, context, use_context, length):
-+        """Returns the exported keying material as defined in RFC 5705."""
-+
-+        seed = self.clientRandom + self.serverRandom
-+        if use_context:
-+            if len(context) > 65535:
-+                raise ValueError("Context is too long")
-+            seed += bytearray(2)
-+            seed[len(seed) - 2] = len(context) >> 8
-+            seed[len(seed) - 1] = len(context) & 0xFF
-+            seed += context
-+        if self.version in ((3,1), (3,2)):
-+            return PRF(self.session.masterSecret, label, seed, length)
-+        elif self.version == (3,3):
-+            return PRF_1_2(self.session.masterSecret, label, seed, length)
-+        else:
-+            raise AssertionError()
diff --git a/third_party/tlslite/patches/extended_master_secret.patch b/third_party/tlslite/patches/extended_master_secret.patch
deleted file mode 100644
index b6ad58dd..0000000
--- a/third_party/tlslite/patches/extended_master_secret.patch
+++ /dev/null
@@ -1,230 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 6d78a20..f9c8676 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -55,6 +55,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     srp = 12            # RFC 5054  
-     cert_type = 9       # RFC 6091
-     signed_cert_timestamps = 18  # RFC 6962
-+    extended_master_secret = 23  # draft-ietf-tls-session-hash-06
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index 605ed42..a7b6ab9 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -111,6 +111,10 @@ class HandshakeSettings(object):
-     @type alertAfterHandshake: bool
-     @ivar alertAfterHandshake: If true, the server will send a fatal
-     alert immediately after the handshake completes.
-+
-+    @type enableExtendedMasterSecret: bool
-+    @ivar enableExtendedMasterSecret: If true, the server supports the extended
-+    master secret TLS extension and will negotiated it with supporting clients.
-     
-     Note that TACK support is not standardized by IETF and uses a temporary
-     TLS Extension number, so should NOT be used in production software.
-@@ -129,6 +133,7 @@ class HandshakeSettings(object):
-         self.tlsIntoleranceType = 'alert'
-         self.useExperimentalTackExtension = False
-         self.alertAfterHandshake = False
-+        self.enableExtendedMasterSecret = True
- 
-     # Validates the min/max fields, and certificateTypes
-     # Filters out unsupported cipherNames and cipherImplementations
-@@ -146,6 +151,7 @@ class HandshakeSettings(object):
-         other.tlsIntolerant = self.tlsIntolerant
-         other.tlsIntoleranceType = self.tlsIntoleranceType
-         other.alertAfterHandshake = self.alertAfterHandshake
-+        other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
- 
-         if not cipherfactory.tripleDESPresent:
-             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-diff --git a/third_party/tlslite/tlslite/mathtls.py b/third_party/tlslite/tlslite/mathtls.py
-index 60a331a..0a23fe1 100644
---- a/third_party/tlslite/tlslite/mathtls.py
-+++ b/third_party/tlslite/tlslite/mathtls.py
-@@ -67,16 +67,20 @@ def PRF_SSL(secret, seed, length):
-             index += 1
-     return bytes
- 
--def calcMasterSecret(version, premasterSecret, clientRandom, serverRandom):
-+def calcMasterSecret(version, premasterSecret, clientRandom, serverRandom,
-+                     handshakeHash, useExtendedMasterSecret):
-+    label = b"master secret"
-+    seed = clientRandom + serverRandom
-+    if useExtendedMasterSecret:
-+        label = b"extended master secret"
-+        seed = handshakeHash
-+
-     if version == (3,0):
--        masterSecret = PRF_SSL(premasterSecret,
--                            clientRandom + serverRandom, 48)
-+        masterSecret = PRF_SSL(premasterSecret, seed, 48)
-     elif version in ((3,1), (3,2)):
--        masterSecret = PRF(premasterSecret, b"master secret",
--                            clientRandom + serverRandom, 48)
-+        masterSecret = PRF(premasterSecret, label, seed, 48)
-     elif version == (3,3):
--        masterSecret = PRF_1_2(premasterSecret, b"master secret",
--                            clientRandom + serverRandom, 48)
-+        masterSecret = PRF_1_2(premasterSecret, label, seed, 48)
-     else:
-         raise AssertionError()
-     return masterSecret
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 9aeff6d..9b553ce 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -114,6 +114,7 @@ class ClientHello(HandshakeMsg):
-         self.supports_npn = False
-         self.server_name = bytearray(0)
-         self.channel_id = False
-+        self.extended_master_secret = False
-         self.support_signed_cert_timestamps = False
-         self.status_request = False
- 
-@@ -185,6 +186,8 @@ class ClientHello(HandshakeMsg):
-                                 break
-                     elif extType == ExtensionType.channel_id:
-                         self.channel_id = True
-+                    elif extType == ExtensionType.extended_master_secret:
-+                        self.extended_master_secret = True
-                     elif extType == ExtensionType.signed_cert_timestamps:
-                         if extLength:
-                             raise SyntaxError()
-@@ -267,6 +270,7 @@ class ServerHello(HandshakeMsg):
-         self.next_protos_advertised = None
-         self.next_protos = None
-         self.channel_id = False
-+        self.extended_master_secret = False
-         self.signed_cert_timestamps = None
-         self.status_request = False
- 
-@@ -358,6 +362,9 @@ class ServerHello(HandshakeMsg):
-         if self.channel_id:
-             w2.add(ExtensionType.channel_id, 2)
-             w2.add(0, 2)
-+        if self.extended_master_secret:
-+            w2.add(ExtensionType.extended_master_secret, 2)
-+            w2.add(0, 2)
-         if self.signed_cert_timestamps:
-             w2.add(ExtensionType.signed_cert_timestamps, 2)
-             w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2)
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index dfac274..04161513 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -981,7 +981,8 @@ class TLSConnection(TLSRecordLayer):
-                 masterSecret = calcMasterSecret(self.version,
-                                          premasterSecret,
-                                          clientRandom,
--                                         serverRandom)
-+                                         serverRandom,
-+                                         b"", False)
-                 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
-             elif self.version in ((3,1), (3,2)):
-                 verifyBytes = self._handshake_md5.digest() + \
-@@ -1036,7 +1037,7 @@ class TLSConnection(TLSRecordLayer):
-                         cipherSuite, cipherImplementations, nextProto):
- 
-         masterSecret = calcMasterSecret(self.version, premasterSecret,
--                            clientRandom, serverRandom)
-+                            clientRandom, serverRandom, b"", False)
-         self._calcPendingStates(cipherSuite, masterSecret, 
-                                 clientRandom, serverRandom, 
-                                 cipherImplementations)
-@@ -1326,6 +1327,9 @@ class TLSConnection(TLSRecordLayer):
-                             cipherSuite, CertificateType.x509, tackExt,
-                             nextProtos)
-         serverHello.channel_id = clientHello.channel_id
-+        serverHello.extended_master_secret = \
-+            clientHello.extended_master_secret and \
-+            settings.enableExtendedMasterSecret
-         if clientHello.support_signed_cert_timestamps:
-             serverHello.signed_cert_timestamps = signedCertTimestamps
-         if clientHello.status_request:
-@@ -1383,7 +1387,8 @@ class TLSConnection(TLSRecordLayer):
-         for result in self._serverFinished(premasterSecret, 
-                                 clientHello.random, serverHello.random,
-                                 cipherSuite, settings.cipherImplementations,
--                                nextProtos, clientHello.channel_id):
-+                                nextProtos, clientHello.channel_id,
-+                                serverHello.extended_master_secret):
-                 if result in (0,1): yield result
-                 else: break
-         masterSecret = result
-@@ -1523,6 +1528,9 @@ class TLSConnection(TLSRecordLayer):
-                 serverHello.create(self.version, getRandomBytes(32),
-                                    session.sessionID, session.cipherSuite,
-                                    CertificateType.x509, None, None)
-+                serverHello.extended_master_secret = \
-+                    clientHello.extended_master_secret and \
-+                    settings.enableExtendedMasterSecret
-                 for result in self._sendMsg(serverHello):
-                     yield result
- 
-@@ -1743,7 +1751,8 @@ class TLSConnection(TLSRecordLayer):
-         if clientCertChain:
-             if self.version == (3,0):
-                 masterSecret = calcMasterSecret(self.version, premasterSecret,
--                                         clientHello.random, serverHello.random)
-+                                         clientHello.random, serverHello.random,
-+                                         b"", False)
-                 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
-             elif self.version in ((3,1), (3,2)):
-                 verifyBytes = self._handshake_md5.digest() + \
-@@ -1827,9 +1836,11 @@ class TLSConnection(TLSRecordLayer):
- 
-     def _serverFinished(self,  premasterSecret, clientRandom, serverRandom,
-                         cipherSuite, cipherImplementations, nextProtos,
--                        doingChannelID):
-+                        doingChannelID, useExtendedMasterSecret):
-         masterSecret = calcMasterSecret(self.version, premasterSecret,
--                                      clientRandom, serverRandom)
-+                                      clientRandom, serverRandom,
-+                                      self._ems_handshake_hash,
-+                                      useExtendedMasterSecret)
-         
-         #Calculate pending connection states
-         self._calcPendingStates(cipherSuite, masterSecret, 
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index c3bcd8c..d2320b8 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -119,6 +119,7 @@ class TLSRecordLayer(object):
-         self._handshake_md5 = hashlib.md5()
-         self._handshake_sha = hashlib.sha1()
-         self._handshake_sha256 = hashlib.sha256()
-+        self._ems_handshake_hash = b""
- 
-         #TLS Protocol Version
-         self.version = (0,0) #read-only
-@@ -814,6 +815,8 @@ class TLSRecordLayer(object):
-                 self._handshake_md5.update(compat26Str(p.bytes))
-                 self._handshake_sha.update(compat26Str(p.bytes))
-                 self._handshake_sha256.update(compat26Str(p.bytes))
-+                if subType == HandshakeType.client_key_exchange:
-+                    self._ems_handshake_hash = self._getHandshakeHash()
- 
-                 #Parse based on handshake type
-                 if subType == HandshakeType.client_hello:
-@@ -1112,6 +1115,7 @@ class TLSRecordLayer(object):
-         self._handshake_md5 = hashlib.md5()
-         self._handshake_sha = hashlib.sha1()
-         self._handshake_sha256 = hashlib.sha256()
-+        self._ems_handshake_hash = b""
-         self._handshakeBuffer = []
-         self.allegedSrpUsername = None
-         self._refCount = 1
-@@ -1256,3 +1260,9 @@ class TLSRecordLayer(object):
- 
-         return md5Bytes + shaBytes
- 
-+    def _getHandshakeHash(self):
-+        if self.version in ((3,1), (3,2)):
-+            return self._handshake_md5.digest() + \
-+                self._handshake_sha.digest()
-+        elif self.version == (3,3):
-+            return self._handshake_sha256.digest()
diff --git a/third_party/tlslite/patches/extension_number_update.patch b/third_party/tlslite/patches/extension_number_update.patch
deleted file mode 100644
index 024d7c9..0000000
--- a/third_party/tlslite/patches/extension_number_update.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 84bb703..715def9 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -55,11 +55,11 @@ class ExtensionType:    # RFC 6066 / 4366
-     srp = 12            # RFC 5054  
-     cert_type = 9       # RFC 6091
-     signed_cert_timestamps = 18  # RFC 6962
--    extended_master_secret = 23  # draft-ietf-tls-session-hash-06
-+    extended_master_secret = 23  # RFC 7627
-+    token_binding = 24           # draft-ietf-tokbind-negotiation
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
--    token_binding = 30033
- 
- class HashAlgorithm:
-     none = 0
diff --git a/third_party/tlslite/patches/fallback_scsv.patch b/third_party/tlslite/patches/fallback_scsv.patch
deleted file mode 100644
index 460468b..0000000
--- a/third_party/tlslite/patches/fallback_scsv.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 8720de6..69e6067 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -107,6 +107,7 @@ class AlertDescription:
-     protocol_version = 70
-     insufficient_security = 71
-     internal_error = 80
-+    inappropriate_fallback = 86
-     user_canceled = 90
-     no_renegotiation = 100
-     unknown_psk_identity = 115
-@@ -118,6 +119,9 @@ class CipherSuite:
-     # We actually don't do any renegotiation, but this
-     # prevents renegotiation attacks
-     TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF
-+
-+    # draft-ietf-tls-downgrade-scsv-03
-+    TLS_FALLBACK_SCSV = 0x5600
-     
-     TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA  = 0xC01A
-     TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D
-diff --git a/third_party/tlslite/tlslite/errors.py b/third_party/tlslite/tlslite/errors.py
-index 22c298c..001ef33 100644
---- a/third_party/tlslite/tlslite/errors.py
-+++ b/third_party/tlslite/tlslite/errors.py
-@@ -63,6 +63,7 @@ class TLSAlert(TLSError):
-         AlertDescription.protocol_version: "protocol_version",\
-         AlertDescription.insufficient_security: "insufficient_security",\
-         AlertDescription.internal_error: "internal_error",\
-+        AlertDescription.inappropriate_fallback: "inappropriate_fallback",\
-         AlertDescription.user_canceled: "user_canceled",\
-         AlertDescription.no_renegotiation: "no_renegotiation",\
-         AlertDescription.unknown_psk_identity: "unknown_psk_identity"}
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 4dedc5f..0563fb5f 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -969,7 +969,8 @@ class TLSConnection(TLSRecordLayer):
-                         reqCAs = None, 
-                         tacks=None, activationFlags=0,
-                         nextProtos=None, anon=False,
--                        tlsIntolerant=None, signedCertTimestamps=None):
-+                        tlsIntolerant=None, signedCertTimestamps=None,
-+                        fallbackSCSV=False):
-         """Perform a handshake in the role of server.
- 
-         This function performs an SSL or TLS handshake.  Depending on
-@@ -1048,6 +1049,11 @@ class TLSConnection(TLSRecordLayer):
-         binary 8-bit string) that will be sent as a TLS extension whenever
-         the client announces support for the extension.
- 
-+        @type fallbackSCSV: bool
-+        @param fallbackSCSV: if true, the server will implement
-+        TLS_FALLBACK_SCSV and thus reject connections using less than the
-+        server's maximum TLS version that include this cipher suite.
-+
-         @raise socket.error: If a socket error occurs.
-         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-         without a preceding alert.
-@@ -1060,7 +1066,8 @@ class TLSConnection(TLSRecordLayer):
-                 checker, reqCAs, 
-                 tacks=tacks, activationFlags=activationFlags, 
-                 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
--                signedCertTimestamps=signedCertTimestamps):
-+                signedCertTimestamps=signedCertTimestamps,
-+                fallbackSCSV=fallbackSCSV):
-             pass
- 
- 
-@@ -1071,7 +1078,8 @@ class TLSConnection(TLSRecordLayer):
-                              tacks=None, activationFlags=0,
-                              nextProtos=None, anon=False,
-                              tlsIntolerant=None,
--                             signedCertTimestamps=None
-+                             signedCertTimestamps=None,
-+                             fallbackSCSV=False
-                              ):
-         """Start a server handshake operation on the TLS connection.
- 
-@@ -1092,7 +1100,8 @@ class TLSConnection(TLSRecordLayer):
-             tacks=tacks, activationFlags=activationFlags, 
-             nextProtos=nextProtos, anon=anon,
-             tlsIntolerant=tlsIntolerant,
--            signedCertTimestamps=signedCertTimestamps)
-+            signedCertTimestamps=signedCertTimestamps,
-+            fallbackSCSV=fallbackSCSV)
-         for result in self._handshakeWrapperAsync(handshaker, checker):
-             yield result
- 
-@@ -1102,7 +1111,7 @@ class TLSConnection(TLSRecordLayer):
-                              settings, reqCAs, 
-                              tacks, activationFlags, 
-                              nextProtos, anon,
--                             tlsIntolerant, signedCertTimestamps):
-+                             tlsIntolerant, signedCertTimestamps, fallbackSCSV):
- 
-         self._handshakeStart(client=False)
- 
-@@ -1137,7 +1146,7 @@ class TLSConnection(TLSRecordLayer):
-         # Handle ClientHello and resumption
-         for result in self._serverGetClientHello(settings, certChain,\
-                                             verifierDB, sessionCache,
--                                            anon, tlsIntolerant):
-+                                            anon, tlsIntolerant, fallbackSCSV):
-             if result in (0,1): yield result
-             elif result == None:
-                 self._handshakeDone(resumed=True)                
-@@ -1237,7 +1246,7 @@ class TLSConnection(TLSRecordLayer):
- 
- 
-     def _serverGetClientHello(self, settings, certChain, verifierDB,
--                                sessionCache, anon, tlsIntolerant):
-+                                sessionCache, anon, tlsIntolerant, fallbackSCSV):
-         #Initialize acceptable cipher suites
-         cipherSuites = []
-         if verifierDB:
-@@ -1283,6 +1292,14 @@ class TLSConnection(TLSRecordLayer):
-         elif clientHello.client_version > settings.maxVersion:
-             self.version = settings.maxVersion
- 
-+        #Detect if the client performed an inappropriate fallback.
-+        elif fallbackSCSV and clientHello.client_version < settings.maxVersion:
-+            self.version = clientHello.client_version
-+            if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites:
-+                for result in self._sendError(\
-+                        AlertDescription.inappropriate_fallback):
-+                    yield result
-+
-         else:
-             #Set the version to the client's version
-             self.version = clientHello.client_version  
diff --git a/third_party/tlslite/patches/fix_test_file.patch b/third_party/tlslite/patches/fix_test_file.patch
deleted file mode 100644
index 891b556..0000000
--- a/third_party/tlslite/patches/fix_test_file.patch
+++ /dev/null
@@ -1,8 +0,0 @@
-diff --git a/third_party/tlslite/tests/httpsserver.sh b/third_party/tlslite/tests/httpsserver.sh
-index 046eb2e..7449ad7 100755
---- a/third_party/tlslite/tests/httpsserver.sh
-+++ b/third_party/tlslite/tests/httpsserver.sh
-@@ -1,2 +1,2 @@
--# /bin/sh
-+#!/bin/sh
- python ../scripts/tls.py server -k serverX509Key.pem -c serverX509Cert.pem -t TACK1.pem localhost:4443
diff --git a/third_party/tlslite/patches/ignore_write_failure.patch b/third_party/tlslite/patches/ignore_write_failure.patch
deleted file mode 100644
index 0a5e960..0000000
--- a/third_party/tlslite/patches/ignore_write_failure.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index 6ef3895..3584726 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -288,7 +288,9 @@ class TLSRecordLayer(object):
-         except GeneratorExit:
-             raise
-         except Exception:
--            self._shutdown(False)
-+            # Don't invalidate the session on write failure if abrupt closes are
-+            # okay.
-+            self._shutdown(self.ignoreAbruptClose)
-             raise
- 
-     def close(self):
diff --git a/third_party/tlslite/patches/intolerance_options.patch b/third_party/tlslite/patches/intolerance_options.patch
deleted file mode 100644
index 2aee3c6..0000000
--- a/third_party/tlslite/patches/intolerance_options.patch
+++ /dev/null
@@ -1,192 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index 7998e2e..2e9e06d 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -19,6 +19,7 @@ ALL_MAC_NAMES = ["sha", "sha256", "md5"]
- KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
- CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
- CERTIFICATE_TYPES = ["x509"]
-+TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"]
- 
- class HandshakeSettings(object):
-     """This class encapsulates various parameters that can be used with
-@@ -91,6 +92,21 @@ class HandshakeSettings(object):
-     version, a protocol_version alert will be signalled.  The default is (3,3).
-     (WARNING: Some servers may (improperly) reject clients which offer support
-     for TLS 1.1.  In this case, try lowering maxVersion to (3,1)).
-+
-+    @type tlsIntolerant: tuple
-+    @ivar tlsIntolerant: The TLS ClientHello version which the server
-+    simulates intolerance of.
-+
-+    If tlsIntolerant is not None, the server will simulate TLS version
-+    intolerance by aborting the handshake in response to all TLS versions
-+    tlsIntolerant or higher.
-+
-+    @type tlsIntoleranceType: str
-+    @ivar tlsIntoleranceType: How the server should react when simulating TLS
-+    intolerance.
-+
-+    The allowed values are "alert" (return a fatal handshake_failure alert),
-+    "close" (abruptly close the connection), and "reset" (send a TCP reset).
-     
-     @type useExperimentalTackExtension: bool
-     @ivar useExperimentalTackExtension: Whether to enabled TACK support.
-@@ -108,6 +124,8 @@ class HandshakeSettings(object):
-         self.certificateTypes = CERTIFICATE_TYPES
-         self.minVersion = (3,1)
-         self.maxVersion = (3,3)
-+        self.tlsIntolerant = None
-+        self.tlsIntoleranceType = 'alert'
-         self.useExperimentalTackExtension = False
- 
-     # Validates the min/max fields, and certificateTypes
-@@ -123,6 +141,8 @@ class HandshakeSettings(object):
-         other.certificateTypes = self.certificateTypes
-         other.minVersion = self.minVersion
-         other.maxVersion = self.maxVersion
-+        other.tlsIntolerant = self.tlsIntolerant
-+        other.tlsIntoleranceType = self.tlsIntoleranceType
- 
-         if not cipherfactory.tripleDESPresent:
-             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-@@ -164,6 +184,10 @@ class HandshakeSettings(object):
-             if s not in CERTIFICATE_TYPES:
-                 raise ValueError("Unknown certificate type: '%s'" % s)
- 
-+        if other.tlsIntoleranceType not in TLS_INTOLERANCE_TYPES:
-+            raise ValueError(
-+                "Unknown TLS intolerance type: '%s'" % other.tlsIntoleranceType)
-+
-         if other.minVersion > other.maxVersion:
-             raise ValueError("Versions set incorrectly")
- 
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index f8547d5..4f3ba1c 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1073,7 +1073,7 @@ class TLSConnection(TLSRecordLayer):
-                         reqCAs = None, reqCertTypes = None,
-                         tacks=None, activationFlags=0,
-                         nextProtos=None, anon=False,
--                        tlsIntolerant=None, signedCertTimestamps=None,
-+                        signedCertTimestamps=None,
-                         fallbackSCSV=False, ocspResponse=None):
-         """Perform a handshake in the role of server.
- 
-@@ -1147,11 +1147,6 @@ class TLSConnection(TLSRecordLayer):
-         clients through the Next-Protocol Negotiation Extension, 
-         if they support it.
- 
--        @type tlsIntolerant: (int, int) or None
--        @param tlsIntolerant: If tlsIntolerant is not None, the server will
--        simulate TLS version intolerance by returning a fatal handshake_failure
--        alert to all TLS versions tlsIntolerant or higher.
--
-         @type signedCertTimestamps: str
-         @param signedCertTimestamps: A SignedCertificateTimestampList (as a
-         binary 8-bit string) that will be sent as a TLS extension whenever
-@@ -1183,7 +1178,7 @@ class TLSConnection(TLSRecordLayer):
-                 certChain, privateKey, reqCert, sessionCache, settings,
-                 checker, reqCAs, reqCertTypes,
-                 tacks=tacks, activationFlags=activationFlags, 
--                nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
-+                nextProtos=nextProtos, anon=anon,
-                 signedCertTimestamps=signedCertTimestamps,
-                 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
-             pass
-@@ -1195,7 +1190,6 @@ class TLSConnection(TLSRecordLayer):
-                              reqCAs=None, reqCertTypes=None,
-                              tacks=None, activationFlags=0,
-                              nextProtos=None, anon=False,
--                             tlsIntolerant=None,
-                              signedCertTimestamps=None,
-                              fallbackSCSV=False,
-                              ocspResponse=None
-@@ -1218,7 +1212,6 @@ class TLSConnection(TLSRecordLayer):
-             reqCAs=reqCAs, reqCertTypes=reqCertTypes,
-             tacks=tacks, activationFlags=activationFlags, 
-             nextProtos=nextProtos, anon=anon,
--            tlsIntolerant=tlsIntolerant,
-             signedCertTimestamps=signedCertTimestamps,
-             fallbackSCSV=fallbackSCSV,
-             ocspResponse=ocspResponse)
-@@ -1231,7 +1224,7 @@ class TLSConnection(TLSRecordLayer):
-                              settings, reqCAs, reqCertTypes,
-                              tacks, activationFlags, 
-                              nextProtos, anon,
--                             tlsIntolerant, signedCertTimestamps, fallbackSCSV,
-+                             signedCertTimestamps, fallbackSCSV,
-                              ocspResponse):
- 
-         self._handshakeStart(client=False)
-@@ -1269,7 +1262,7 @@ class TLSConnection(TLSRecordLayer):
-         # Handle ClientHello and resumption
-         for result in self._serverGetClientHello(settings, certChain,\
-                                             verifierDB, sessionCache,
--                                            anon, tlsIntolerant, fallbackSCSV):
-+                                            anon, fallbackSCSV):
-             if result in (0,1): yield result
-             elif result == None:
-                 self._handshakeDone(resumed=True)                
-@@ -1384,7 +1377,7 @@ class TLSConnection(TLSRecordLayer):
- 
- 
-     def _serverGetClientHello(self, settings, certChain, verifierDB,
--                                sessionCache, anon, tlsIntolerant, fallbackSCSV):
-+                                sessionCache, anon, fallbackSCSV):
-         #Initialize acceptable cipher suites
-         cipherSuites = []
-         if verifierDB:
-@@ -1421,11 +1414,21 @@ class TLSConnection(TLSRecordLayer):
-                 yield result
- 
-         #If simulating TLS intolerance, reject certain TLS versions.
--        elif (tlsIntolerant is not None and
--            clientHello.client_version >= tlsIntolerant):
--            for result in self._sendError(\
-+        elif (settings.tlsIntolerant is not None and
-+              clientHello.client_version >= settings.tlsIntolerant):
-+            if settings.tlsIntoleranceType == "alert":
-+                for result in self._sendError(\
-                     AlertDescription.handshake_failure):
--                yield result
-+                    yield result
-+            elif settings.tlsIntoleranceType == "close":
-+                self._abruptClose()
-+                raise TLSUnsupportedError("Simulating version intolerance")
-+            elif settings.tlsIntoleranceType == "reset":
-+                self._abruptClose(reset=True)
-+                raise TLSUnsupportedError("Simulating version intolerance")
-+            else:
-+                raise ValueError("Unknown intolerance type: '%s'" %
-+                                 settings.tlsIntoleranceType)
- 
-         #If client's version is too high, propose my highest version
-         elif clientHello.client_version > settings.maxVersion:
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index 3584726..eda11e6 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -20,6 +20,7 @@ from .constants import *
- from .utils.cryptomath import getRandomBytes
- 
- import socket
-+import struct
- import errno
- import traceback
- 
-@@ -527,6 +528,13 @@ class TLSRecordLayer(object):
-         self._shutdown(False)
-         raise TLSLocalAlert(alert, errorStr)
- 
-+    def _abruptClose(self, reset=False):
-+        if reset:
-+            #Set an SO_LINGER timeout of 0 to send a TCP RST.
-+            self.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
-+                            struct.pack('ii', 1, 0))
-+        self._shutdown(False)
-+
-     def _sendMsgs(self, msgs):
-         randomizeFirstBlock = True
-         for msg in msgs:
diff --git a/third_party/tlslite/patches/python3.patch b/third_party/tlslite/patches/python3.patch
deleted file mode 100644
index 12cffa1f..0000000
--- a/third_party/tlslite/patches/python3.patch
+++ /dev/null
@@ -1,272 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/integration/asyncstatemachine.py b/third_party/tlslite/tlslite/integration/asyncstatemachine.py
-index 50a6f4a355c14..9faf84f966a31 100644
---- a/third_party/tlslite/tlslite/integration/asyncstatemachine.py
-+++ b/third_party/tlslite/tlslite/integration/asyncstatemachine.py
-@@ -192,7 +192,7 @@ class AsyncStateMachine:
-         @type handshaker: generator
-         @param handshaker: A generator created by using one of the
-         asynchronous handshake functions (i.e. handshakeServerAsync, or
--        handshakeClientxxx(..., async=True).
-+        handshakeClientxxx(..., is_async=True).
-         """
-         try:
-             self._checkAssert(0)
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index ce4f1a6e15eb2..5df50d34cd3ad 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -9,6 +9,8 @@
- 
- """Classes representing TLS messages."""
- 
-+from __future__ import division
-+
- from .utils.compat import *
- from .utils.cryptomath import *
- from .errors import *
-@@ -262,7 +264,7 @@ class ClientHello(HandshakeMsg):
-                         numBytes = p.get(2)
-                         if numBytes + 2 != extLength or numBytes % 2 != 0:
-                             raise SyntaxError()
--                        for _ in range(numBytes / 2):
-+                        for _ in range(numBytes // 2):
-                             hashAlg = p.get(1)
-                             sigAlg = p.get(1)
-                             self.signature_algorithms.append((hashAlg, sigAlg))
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 6d7c859884a41..f64c848a511c0 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -202,7 +202,7 @@ class TLSConnection(TLSRecordLayer):
- 
-     def handshakeClientAnonymous(self, session=None, settings=None, 
-                                 checker=None, serverName="",
--                                async=False):
-+                                is_async=False):
-         """Perform an anonymous handshake in the role of client.
- 
-         This function performs an SSL or TLS handshake using an
-@@ -236,8 +236,8 @@ class TLSConnection(TLSRecordLayer):
-         @type serverName: string
-         @param serverName: The ServerNameIndication TLS Extension.
- 
--        @type async: bool
--        @param async: If False, this function will block until the
-+        @type is_async: bool
-+        @param is_async: If False, this function will block until the
-         handshake is completed.  If True, this function will return a
-         generator.  Successive invocations of the generator will
-         return 0 if it is waiting to read from the socket, 1 if it is
-@@ -245,7 +245,7 @@ class TLSConnection(TLSRecordLayer):
-         the handshake operation is completed.
- 
-         @rtype: None or an iterable
--        @return: If 'async' is True, a generator object will be
-+        @return: If 'is_async' is True, a generator object will be
-         returned.
- 
-         @raise socket.error: If a socket error occurs.
-@@ -260,7 +260,7 @@ class TLSConnection(TLSRecordLayer):
-                                                 settings=settings,
-                                                 checker=checker,
-                                                 serverName=serverName)
--        if async:
-+        if is_async:
-             return handshaker
-         for result in handshaker:
-             pass
-@@ -268,7 +268,7 @@ class TLSConnection(TLSRecordLayer):
-     def handshakeClientSRP(self, username, password, session=None,
-                            settings=None, checker=None, 
-                            reqTack=True, serverName="",
--                           async=False):
-+                           is_async=False):
-         """Perform an SRP handshake in the role of client.
- 
-         This function performs a TLS/SRP handshake.  SRP mutually
-@@ -313,8 +313,8 @@ class TLSConnection(TLSRecordLayer):
-         @type serverName: string
-         @param serverName: The ServerNameIndication TLS Extension.
- 
--        @type async: bool
--        @param async: If False, this function will block until the
-+        @type is_async: bool
-+        @param is_async: If False, this function will block until the
-         handshake is completed.  If True, this function will return a
-         generator.  Successive invocations of the generator will
-         return 0 if it is waiting to read from the socket, 1 if it is
-@@ -322,7 +322,7 @@ class TLSConnection(TLSRecordLayer):
-         the handshake operation is completed.
- 
-         @rtype: None or an iterable
--        @return: If 'async' is True, a generator object will be
-+        @return: If 'is_async' is True, a generator object will be
-         returned.
- 
-         @raise socket.error: If a socket error occurs.
-@@ -340,9 +340,9 @@ class TLSConnection(TLSRecordLayer):
-         # fashion, returning 1 when it is waiting to able to write, 0 when
-         # it is waiting to read.
-         #
--        # If 'async' is True, the generator is returned to the caller, 
--        # otherwise it is executed to completion here.  
--        if async:
-+        # If 'is_async' is True, the generator is returned to the caller,
-+        # otherwise it is executed to completion here.
-+        if is_async:
-             return handshaker
-         for result in handshaker:
-             pass
-@@ -350,7 +350,7 @@ class TLSConnection(TLSRecordLayer):
-     def handshakeClientCert(self, certChain=None, privateKey=None,
-                             session=None, settings=None, checker=None,
-                             nextProtos=None, reqTack=True, serverName="",
--                            async=False):
-+                            is_async=False):
-         """Perform a certificate-based handshake in the role of client.
- 
-         This function performs an SSL or TLS handshake.  The server
-@@ -407,8 +407,8 @@ class TLSConnection(TLSRecordLayer):
-         @type serverName: string
-         @param serverName: The ServerNameIndication TLS Extension.
- 
--        @type async: bool
--        @param async: If False, this function will block until the
-+        @type is_async: bool
-+        @param is_async: If False, this function will block until the
-         handshake is completed.  If True, this function will return a
-         generator.  Successive invocations of the generator will
-         return 0 if it is waiting to read from the socket, 1 if it is
-@@ -416,7 +416,7 @@ class TLSConnection(TLSRecordLayer):
-         the handshake operation is completed.
- 
-         @rtype: None or an iterable
--        @return: If 'async' is True, a generator object will be
-+        @return: If 'is_async' is True, a generator object will be
-         returned.
- 
-         @raise socket.error: If a socket error occurs.
-@@ -435,9 +435,9 @@ class TLSConnection(TLSRecordLayer):
-         # fashion, returning 1 when it is waiting to able to write, 0 when
-         # it is waiting to read.
-         #
--        # If 'async' is True, the generator is returned to the caller, 
--        # otherwise it is executed to completion here.                        
--        if async:
-+        # If 'is_async' is True, the generator is returned to the caller,
-+        # otherwise it is executed to completion here.
-+        if is_async:
-             return handshaker
-         for result in handshaker:
-             pass
-@@ -1368,10 +1368,10 @@ class TLSConnection(TLSRecordLayer):
-         # See https://tools.ietf.org/html/rfc8446#section-4.1.3
-         if settings.simulateTLS13Downgrade:
-             serverRandom = serverRandom[:24] + \
--                bytearray("\x44\x4f\x57\x4e\x47\x52\x44\x01")
-+                bytearray(b"\x44\x4f\x57\x4e\x47\x52\x44\x01")
-         elif settings.simulateTLS12Downgrade:
-             serverRandom = serverRandom[:24] + \
--                bytearray("\x44\x4f\x57\x4e\x47\x52\x44\x00")
-+                bytearray(b"\x44\x4f\x57\x4e\x47\x52\x44\x00")
-         serverHello = ServerHello()
-         serverHello.create(self.version, serverRandom, sessionID, \
-                             cipherSuite, CertificateType.x509, tackExt,
-diff --git a/third_party/tlslite/tlslite/utils/aesgcm.py b/third_party/tlslite/tlslite/utils/aesgcm.py
-index 7319c268536a3..c887f2f518e77 100644
---- a/third_party/tlslite/tlslite/utils/aesgcm.py
-+++ b/third_party/tlslite/tlslite/utils/aesgcm.py
-@@ -13,6 +13,8 @@
- # x^127 term. This bit reversal also applies to polynomials used as indices in a
- # look-up table.
- 
-+from __future__ import division
-+
- from .cryptomath import bytesToNumber, numberToByteArray
- 
- class AESGCM(object):
-@@ -47,7 +49,7 @@ class AESGCM(object):
-         self._productTable[_reverseBits(1)] = h
-         for i in range(2, 16, 2):
-             self._productTable[_reverseBits(i)] = \
--                _gcmShift(self._productTable[_reverseBits(i/2)])
-+                _gcmShift(self._productTable[_reverseBits(i//2)])
-             self._productTable[_reverseBits(i+1)] = \
-                 _gcmAdd(self._productTable[_reverseBits(i)], h)
- 
-diff --git a/third_party/tlslite/tlslite/utils/p256.py b/third_party/tlslite/tlslite/utils/p256.py
-index 6eb9a7799accc..45159000fa499 100644
---- a/third_party/tlslite/tlslite/utils/p256.py
-+++ b/third_party/tlslite/tlslite/utils/p256.py
-@@ -2,6 +2,7 @@
- # See the LICENSE file for legal information regarding use of this file.
- 
- import os
-+import six
- 
- p = (
-     115792089210356248762697446949407573530086143415290314195533631308867097853951)
-@@ -90,25 +91,27 @@ def _scalarBaseMult(k):
- 
- 
- def _decodeBigEndian(b):
--    return sum([ord(b[len(b) - i - 1]) << 8 * i for i in range(len(b))])
-+    # TODO(davidben): Replace with int.from_bytes when removing Python 2.
-+    return sum([six.indexbytes(b, len(b) - i - 1) << 8 * i
-+                for i in range(len(b))])
- 
- 
- def _encodeBigEndian(n):
--    b = []
-+    b = bytearray()
-     while n != 0:
--        b.append(chr(n & 0xff))
-+        b.append(n & 0xff)
-         n >>= 8
- 
-     if len(b) == 0:
-         b.append(0)
-     b.reverse()
- 
--    return "".join(b)
-+    return bytes(b)
- 
- 
- def _zeroPad(b, length):
-     if len(b) < length:
--        return ("\x00" * (length - len(b))) + b
-+        return (b"\x00" * (length - len(b))) + b
-     return b
- 
- 
-@@ -117,12 +120,12 @@ def _encodePoint(point):
-     y = point[1]
-     if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
-         raise "point not on curve"
--    return "\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad(
-+    return b"\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad(
-         _encodeBigEndian(point[1]), 32)
- 
- 
- def _decodePoint(b):
--    if len(b) != 1 + 32 + 32 or ord(b[0]) != 4:
-+    if len(b) != 1 + 32 + 32 or six.indexbytes(b, 0) != 4:
-         raise "invalid encoded ec point"
-     x = _decodeBigEndian(b[1:33])
-     y = _decodeBigEndian(b[33:65])
-diff --git a/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py b/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py
-index d76ea2d1b13a6..453785664565c 100644
---- a/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py
-+++ b/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py
-@@ -15,9 +15,9 @@ if pycryptoLoaded:
-     class PyCrypto_RSAKey(RSAKey):
-         def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
-             if not d:
--                self.rsa = RSA.construct( (long(n), long(e)) )
-+                self.rsa = RSA.construct( (n, e) )
-             else:
--                self.rsa = RSA.construct( (long(n), long(e), long(d), long(p), long(q)) )
-+                self.rsa = RSA.construct( (n, e, d, p, q) )
- 
-         def __getattr__(self, name):
-             return getattr(self.rsa, name)
diff --git a/third_party/tlslite/patches/renegotiation_indication.patch b/third_party/tlslite/patches/renegotiation_indication.patch
deleted file mode 100644
index 69a1d7b5..0000000
--- a/third_party/tlslite/patches/renegotiation_indication.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index e9743e4..82e8c07 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -61,6 +61,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
-+    renegotiation_info = 0xFF01 # RFC 5746
- 
- class HashAlgorithm:
-     none = 0
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 1ce9320..ac7e563 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -140,6 +140,7 @@ class ClientHello(HandshakeMsg):
-         self.tb_client_params = []
-         self.support_signed_cert_timestamps = False
-         self.status_request = False
-+        self.ri = False
- 
-     def create(self, version, random, session_id, cipher_suites,
-                certificate_types=None, srpUsername=None,
-@@ -244,12 +245,20 @@ class ClientHello(HandshakeMsg):
-                         # request_extensions in the OCSP request.
-                         p.getFixBytes(extLength)
-                         self.status_request = True
-+                    elif extType == ExtensionType.renegotiation_info:
-+                        # We don't support renegotiation, so if we receive this
-+                        # extension, it should contain a single null byte.
-+                        if extLength != 1 or p.getFixBytes(extLength)[0] != 0:
-+                            raise SyntaxError()
-+                        self.ri = True
-                     else:
-                         _ = p.getFixBytes(extLength)
-                     index2 = p.index
-                     if index2 - index1 != extLength:
-                         raise SyntaxError("Bad length for extension_data")
-                     soFar += 4 + extLength
-+            if CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV in self.cipher_suites:
-+                self.ri = True
-             p.stopLengthCheck()
-         return self
- 
-@@ -327,6 +336,7 @@ class ServerHello(HandshakeMsg):
-         self.tb_params = None
-         self.signed_cert_timestamps = None
-         self.status_request = False
-+        self.send_ri = False
- 
-     def create(self, version, random, session_id, cipher_suite,
-                certificate_type, tackExt, alpn_proto_selected,
-@@ -432,6 +442,10 @@ class ServerHello(HandshakeMsg):
-         if self.status_request:
-             w2.add(ExtensionType.status_request, 2)
-             w2.add(0, 2)
-+        if self.send_ri:
-+            w2.add(ExtensionType.renegotiation_info, 2)
-+            w2.add(1, 2)
-+            w2.add(0, 1)
-         if len(w2.bytes):
-             w.add(len(w2.bytes), 2)
-             w.bytes += w2.bytes        
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index de5d580..8ba1c6e 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1370,6 +1370,8 @@ class TLSConnection(TLSRecordLayer):
-             serverHello.signed_cert_timestamps = signedCertTimestamps
-         if clientHello.status_request:
-             serverHello.status_request = ocspResponse
-+        if clientHello.ri:
-+            serverHello.send_ri = True
- 
-         # Perform the SRP key exchange
-         clientCertChain = None
-@@ -1583,6 +1585,8 @@ class TLSConnection(TLSRecordLayer):
-                     if param in settings.supportedTokenBindingParams:
-                           serverHello.tb_params = param
-                           break
-+                if clientHello.ri:
-+                    serverHello.send_ri = True
-                 for result in self._sendMsg(serverHello):
-                     yield result
- 
diff --git a/third_party/tlslite/patches/req_cert_types.patch b/third_party/tlslite/patches/req_cert_types.patch
deleted file mode 100644
index 4e69003..0000000
--- a/third_party/tlslite/patches/req_cert_types.patch
+++ /dev/null
@@ -1,163 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/api.py b/third_party/tlslite/tlslite/api.py
-index fa6a18c..aabcc14 100644
---- a/third_party/tlslite/tlslite/api.py
-+++ b/third_party/tlslite/tlslite/api.py
-@@ -2,7 +2,8 @@
- # See the LICENSE file for legal information regarding use of this file.
- 
- __version__ = "0.4.8"
--from .constants import AlertLevel, AlertDescription, Fault
-+from .constants import AlertLevel, AlertDescription, ClientCertificateType, \
-+                       Fault
- from .errors import *
- from .checker import Checker
- from .handshakesettings import HandshakeSettings
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index d2d50c5..7ee70be 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -15,10 +15,14 @@ class CertificateType:
-     openpgp = 1
- 
- class ClientCertificateType:
-+    # http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2
-     rsa_sign = 1
-     dss_sign = 2
-     rsa_fixed_dh = 3
-     dss_fixed_dh = 4
-+    ecdsa_sign = 64
-+    rsa_fixed_ecdh = 65
-+    ecdsa_fixed_ecdh = 66
-  
- class HandshakeType:
-     hello_request = 0
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 8b77ee6..e1be195 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -455,17 +455,14 @@ class CertificateStatus(HandshakeMsg):
- class CertificateRequest(HandshakeMsg):
-     def __init__(self, version):
-         HandshakeMsg.__init__(self, HandshakeType.certificate_request)
--        #Apple's Secure Transport library rejects empty certificate_types, so
--        #default to rsa_sign.
--        self.certificate_types = [ClientCertificateType.rsa_sign]
-+        self.certificate_types = []
-         self.certificate_authorities = []
-         self.version = version
-         self.supported_signature_algs = []
- 
--    def create(self, certificate_types, certificate_authorities, sig_algs=(), version=(3,0)):
-+    def create(self, certificate_types, certificate_authorities, sig_algs=()):
-         self.certificate_types = certificate_types
-         self.certificate_authorities = certificate_authorities
--        self.version = version
-         self.supported_signature_algs = sig_algs
-         return self
- 
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index f6d13d4..f8547d5 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1070,7 +1070,7 @@ class TLSConnection(TLSRecordLayer):
-     def handshakeServer(self, verifierDB=None,
-                         certChain=None, privateKey=None, reqCert=False,
-                         sessionCache=None, settings=None, checker=None,
--                        reqCAs = None, 
-+                        reqCAs = None, reqCertTypes = None,
-                         tacks=None, activationFlags=0,
-                         nextProtos=None, anon=False,
-                         tlsIntolerant=None, signedCertTimestamps=None,
-@@ -1138,6 +1138,10 @@ class TLSConnection(TLSRecordLayer):
-         will be sent along with a certificate request. This does not affect
-         verification.        
- 
-+        @type reqCertTypes: list of int
-+        @param reqCertTypes: A list of certificate_type values to be sent
-+        along with a certificate request. This does not affect verification.
-+
-         @type nextProtos: list of strings.
-         @param nextProtos: A list of upper layer protocols to expose to the
-         clients through the Next-Protocol Negotiation Extension, 
-@@ -1177,7 +1181,7 @@ class TLSConnection(TLSRecordLayer):
-         """
-         for result in self.handshakeServerAsync(verifierDB,
-                 certChain, privateKey, reqCert, sessionCache, settings,
--                checker, reqCAs, 
-+                checker, reqCAs, reqCertTypes,
-                 tacks=tacks, activationFlags=activationFlags, 
-                 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
-                 signedCertTimestamps=signedCertTimestamps,
-@@ -1188,7 +1192,7 @@ class TLSConnection(TLSRecordLayer):
-     def handshakeServerAsync(self, verifierDB=None,
-                              certChain=None, privateKey=None, reqCert=False,
-                              sessionCache=None, settings=None, checker=None,
--                             reqCAs=None, 
-+                             reqCAs=None, reqCertTypes=None,
-                              tacks=None, activationFlags=0,
-                              nextProtos=None, anon=False,
-                              tlsIntolerant=None,
-@@ -1211,7 +1215,7 @@ class TLSConnection(TLSRecordLayer):
-             verifierDB=verifierDB, certChain=certChain,
-             privateKey=privateKey, reqCert=reqCert,
-             sessionCache=sessionCache, settings=settings, 
--            reqCAs=reqCAs, 
-+            reqCAs=reqCAs, reqCertTypes=reqCertTypes,
-             tacks=tacks, activationFlags=activationFlags, 
-             nextProtos=nextProtos, anon=anon,
-             tlsIntolerant=tlsIntolerant,
-@@ -1224,7 +1228,7 @@ class TLSConnection(TLSRecordLayer):
- 
-     def _handshakeServerAsyncHelper(self, verifierDB,
-                              certChain, privateKey, reqCert, sessionCache,
--                             settings, reqCAs, 
-+                             settings, reqCAs, reqCertTypes,
-                              tacks, activationFlags, 
-                              nextProtos, anon,
-                              tlsIntolerant, signedCertTimestamps, fallbackSCSV,
-@@ -1240,6 +1244,8 @@ class TLSConnection(TLSRecordLayer):
-             raise ValueError("Caller passed a privateKey but no certChain")
-         if reqCAs and not reqCert:
-             raise ValueError("Caller passed reqCAs but not reqCert")            
-+        if reqCertTypes and not reqCert:
-+            raise ValueError("Caller passed reqCertTypes but not reqCert")
-         if certChain and not isinstance(certChain, X509CertChain):
-             raise ValueError("Unrecognized certificate type")
-         if activationFlags and not tacks:
-@@ -1328,7 +1334,7 @@ class TLSConnection(TLSRecordLayer):
-                 assert(False)
-             for result in self._serverCertKeyExchange(clientHello, serverHello, 
-                                         certChain, keyExchange,
--                                        reqCert, reqCAs, cipherSuite,
-+                                        reqCert, reqCAs, reqCertTypes, cipherSuite,
-                                         settings, ocspResponse):
-                 if result in (0,1): yield result
-                 else: break
-@@ -1607,7 +1613,7 @@ class TLSConnection(TLSRecordLayer):
- 
-     def _serverCertKeyExchange(self, clientHello, serverHello, 
-                                 serverCertChain, keyExchange,
--                                reqCert, reqCAs, cipherSuite,
-+                                reqCert, reqCAs, reqCertTypes, cipherSuite,
-                                 settings, ocspResponse):
-         #Send ServerHello, Certificate[, ServerKeyExchange]
-         #[, CertificateRequest], ServerHelloDone
-@@ -1623,11 +1629,13 @@ class TLSConnection(TLSRecordLayer):
-         serverKeyExchange = keyExchange.makeServerKeyExchange()
-         if serverKeyExchange is not None:
-             msgs.append(serverKeyExchange)
--        if reqCert and reqCAs:
--            msgs.append(CertificateRequest().create(\
--                [ClientCertificateType.rsa_sign], reqCAs))
--        elif reqCert:
--            msgs.append(CertificateRequest(self.version))
-+        if reqCert:
-+            reqCAs = reqCAs or []
-+            #Apple's Secure Transport library rejects empty certificate_types,
-+            #so default to rsa_sign.
-+            reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
-+            msgs.append(CertificateRequest(self.version).create(reqCertTypes,
-+                                                                reqCAs))
-         msgs.append(ServerHelloDone())
-         for result in self._sendMsgs(msgs):
-             yield result
diff --git a/third_party/tlslite/patches/save_client_hello.patch b/third_party/tlslite/patches/save_client_hello.patch
deleted file mode 100644
index ee445b5c..0000000
--- a/third_party/tlslite/patches/save_client_hello.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 4f3ba1c..cb743fe 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1269,6 +1269,9 @@ class TLSConnection(TLSRecordLayer):
-                 return # Handshake was resumed, we're done 
-             else: break
-         (clientHello, cipherSuite) = result
-+
-+        # Save the ClientHello for external code to query.
-+        self.clientHello = clientHello
-         
-         #If not a resumption...
- 
diff --git a/third_party/tlslite/patches/save_randoms.patch b/third_party/tlslite/patches/save_randoms.patch
deleted file mode 100644
index ceb4697..0000000
--- a/third_party/tlslite/patches/save_randoms.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index e42b362..41aab85 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1570,6 +1570,8 @@ class TLSConnection(TLSRecordLayer):
-                 #Set the session
-                 self.session = session
-                     
-+                self.clientRandom = clientHello.random
-+                self.serverRandom = serverHello.random
-                 yield None # Handshake done!
- 
-         #Calculate the first cipher suite intersection.
diff --git a/third_party/tlslite/patches/signature_algorithms.patch b/third_party/tlslite/patches/signature_algorithms.patch
deleted file mode 100644
index 9e8beb9..0000000
--- a/third_party/tlslite/patches/signature_algorithms.patch
+++ /dev/null
@@ -1,175 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index bac05c2f70cf..3f994e7e6f60 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -52,8 +52,9 @@ class CertificateStatusType:
- class ExtensionType:    # RFC 6066 / 4366
-     server_name = 0     # RFC 6066 / 4366
-     status_request = 5  # RFC 6066 / 4366
--    srp = 12            # RFC 5054  
-+    srp = 12            # RFC 5054
-     cert_type = 9       # RFC 6091
-+    signature_algorithms = 13 # RFC 5246
-     alpn = 16           # RFC 7301
-     signed_cert_timestamps = 18  # RFC 6962
-     extended_master_secret = 23  # RFC 7627
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 90a3cec9f54e..ce4f1a6e15eb 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -142,6 +142,7 @@ class ClientHello(HandshakeMsg):
-         self.status_request = False
-         self.has_supported_versions = False
-         self.ri = False
-+        self.signature_algorithms = []
- 
-     def create(self, version, random, session_id, cipher_suites,
-                certificate_types=None, srpUsername=None,
-@@ -257,6 +258,14 @@ class ClientHello(HandshakeMsg):
-                         # intolerance simulation.
-                         self.has_supported_versions = True
-                         _ = p.getFixBytes(extLength)
-+                    elif extType == ExtensionType.signature_algorithms:
-+                        numBytes = p.get(2)
-+                        if numBytes + 2 != extLength or numBytes % 2 != 0:
-+                            raise SyntaxError()
-+                        for _ in range(numBytes / 2):
-+                            hashAlg = p.get(1)
-+                            sigAlg = p.get(1)
-+                            self.signature_algorithms.append((hashAlg, sigAlg))
-                     else:
-                         _ = p.getFixBytes(extLength)
-                     index2 = p.index
-@@ -605,6 +614,7 @@ class ServerKeyExchange(HandshakeMsg):
-         self.ecdhCurve = 0
-         self.ecdhPublic = bytearray(0)
-         self.signature = bytearray(0)
-+        self.signature_algorithm = None
- 
-     def createSRP(self, srp_N, srp_g, srp_s, srp_B):
-         self.srp_N = srp_N
-@@ -664,18 +674,13 @@ class ServerKeyExchange(HandshakeMsg):
-         w.bytes += self.write_params()
-         if self.cipherSuite in CipherSuite.certAllSuites:
-             if self.version >= (3,3):
--                # TODO: Signature algorithm negotiation not supported.
--                w.add(HashAlgorithm.sha1, 1)
--                w.add(SignatureAlgorithm.rsa, 1)
-+                w.add(self.signature_algorithm[0], 1)
-+                w.add(self.signature_algorithm[1], 1)
-             w.addVarSeq(self.signature, 1, 2)
-         return self.postWrite(w)
- 
--    def hash(self, clientRandom, serverRandom):
--        bytes = clientRandom + serverRandom + self.write_params()
--        if self.version >= (3,3):
--            # TODO: Signature algorithm negotiation not supported.
--            return SHA1(bytes)
--        return MD5(bytes) + SHA1(bytes)
-+    def signingPayload(self, clientRandom, serverRandom):
-+        return clientRandom + serverRandom + self.write_params()
- 
- class ServerHelloDone(HandshakeMsg):
-     def __init__(self):
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index efe2b9fefaa0..6d7c859884a4 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -17,7 +17,7 @@ from .utils.compat import formatExceptionTrace
- from .tlsrecordlayer import TLSRecordLayer
- from .session import Session
- from .constants import *
--from .utils.cryptomath import getRandomBytes
-+from .utils.cryptomath import getRandomBytes, MD5, SHA1, SHA256
- from .errors import *
- from .messages import *
- from .mathtls import *
-@@ -51,6 +51,24 @@ class KeyExchange(object):
-         """
-         raise NotImplementedError()
- 
-+    def sign(self, inpBytes):
-+        algorithm = None
-+        if self.serverHello.server_version >= (3, 3):
-+            # Negotiate a signature algorithm.
-+            peerPrefs = self.clientHello.signature_algorithms
-+            if (HashAlgorithm.sha256, SignatureAlgorithm.rsa) in peerPrefs:
-+                algorithm = (HashAlgorithm.sha256, SignatureAlgorithm.rsa)
-+                inpBytes = RSAKey.addPKCS1SHA256Prefix(SHA256(inpBytes))
-+            elif (HashAlgorithm.sha1, SignatureAlgorithm.rsa) in peerPrefs:
-+                algorithm = (HashAlgorithm.sha1, SignatureAlgorithm.rsa)
-+                inpBytes = RSAKey.addPKCS1SHA1Prefix(SHA1(inpBytes))
-+            else:
-+                raise TLSLocalAlert(AlertDescription.handshake_failure,
-+                                   "no common signature algorithms")
-+        else:
-+            inpBytes = MD5(inpBytes) + SHA1(inpBytes)
-+        return algorithm, self.privateKey.sign(inpBytes)
-+
- class RSAKeyExchange(KeyExchange):
-     def makeServerKeyExchange(self):
-         return None
-@@ -108,12 +126,9 @@ DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
-         version = self.serverHello.server_version
-         serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
-         serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
--        hashBytes = serverKeyExchange.hash(self.clientHello.random,
--                                           self.serverHello.random)
--        if version >= (3,3):
--            # TODO: Signature algorithm negotiation not supported.
--            hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes)
--        serverKeyExchange.signature = self.privateKey.sign(hashBytes)
-+        serverKeyExchange.signature_algorithm, serverKeyExchange.signature = \
-+            self.sign(serverKeyExchange.signingPayload(self.clientHello.random,
-+                                                       self.serverHello.random))
-         return serverKeyExchange
- 
-     def processClientKeyExchange(self, clientKeyExchange):
-@@ -135,12 +150,9 @@ class ECDHE_RSAKeyExchange(KeyExchange):
-         version = self.serverHello.server_version
-         serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
-         serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public))
--        hashBytes = serverKeyExchange.hash(self.clientHello.random,
--                                           self.serverHello.random)
--        if version >= (3,3):
--            # TODO: Signature algorithm negotiation not supported.
--            hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes)
--        serverKeyExchange.signature = self.privateKey.sign(hashBytes)
-+        serverKeyExchange.signature_algorithm, serverKeyExchange.signature = \
-+            self.sign(serverKeyExchange.signingPayload(self.clientHello.random,
-+                                                       self.serverHello.random))
-         return serverKeyExchange
- 
-     def processClientKeyExchange(self, clientKeyExchange):
-diff --git a/third_party/tlslite/tlslite/utils/cryptomath.py b/third_party/tlslite/tlslite/utils/cryptomath.py
-index 61fd1432d566..f7142c06ba23 100644
---- a/third_party/tlslite/tlslite/utils/cryptomath.py
-+++ b/third_party/tlslite/tlslite/utils/cryptomath.py
-@@ -73,6 +73,9 @@ def MD5(b):
- def SHA1(b):
-     return bytearray(hashlib.sha1(compat26Str(b)).digest())
- 
-+def SHA256(b):
-+    return bytearray(hashlib.sha256(compat26Str(b)).digest())
-+
- def HMAC_MD5(k, b):
-     k = compatHMAC(k)
-     b = compatHMAC(b)
-diff --git a/third_party/tlslite/tlslite/utils/rsakey.py b/third_party/tlslite/tlslite/utils/rsakey.py
-index fb022cc6445d..7e3f97881a10 100644
---- a/third_party/tlslite/tlslite/utils/rsakey.py
-+++ b/third_party/tlslite/tlslite/utils/rsakey.py
-@@ -240,6 +240,13 @@ class RSAKey(object):
-         prefixedBytes = prefixBytes + bytes
-         return prefixedBytes
- 
-+    @staticmethod
-+    def addPKCS1SHA256Prefix(bytes):
-+        prefixBytes = bytearray([
-+            0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
-+            0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20])
-+        return prefixBytes + bytes
-+
-     def _addPKCS1Padding(self, bytes, blockType):
-         padLength = (numBytes(self.n) - (len(bytes)+3))
-         if blockType == 1: #Signature padding
diff --git a/third_party/tlslite/patches/signed_certificate_timestamps.patch b/third_party/tlslite/patches/signed_certificate_timestamps.patch
deleted file mode 100644
index 91bc06c..0000000
--- a/third_party/tlslite/patches/signed_certificate_timestamps.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 6429c66..8720de6 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -45,6 +45,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     server_name = 0     # RFC 6066 / 4366
-     srp = 12            # RFC 5054  
-     cert_type = 9       # RFC 6091
-+    signed_cert_timestamps = 18  # RFC 6962
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 4fa9d96..876b033 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -114,6 +114,7 @@ class ClientHello(HandshakeMsg):
-         self.supports_npn = False
-         self.server_name = bytearray(0)
-         self.channel_id = False
-+        self.support_signed_cert_timestamps = False
- 
-     def create(self, version, random, session_id, cipher_suites,
-                certificate_types=None, srpUsername=None,
-@@ -183,6 +184,10 @@ class ClientHello(HandshakeMsg):
-                                 break
-                     elif extType == ExtensionType.channel_id:
-                         self.channel_id = True
-+                    elif extType == ExtensionType.signed_cert_timestamps:
-+                        if extLength:
-+                            raise SyntaxError()
-+                        self.support_signed_cert_timestamps = True
-                     else:
-                         _ = p.getFixBytes(extLength)
-                     index2 = p.index
-@@ -248,6 +253,7 @@ class ServerHello(HandshakeMsg):
-         self.next_protos_advertised = None
-         self.next_protos = None
-         self.channel_id = False
-+        self.signed_cert_timestamps = None
- 
-     def create(self, version, random, session_id, cipher_suite,
-                certificate_type, tackExt, next_protos_advertised):
-@@ -337,6 +343,9 @@ class ServerHello(HandshakeMsg):
-         if self.channel_id:
-             w2.add(ExtensionType.channel_id, 2)
-             w2.add(0, 2)
-+        if self.signed_cert_timestamps:
-+            w2.add(ExtensionType.signed_cert_timestamps, 2)
-+            w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2)
-         if len(w2.bytes):
-             w.add(len(w2.bytes), 2)
-             w.bytes += w2.bytes        
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index b0400f8..4dedc5f 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -969,7 +969,7 @@ class TLSConnection(TLSRecordLayer):
-                         reqCAs = None, 
-                         tacks=None, activationFlags=0,
-                         nextProtos=None, anon=False,
--                        tlsIntolerant=None):
-+                        tlsIntolerant=None, signedCertTimestamps=None):
-         """Perform a handshake in the role of server.
- 
-         This function performs an SSL or TLS handshake.  Depending on
-@@ -1043,6 +1043,11 @@ class TLSConnection(TLSRecordLayer):
-         simulate TLS version intolerance by returning a fatal handshake_failure
-         alert to all TLS versions tlsIntolerant or higher.
- 
-+        @type signedCertTimestamps: str
-+        @param signedCertTimestamps: A SignedCertificateTimestampList (as a
-+        binary 8-bit string) that will be sent as a TLS extension whenever
-+        the client announces support for the extension.
-+
-         @raise socket.error: If a socket error occurs.
-         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-         without a preceding alert.
-@@ -1054,7 +1059,8 @@ class TLSConnection(TLSRecordLayer):
-                 certChain, privateKey, reqCert, sessionCache, settings,
-                 checker, reqCAs, 
-                 tacks=tacks, activationFlags=activationFlags, 
--                nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant):
-+                nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
-+                signedCertTimestamps=signedCertTimestamps):
-             pass
- 
- 
-@@ -1064,7 +1070,8 @@ class TLSConnection(TLSRecordLayer):
-                              reqCAs=None, 
-                              tacks=None, activationFlags=0,
-                              nextProtos=None, anon=False,
--                             tlsIntolerant=None
-+                             tlsIntolerant=None,
-+                             signedCertTimestamps=None
-                              ):
-         """Start a server handshake operation on the TLS connection.
- 
-@@ -1084,7 +1091,8 @@ class TLSConnection(TLSRecordLayer):
-             reqCAs=reqCAs, 
-             tacks=tacks, activationFlags=activationFlags, 
-             nextProtos=nextProtos, anon=anon,
--            tlsIntolerant=tlsIntolerant)
-+            tlsIntolerant=tlsIntolerant,
-+            signedCertTimestamps=signedCertTimestamps)
-         for result in self._handshakeWrapperAsync(handshaker, checker):
-             yield result
- 
-@@ -1094,7 +1102,7 @@ class TLSConnection(TLSRecordLayer):
-                              settings, reqCAs, 
-                              tacks, activationFlags, 
-                              nextProtos, anon,
--                             tlsIntolerant):
-+                             tlsIntolerant, signedCertTimestamps):
- 
-         self._handshakeStart(client=False)
- 
-@@ -1115,6 +1123,9 @@ class TLSConnection(TLSRecordLayer):
-                 raise ValueError("tackpy is not loaded")
-             if not settings or not settings.useExperimentalTackExtension:
-                 raise ValueError("useExperimentalTackExtension not enabled")
-+        if signedCertTimestamps and not certChain:
-+            raise ValueError("Caller passed signedCertTimestamps but no "
-+                             "certChain")
- 
-         if not settings:
-             settings = HandshakeSettings()
-@@ -1159,6 +1170,8 @@ class TLSConnection(TLSRecordLayer):
-                             cipherSuite, CertificateType.x509, tackExt,
-                             nextProtos)
-         serverHello.channel_id = clientHello.channel_id
-+        if clientHello.support_signed_cert_timestamps:
-+            serverHello.signed_cert_timestamps = signedCertTimestamps
- 
-         # Perform the SRP key exchange
-         clientCertChain = None
diff --git a/third_party/tlslite/patches/simulate_tls13_downgrade.patch b/third_party/tlslite/patches/simulate_tls13_downgrade.patch
deleted file mode 100644
index 775e079..0000000
--- a/third_party/tlslite/patches/simulate_tls13_downgrade.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index 69fc6f455e10..a647af53c13e 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -125,7 +125,15 @@ class HandshakeSettings(object):
-     corresponding to the TokenBindingKeyParameters enum in the Token Binding
-     Negotiation spec (draft-ietf-tokbind-negotiation-00). Values are in server's
-     preference order, with most preferred params first.
--    
-+
-+    @type simulateTLS13Downgrade: bool
-+    @ivar simulateTLS13Downgrade: If true, the server will simulate a TLS 1.3
-+    to TLS 1.2 downgrade in the ServerHello random.
-+
-+    @type simulateTLS12Downgrade: bool
-+    @ivar simulateTLS12Downgrade: If true, the server will simulate a TLS 1.2
-+    to TLS 1.1 downgrade in the ServerHello random.
-+
-     Note that TACK support is not standardized by IETF and uses a temporary
-     TLS Extension number, so should NOT be used in production software.
- 
-@@ -153,6 +161,8 @@ class HandshakeSettings(object):
-         self.enableExtendedMasterSecret = True
-         self.supportedTokenBindingParams = []
-         self.alpnProtos = None
-+        self.simulateTLS13Downgrade = False
-+        self.simulateTLS12Downgrade = False
- 
-     # Validates the min/max fields, and certificateTypes
-     # Filters out unsupported cipherNames and cipherImplementations
-@@ -174,6 +184,8 @@ class HandshakeSettings(object):
-         other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
-         other.supportedTokenBindingParams = self.supportedTokenBindingParams
-         other.alpnProtos = self.alpnProtos;
-+        other.simulateTLS13Downgrade = self.simulateTLS13Downgrade
-+        other.simulateTLS12Downgrade = self.simulateTLS12Downgrade
- 
-         if not cipherfactory.tripleDESPresent:
-             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 2309d4fa8f3a..cb7160f25cc9 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1352,8 +1352,16 @@ class TLSConnection(TLSRecordLayer):
-             tackExt = TackExtension.create(tacks, activationFlags)
-         else:
-             tackExt = None
-+        serverRandom = getRandomBytes(32)
-+        # See https://tools.ietf.org/html/rfc8446#section-4.1.3
-+        if settings.simulateTLS13Downgrade:
-+            serverRandom = serverRandom[:24] + \
-+                bytearray("\x44\x4f\x57\x4e\x47\x52\x44\x01")
-+        elif settings.simulateTLS12Downgrade:
-+            serverRandom = serverRandom[:24] + \
-+                bytearray("\x44\x4f\x57\x4e\x47\x52\x44\x00")
-         serverHello = ServerHello()
--        serverHello.create(self.version, getRandomBytes(32), sessionID, \
-+        serverHello.create(self.version, serverRandom, sessionID, \
-                             cipherSuite, CertificateType.x509, tackExt,
-                             alpn_proto_selected,
-                             nextProtos)
diff --git a/third_party/tlslite/patches/ssl3_padding.patch b/third_party/tlslite/patches/ssl3_padding.patch
deleted file mode 100644
index 6f720ac..0000000
--- a/third_party/tlslite/patches/ssl3_padding.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
-index f18fcf5..01ff3e9 100644
---- a/third_party/tlslite/tlslite/tlsrecordlayer.py
-+++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
-@@ -592,9 +592,9 @@ class TLSRecordLayer(object):
-                     b = self.fixedIVBlock + b
- 
-                 #Add padding: b = b+ (macBytes + paddingBytes)
--                currentLength = len(b) + len(macBytes) + 1
-+                currentLength = len(b) + len(macBytes)
-                 blockLength = self._writeState.encContext.block_size
--                paddingLength = blockLength-(currentLength % blockLength)
-+                paddingLength = blockLength - 1 - (currentLength % blockLength)
- 
-                 paddingBytes = bytearray([paddingLength] * (paddingLength+1))
-                 if self.fault == Fault.badPadding:
diff --git a/third_party/tlslite/patches/status_request.patch b/third_party/tlslite/patches/status_request.patch
deleted file mode 100644
index b6de396..0000000
--- a/third_party/tlslite/patches/status_request.patch
+++ /dev/null
@@ -1,218 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 69e6067..1a1ace9 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -31,6 +31,7 @@ class HandshakeType:
-     certificate_verify = 15
-     client_key_exchange = 16
-     finished = 20
-+    certificate_status = 22
-     next_protocol = 67
-     encrypted_extensions = 203
- 
-@@ -41,8 +42,12 @@ class ContentType:
-     application_data = 23
-     all = (20,21,22,23)
- 
-+class CertificateStatusType:
-+    ocsp = 1
-+
- class ExtensionType:    # RFC 6066 / 4366
-     server_name = 0     # RFC 6066 / 4366
-+    status_request = 5  # RFC 6066 / 4366
-     srp = 12            # RFC 5054  
-     cert_type = 9       # RFC 6091
-     signed_cert_timestamps = 18  # RFC 6962
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 876b033..9a8e5f6 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -115,6 +115,7 @@ class ClientHello(HandshakeMsg):
-         self.server_name = bytearray(0)
-         self.channel_id = False
-         self.support_signed_cert_timestamps = False
-+        self.status_request = False
- 
-     def create(self, version, random, session_id, cipher_suites,
-                certificate_types=None, srpUsername=None,
-@@ -188,6 +189,19 @@ class ClientHello(HandshakeMsg):
-                         if extLength:
-                             raise SyntaxError()
-                         self.support_signed_cert_timestamps = True
-+                    elif extType == ExtensionType.status_request:
-+                        # Extension contents are currently ignored.
-+                        # According to RFC 6066, this is not strictly forbidden
-+                        # (although it is suboptimal):
-+                        # Servers that receive a client hello containing the
-+                        # "status_request" extension MAY return a suitable
-+                        # certificate status response to the client along with
-+                        # their certificate.  If OCSP is requested, they
-+                        # SHOULD use the information contained in the extension
-+                        # when selecting an OCSP responder and SHOULD include
-+                        # request_extensions in the OCSP request.
-+                        p.getFixBytes(extLength)
-+                        self.status_request = True
-                     else:
-                         _ = p.getFixBytes(extLength)
-                     index2 = p.index
-@@ -254,6 +268,7 @@ class ServerHello(HandshakeMsg):
-         self.next_protos = None
-         self.channel_id = False
-         self.signed_cert_timestamps = None
-+        self.status_request = False
- 
-     def create(self, version, random, session_id, cipher_suite,
-                certificate_type, tackExt, next_protos_advertised):
-@@ -346,6 +361,9 @@ class ServerHello(HandshakeMsg):
-         if self.signed_cert_timestamps:
-             w2.add(ExtensionType.signed_cert_timestamps, 2)
-             w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2)
-+        if self.status_request:
-+            w2.add(ExtensionType.status_request, 2)
-+            w2.add(0, 2)
-         if len(w2.bytes):
-             w.add(len(w2.bytes), 2)
-             w.bytes += w2.bytes        
-@@ -403,6 +421,37 @@ class Certificate(HandshakeMsg):
-             raise AssertionError()
-         return self.postWrite(w)
- 
-+class CertificateStatus(HandshakeMsg):
-+    def __init__(self):
-+        HandshakeMsg.__init__(self, HandshakeType.certificate_status)
-+
-+    def create(self, ocsp_response):
-+        self.ocsp_response = ocsp_response
-+        return self
-+
-+    # Defined for the sake of completeness, even though we currently only
-+    # support sending the status message (server-side), not requesting
-+    # or receiving it (client-side).
-+    def parse(self, p):
-+        p.startLengthCheck(3)
-+        status_type = p.get(1)
-+        # Only one type is specified, so hardwire it.
-+        if status_type != CertificateStatusType.ocsp:
-+            raise SyntaxError()
-+        ocsp_response = p.getVarBytes(3)
-+        if not ocsp_response:
-+            # Can't be empty
-+            raise SyntaxError()
-+        self.ocsp_response = ocsp_response
-+        p.stopLengthCheck()
-+        return self
-+
-+    def write(self):
-+        w = Writer()
-+        w.add(CertificateStatusType.ocsp, 1)
-+        w.addVarSeq(bytearray(self.ocsp_response), 1, 3)
-+        return self.postWrite(w)
-+
- class CertificateRequest(HandshakeMsg):
-     def __init__(self, version):
-         HandshakeMsg.__init__(self, HandshakeType.certificate_request)
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 0563fb5f..5d508ed 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -970,7 +970,7 @@ class TLSConnection(TLSRecordLayer):
-                         tacks=None, activationFlags=0,
-                         nextProtos=None, anon=False,
-                         tlsIntolerant=None, signedCertTimestamps=None,
--                        fallbackSCSV=False):
-+                        fallbackSCSV=False, ocspResponse=None):
-         """Perform a handshake in the role of server.
- 
-         This function performs an SSL or TLS handshake.  Depending on
-@@ -1054,6 +1054,16 @@ class TLSConnection(TLSRecordLayer):
-         TLS_FALLBACK_SCSV and thus reject connections using less than the
-         server's maximum TLS version that include this cipher suite.
- 
-+        @type ocspResponse: str
-+        @param ocspResponse: An OCSP response (as a binary 8-bit string) that
-+        will be sent stapled in the handshake whenever the client announces
-+        support for the status_request extension.
-+        Note that the response is sent independent of the ClientHello
-+        status_request extension contents, and is thus only meant for testing
-+        environments. Real OCSP stapling is more complicated as it requires
-+        choosing a suitable response based on the ClientHello status_request
-+        extension contents.
-+
-         @raise socket.error: If a socket error occurs.
-         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-         without a preceding alert.
-@@ -1067,7 +1077,7 @@ class TLSConnection(TLSRecordLayer):
-                 tacks=tacks, activationFlags=activationFlags, 
-                 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
-                 signedCertTimestamps=signedCertTimestamps,
--                fallbackSCSV=fallbackSCSV):
-+                fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
-             pass
- 
- 
-@@ -1079,7 +1089,8 @@ class TLSConnection(TLSRecordLayer):
-                              nextProtos=None, anon=False,
-                              tlsIntolerant=None,
-                              signedCertTimestamps=None,
--                             fallbackSCSV=False
-+                             fallbackSCSV=False,
-+                             ocspResponse=None
-                              ):
-         """Start a server handshake operation on the TLS connection.
- 
-@@ -1101,7 +1112,8 @@ class TLSConnection(TLSRecordLayer):
-             nextProtos=nextProtos, anon=anon,
-             tlsIntolerant=tlsIntolerant,
-             signedCertTimestamps=signedCertTimestamps,
--            fallbackSCSV=fallbackSCSV)
-+            fallbackSCSV=fallbackSCSV,
-+            ocspResponse=ocspResponse)
-         for result in self._handshakeWrapperAsync(handshaker, checker):
-             yield result
- 
-@@ -1111,7 +1123,8 @@ class TLSConnection(TLSRecordLayer):
-                              settings, reqCAs, 
-                              tacks, activationFlags, 
-                              nextProtos, anon,
--                             tlsIntolerant, signedCertTimestamps, fallbackSCSV):
-+                             tlsIntolerant, signedCertTimestamps, fallbackSCSV,
-+                             ocspResponse):
- 
-         self._handshakeStart(client=False)
- 
-@@ -1181,6 +1194,8 @@ class TLSConnection(TLSRecordLayer):
-         serverHello.channel_id = clientHello.channel_id
-         if clientHello.support_signed_cert_timestamps:
-             serverHello.signed_cert_timestamps = signedCertTimestamps
-+        if clientHello.status_request:
-+            serverHello.status_request = ocspResponse
- 
-         # Perform the SRP key exchange
-         clientCertChain = None
-@@ -1197,7 +1212,7 @@ class TLSConnection(TLSRecordLayer):
-             for result in self._serverCertKeyExchange(clientHello, serverHello, 
-                                         certChain, privateKey,
-                                         reqCert, reqCAs, cipherSuite,
--                                        settings):
-+                                        settings, ocspResponse):
-                 if result in (0,1): yield result
-                 else: break
-             (premasterSecret, clientCertChain) = result
-@@ -1475,7 +1490,7 @@ class TLSConnection(TLSRecordLayer):
-     def _serverCertKeyExchange(self, clientHello, serverHello, 
-                                 serverCertChain, privateKey,
-                                 reqCert, reqCAs, cipherSuite,
--                                settings):
-+                                settings, ocspResponse):
-         #Send ServerHello, Certificate[, CertificateRequest],
-         #ServerHelloDone
-         msgs = []
-@@ -1485,6 +1500,8 @@ class TLSConnection(TLSRecordLayer):
- 
-         msgs.append(serverHello)
-         msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
-+        if serverHello.status_request:
-+            msgs.append(CertificateStatus().create(ocspResponse))
-         if reqCert and reqCAs:
-             msgs.append(CertificateRequest().create(\
-                 [ClientCertificateType.rsa_sign], reqCAs))
diff --git a/third_party/tlslite/patches/thread_safe_python_rsa_key.patch b/third_party/tlslite/patches/thread_safe_python_rsa_key.patch
deleted file mode 100644
index fe68d88..0000000
--- a/third_party/tlslite/patches/thread_safe_python_rsa_key.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/utils/python_rsakey.py b/third_party/tlslite/tlslite/utils/python_rsakey.py
-index 1281f1dc899c..a62fc68b4701 100644
---- a/third_party/tlslite/tlslite/utils/python_rsakey.py
-+++ b/third_party/tlslite/tlslite/utils/python_rsakey.py
-@@ -2,7 +2,7 @@
- # See the LICENSE file for legal information regarding use of this file.
- 
- """Pure-Python RSA implementation."""
--
-+import threading
- from .cryptomath import *
- from .asn1parser import ASN1Parser
- from .rsakey import *
-@@ -22,33 +22,36 @@ class Python_RSAKey(RSAKey):
-         self.qInv = qInv
-         self.blinder = 0
-         self.unblinder = 0
-+        self._lock = threading.Lock()
- 
-     def hasPrivateKey(self):
-         return self.d != 0
- 
--    def _rawPrivateKeyOp(self, m):
--        #Create blinding values, on the first pass:
--        if not self.blinder:
--            self.unblinder = getRandomNumber(2, self.n)
--            self.blinder = powMod(invMod(self.unblinder, self.n), self.e,
--                                  self.n)
--
--        #Blind the input
--        m = (m * self.blinder) % self.n
-+    def _rawPrivateKeyOp(self, message):
-+        with self._lock:
-+            # Create blinding values, on the first pass:
-+            if not self.blinder:
-+                self.unblinder = getRandomNumber(2, self.n)
-+                self.blinder = powMod(invMod(self.unblinder, self.n), self.e,
-+                                      self.n)
-+            unblinder = self.unblinder
-+            blinder = self.blinder
- 
--        #Perform the RSA operation
--        c = self._rawPrivateKeyOpHelper(m)
-+            # Update blinding values
-+            self.blinder = (self.blinder * self.blinder) % self.n
-+            self.unblinder = (self.unblinder * self.unblinder) % self.n
- 
--        #Unblind the output
--        c = (c * self.unblinder) % self.n
-+        # Blind the input
-+        message = (message * blinder) % self.n
- 
--        #Update blinding values
--        self.blinder = (self.blinder * self.blinder) % self.n
--        self.unblinder = (self.unblinder * self.unblinder) % self.n
-+        # Perform the RSA operation
-+        cipher = self._rawPrivateKeyOpHelper(message)
- 
--        #Return the output
--        return c
-+        # Unblind the output
-+        cipher = (cipher * unblinder) % self.n
- 
-+        # Return the output
-+        return cipher
- 
-     def _rawPrivateKeyOpHelper(self, m):
-         #Non-CRT version
diff --git a/third_party/tlslite/patches/tls13_intolerance.patch b/third_party/tlslite/patches/tls13_intolerance.patch
deleted file mode 100644
index ef50fed..0000000
--- a/third_party/tlslite/patches/tls13_intolerance.patch
+++ /dev/null
@@ -1,66 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index 82e8c075fe2a..8fb75d0948e4 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -58,6 +58,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     signed_cert_timestamps = 18  # RFC 6962
-     extended_master_secret = 23  # RFC 7627
-     token_binding = 24           # draft-ietf-tokbind-negotiation
-+    supported_versions = 43      # RFC 8446
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index ac7e563021d9..b29db939c2a8 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -140,6 +140,7 @@ class ClientHello(HandshakeMsg):
-         self.tb_client_params = []
-         self.support_signed_cert_timestamps = False
-         self.status_request = False
-+        self.has_supported_versions = False
-         self.ri = False
- 
-     def create(self, version, random, session_id, cipher_suites,
-@@ -251,6 +252,11 @@ class ClientHello(HandshakeMsg):
-                         if extLength != 1 or p.getFixBytes(extLength)[0] != 0:
-                             raise SyntaxError()
-                         self.ri = True
-+                    elif extType == ExtensionType.supported_versions:
-+                        # Ignore the extension, but make a note of it for
-+                        # intolerance simulation.
-+                        self.has_supported_versions = True
-+                        _ = p.getFixBytes(extLength)
-                     else:
-                         _ = p.getFixBytes(extLength)
-                     index2 = p.index
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 8ba1c6e636ab..2309d4fa8f3a 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1457,6 +1457,15 @@ class TLSConnection(TLSRecordLayer):
-         self._handshakeDone(resumed=False)
- 
- 
-+    def _isIntolerant(self, settings, clientHello):
-+        if settings.tlsIntolerant is None:
-+            return False
-+        clientVersion = clientHello.client_version
-+        if clientHello.has_supported_versions:
-+            clientVersion = (3, 4)
-+        return clientVersion >= settings.tlsIntolerant
-+
-+
-     def _serverGetClientHello(self, settings, certChain, verifierDB,
-                                 sessionCache, anon, fallbackSCSV):
-         #Tentatively set version to most-desirable version, so if an error
-@@ -1480,8 +1489,7 @@ class TLSConnection(TLSRecordLayer):
-                 yield result
- 
-         #If simulating TLS intolerance, reject certain TLS versions.
--        elif (settings.tlsIntolerant is not None and
--              clientHello.client_version >= settings.tlsIntolerant):
-+        elif self._isIntolerant(settings, clientHello):
-             if settings.tlsIntoleranceType == "alert":
-                 for result in self._sendError(\
-                     AlertDescription.handshake_failure):
diff --git a/third_party/tlslite/patches/tls_intolerant.patch b/third_party/tlslite/patches/tls_intolerant.patch
deleted file mode 100644
index f9c82676..0000000
--- a/third_party/tlslite/patches/tls_intolerant.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index e7c6834..0e78753 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -968,7 +968,8 @@ class TLSConnection(TLSRecordLayer):
-                         sessionCache=None, settings=None, checker=None,
-                         reqCAs = None, 
-                         tacks=None, activationFlags=0,
--                        nextProtos=None, anon=False):
-+                        nextProtos=None, anon=False,
-+                        tlsIntolerant=None):
-         """Perform a handshake in the role of server.
- 
-         This function performs an SSL or TLS handshake.  Depending on
-@@ -1037,6 +1038,11 @@ class TLSConnection(TLSRecordLayer):
-         clients through the Next-Protocol Negotiation Extension, 
-         if they support it.
- 
-+        @type tlsIntolerant: (int, int) or None
-+        @param tlsIntolerant: If tlsIntolerant is not None, the server will
-+        simulate TLS version intolerance by returning a fatal handshake_failure
-+        alert to all TLS versions tlsIntolerant or higher.
-+
-         @raise socket.error: If a socket error occurs.
-         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-         without a preceding alert.
-@@ -1048,7 +1054,7 @@ class TLSConnection(TLSRecordLayer):
-                 certChain, privateKey, reqCert, sessionCache, settings,
-                 checker, reqCAs, 
-                 tacks=tacks, activationFlags=activationFlags, 
--                nextProtos=nextProtos, anon=anon):
-+                nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant):
-             pass
- 
- 
-@@ -1057,7 +1063,8 @@ class TLSConnection(TLSRecordLayer):
-                              sessionCache=None, settings=None, checker=None,
-                              reqCAs=None, 
-                              tacks=None, activationFlags=0,
--                             nextProtos=None, anon=False
-+                             nextProtos=None, anon=False,
-+                             tlsIntolerant=None
-                              ):
-         """Start a server handshake operation on the TLS connection.
- 
-@@ -1076,7 +1083,8 @@ class TLSConnection(TLSRecordLayer):
-             sessionCache=sessionCache, settings=settings, 
-             reqCAs=reqCAs, 
-             tacks=tacks, activationFlags=activationFlags, 
--            nextProtos=nextProtos, anon=anon)
-+            nextProtos=nextProtos, anon=anon,
-+            tlsIntolerant=tlsIntolerant)
-         for result in self._handshakeWrapperAsync(handshaker, checker):
-             yield result
- 
-@@ -1085,7 +1093,8 @@ class TLSConnection(TLSRecordLayer):
-                              certChain, privateKey, reqCert, sessionCache,
-                              settings, reqCAs, 
-                              tacks, activationFlags, 
--                             nextProtos, anon):
-+                             nextProtos, anon,
-+                             tlsIntolerant):
- 
-         self._handshakeStart(client=False)
- 
-@@ -1117,7 +1126,7 @@ class TLSConnection(TLSRecordLayer):
-         # Handle ClientHello and resumption
-         for result in self._serverGetClientHello(settings, certChain,\
-                                             verifierDB, sessionCache,
--                                            anon):
-+                                            anon, tlsIntolerant):
-             if result in (0,1): yield result
-             elif result == None:
-                 self._handshakeDone(resumed=True)                
-@@ -1214,7 +1223,7 @@ class TLSConnection(TLSRecordLayer):
- 
- 
-     def _serverGetClientHello(self, settings, certChain, verifierDB,
--                                sessionCache, anon):
-+                                sessionCache, anon, tlsIntolerant):
-         #Initialize acceptable cipher suites
-         cipherSuites = []
-         if verifierDB:
-@@ -1249,6 +1258,13 @@ class TLSConnection(TLSRecordLayer):
-                   "Too old version: %s" % str(clientHello.client_version)):
-                 yield result
- 
-+        #If simulating TLS intolerance, reject certain TLS versions.
-+        elif (tlsIntolerant is not None and
-+            clientHello.client_version >= tlsIntolerant):
-+            for result in self._sendError(\
-+                    AlertDescription.handshake_failure):
-+                yield result
-+
-         #If client's version is too high, propose my highest version
-         elif clientHello.client_version > settings.maxVersion:
-             self.version = settings.maxVersion
diff --git a/third_party/tlslite/patches/token_binding_negotiation.patch b/third_party/tlslite/patches/token_binding_negotiation.patch
deleted file mode 100644
index ed1775d..0000000
--- a/third_party/tlslite/patches/token_binding_negotiation.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
-index f9c8676..84bb703 100644
---- a/third_party/tlslite/tlslite/constants.py
-+++ b/third_party/tlslite/tlslite/constants.py
-@@ -59,6 +59,7 @@ class ExtensionType:    # RFC 6066 / 4366
-     tack = 0xF300
-     supports_npn = 13172
-     channel_id = 30032
-+    token_binding = 30033
- 
- class HashAlgorithm:
-     none = 0
-diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
-index a7b6ab9..8f25f62 100644
---- a/third_party/tlslite/tlslite/handshakesettings.py
-+++ b/third_party/tlslite/tlslite/handshakesettings.py
-@@ -115,6 +115,13 @@ class HandshakeSettings(object):
-     @type enableExtendedMasterSecret: bool
-     @ivar enableExtendedMasterSecret: If true, the server supports the extended
-     master secret TLS extension and will negotiated it with supporting clients.
-+
-+    @type supportedTokenBindingParams: list
-+    @ivar supportedTokenBindingParams: A list of token binding parameters that
-+    the server supports when negotiating token binding. List values are integers
-+    corresponding to the TokenBindingKeyParameters enum in the Token Binding
-+    Negotiation spec (draft-ietf-tokbind-negotiation-00). Values are in server's
-+    preference order, with most preferred params first.
-     
-     Note that TACK support is not standardized by IETF and uses a temporary
-     TLS Extension number, so should NOT be used in production software.
-@@ -134,6 +141,7 @@ class HandshakeSettings(object):
-         self.useExperimentalTackExtension = False
-         self.alertAfterHandshake = False
-         self.enableExtendedMasterSecret = True
-+        self.supportedTokenBindingParams = []
- 
-     # Validates the min/max fields, and certificateTypes
-     # Filters out unsupported cipherNames and cipherImplementations
-@@ -152,6 +160,7 @@ class HandshakeSettings(object):
-         other.tlsIntoleranceType = self.tlsIntoleranceType
-         other.alertAfterHandshake = self.alertAfterHandshake
-         other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
-+        other.supportedTokenBindingParams = self.supportedTokenBindingParams
- 
-         if not cipherfactory.tripleDESPresent:
-             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 9b553ce..ab2be57 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -115,6 +115,7 @@ class ClientHello(HandshakeMsg):
-         self.server_name = bytearray(0)
-         self.channel_id = False
-         self.extended_master_secret = False
-+        self.tb_client_params = []
-         self.support_signed_cert_timestamps = False
-         self.status_request = False
- 
-@@ -188,6 +189,15 @@ class ClientHello(HandshakeMsg):
-                         self.channel_id = True
-                     elif extType == ExtensionType.extended_master_secret:
-                         self.extended_master_secret = True
-+                    elif extType == ExtensionType.token_binding:
-+                        tokenBindingBytes = p.getFixBytes(extLength)
-+                        p2 = Parser(tokenBindingBytes)
-+                        ver_minor = p2.get(1)
-+                        ver_major = p2.get(1)
-+                        if (ver_major, ver_minor) >= (0, 6):
-+                            p2.startLengthCheck(1)
-+                            while not p2.atLengthCheck():
-+                                self.tb_client_params.append(p2.get(1))
-                     elif extType == ExtensionType.signed_cert_timestamps:
-                         if extLength:
-                             raise SyntaxError()
-@@ -271,6 +281,7 @@ class ServerHello(HandshakeMsg):
-         self.next_protos = None
-         self.channel_id = False
-         self.extended_master_secret = False
-+        self.tb_params = None
-         self.signed_cert_timestamps = None
-         self.status_request = False
- 
-@@ -365,6 +376,17 @@ class ServerHello(HandshakeMsg):
-         if self.extended_master_secret:
-             w2.add(ExtensionType.extended_master_secret, 2)
-             w2.add(0, 2)
-+        if self.tb_params:
-+            w2.add(ExtensionType.token_binding, 2)
-+            # length of extension
-+            w2.add(4, 2)
-+            # version
-+            w2.add(0, 1)
-+            w2.add(6, 1)
-+            # length of params (defined as variable length <1..2^8-1>, but in
-+            # this context the server can only send a single value.
-+            w2.add(1, 1)
-+            w2.add(self.tb_params, 1)
-         if self.signed_cert_timestamps:
-             w2.add(ExtensionType.signed_cert_timestamps, 2)
-             w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2)
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 04161513..06404fe 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1330,6 +1330,10 @@ class TLSConnection(TLSRecordLayer):
-         serverHello.extended_master_secret = \
-             clientHello.extended_master_secret and \
-             settings.enableExtendedMasterSecret
-+        for param in clientHello.tb_client_params:
-+            if param in settings.supportedTokenBindingParams:
-+                serverHello.tb_params = param
-+                break
-         if clientHello.support_signed_cert_timestamps:
-             serverHello.signed_cert_timestamps = signedCertTimestamps
-         if clientHello.status_request:
diff --git a/third_party/tlslite/patches/token_binding_resumption.patch b/third_party/tlslite/patches/token_binding_resumption.patch
deleted file mode 100644
index 5d856b2a..0000000
--- a/third_party/tlslite/patches/token_binding_resumption.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
-index 6a53282..6e26fdd 100644
---- a/third_party/tlslite/tlslite/tlsconnection.py
-+++ b/third_party/tlslite/tlslite/tlsconnection.py
-@@ -1536,6 +1536,10 @@ class TLSConnection(TLSRecordLayer):
-                 serverHello.extended_master_secret = \
-                     clientHello.extended_master_secret and \
-                     settings.enableExtendedMasterSecret
-+                for param in clientHello.tb_client_params:
-+                    if param in settings.supportedTokenBindingParams:
-+                          serverHello.tb_params = param
-+                          break
-                 for result in self._sendMsg(serverHello):
-                     yield result
- 
diff --git a/third_party/tlslite/patches/token_binding_version.patch b/third_party/tlslite/patches/token_binding_version.patch
deleted file mode 100644
index 226672a1..0000000
--- a/third_party/tlslite/patches/token_binding_version.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
-index 1ce9320..ac7e563 100644
---- a/third_party/tlslite/tlslite/messages.py
-+++ b/third_party/tlslite/tlslite/messages.py
-@@ -223,7 +224,7 @@ class ClientHello(HandshakeMsg):
-                         p2 = Parser(tokenBindingBytes)
-                         ver_minor = p2.get(1)
-                         ver_major = p2.get(1)
--                        if (ver_major, ver_minor) >= (0, 6):
-+                        if (ver_major, ver_minor) >= (0, 13):
-                             p2.startLengthCheck(1)
-                             while not p2.atLengthCheck():
-                                 self.tb_client_params.append(p2.get(1))
-@@ -421,7 +431,7 @@ class ServerHello(HandshakeMsg):
-             w2.add(4, 2)
-             # version
-             w2.add(0, 1)
--            w2.add(6, 1)
-+            w2.add(13, 1)
-             # length of params (defined as variable length <1..2^8-1>, but in
-             # this context the server can only send a single value.
-             w2.add(1, 1)
diff --git a/third_party/tlslite/scripts/tls.py b/third_party/tlslite/scripts/tls.py
deleted file mode 100755
index 48035ce..0000000
--- a/third_party/tlslite/scripts/tls.py
+++ /dev/null
@@ -1,336 +0,0 @@
-#!/usr/bin/env python
-
-# Authors: 
-#   Trevor Perrin
-#   Marcelo Fernandez - bugfix and NPN support
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-from __future__ import print_function
-import sys
-import os
-import os.path
-import socket
-import time
-import getopt
-try:
-    import httplib
-    from SocketServer import *
-    from BaseHTTPServer import *
-    from SimpleHTTPServer import *
-except ImportError:
-    # Python 3.x
-    from http import client as httplib
-    from socketserver import *
-    from http.server import *
-
-if __name__ != "__main__":
-    raise "This must be run as a command, not used as a module!"
-
-from tlslite.api import *
-from tlslite import __version__
-
-try:
-    from tack.structures.Tack import Tack
-
-except ImportError:
-    pass
-
-def printUsage(s=None):
-    if s:
-        print("ERROR: %s" % s)
-
-    print("")
-    print("Version: %s" % __version__)
-    print("")
-    print("RNG: %s" % prngName)
-    print("")
-    print("Modules:")
-    if tackpyLoaded:
-        print("  tackpy      : Loaded")
-    else:
-        print("  tackpy      : Not Loaded")            
-    if m2cryptoLoaded:
-        print("  M2Crypto    : Loaded")
-    else:
-        print("  M2Crypto    : Not Loaded")
-    if pycryptoLoaded:
-        print("  pycrypto    : Loaded")
-    else:
-        print("  pycrypto    : Not Loaded")
-    if gmpyLoaded:
-        print("  GMPY        : Loaded")
-    else:
-        print("  GMPY        : Not Loaded")
-    
-    print("")
-    print("""Commands:
-
-  server  
-    [-k KEY] [-c CERT] [-t TACK] [-v VERIFIERDB] [-d DIR]
-    [--reqcert] HOST:PORT
-
-  client
-    [-k KEY] [-c CERT] [-u USER] [-p PASS]
-    HOST:PORT
-""")
-    sys.exit(-1)
-
-def printError(s):
-    """Print error message and exit"""
-    sys.stderr.write("ERROR: %s\n" % s)
-    sys.exit(-1)
-
-
-def handleArgs(argv, argString, flagsList=[]):
-    # Convert to getopt argstring format:
-    # Add ":" after each arg, ie "abc" -> "a:b:c:"
-    getOptArgString = ":".join(argString) + ":"
-    try:
-        opts, argv = getopt.getopt(argv, getOptArgString, flagsList)
-    except getopt.GetoptError as e:
-        printError(e) 
-    # Default values if arg not present  
-    privateKey = None
-    certChain = None
-    username = None
-    password = None
-    tacks = None
-    verifierDB = None
-    reqCert = False
-    directory = None
-    
-    for opt, arg in opts:
-        if opt == "-k":
-            s = open(arg, "rb").read()
-            privateKey = parsePEMKey(s, private=True)            
-        elif opt == "-c":
-            s = open(arg, "rb").read()
-            x509 = X509()
-            x509.parse(s)
-            certChain = X509CertChain([x509])
-        elif opt == "-u":
-            username = arg
-        elif opt == "-p":
-            password = arg
-        elif opt == "-t":
-            if tackpyLoaded:
-                s = open(arg, "rU").read()
-                tacks = Tack.createFromPemList(s)
-        elif opt == "-v":
-            verifierDB = VerifierDB(arg)
-            verifierDB.open()
-        elif opt == "-d":
-            directory = arg
-        elif opt == "--reqcert":
-            reqCert = True
-        else:
-            assert(False)
-            
-    if not argv:
-        printError("Missing address")
-    if len(argv)>1:
-        printError("Too many arguments")
-    #Split address into hostname/port tuple
-    address = argv[0]
-    address = address.split(":")
-    if len(address) != 2:
-        raise SyntaxError("Must specify <host>:<port>")
-    address = ( address[0], int(address[1]) )
-
-    # Populate the return list
-    retList = [address]
-    if "k" in argString:
-        retList.append(privateKey)
-    if "c" in argString:
-        retList.append(certChain)
-    if "u" in argString:
-        retList.append(username)
-    if "p" in argString:
-        retList.append(password)
-    if "t" in argString:
-        retList.append(tacks)
-    if "v" in argString:
-        retList.append(verifierDB)
-    if "d" in argString:
-        retList.append(directory)
-    if "reqcert" in flagsList:
-        retList.append(reqCert)
-    return retList
-
-
-def printGoodConnection(connection, seconds):
-    print("  Handshake time: %.3f seconds" % seconds)
-    print("  Version: %s" % connection.getVersionName())
-    print("  Cipher: %s %s" % (connection.getCipherName(), 
-        connection.getCipherImplementation()))
-    if connection.session.srpUsername:
-        print("  Client SRP username: %s" % connection.session.srpUsername)
-    if connection.session.clientCertChain:
-        print("  Client X.509 SHA1 fingerprint: %s" % 
-            connection.session.clientCertChain.getFingerprint())
-    if connection.session.serverCertChain:
-        print("  Server X.509 SHA1 fingerprint: %s" % 
-            connection.session.serverCertChain.getFingerprint())
-    if connection.session.serverName:
-        print("  SNI: %s" % connection.session.serverName)
-    if connection.session.tackExt:   
-        if connection.session.tackInHelloExt:
-            emptyStr = "\n  (via TLS Extension)"
-        else:
-            emptyStr = "\n  (via TACK Certificate)" 
-        print("  TACK: %s" % emptyStr)
-        print(str(connection.session.tackExt))
-    print("  Next-Protocol Negotiated: %s" % connection.next_proto) 
-    
-
-def clientCmd(argv):
-    (address, privateKey, certChain, username, password) = \
-        handleArgs(argv, "kcup")
-        
-    if (certChain and not privateKey) or (not certChain and privateKey):
-        raise SyntaxError("Must specify CERT and KEY together")
-    if (username and not password) or (not username and password):
-        raise SyntaxError("Must specify USER with PASS")
-    if certChain and username:
-        raise SyntaxError("Can use SRP or client cert for auth, not both")
-
-    #Connect to server
-    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    sock.settimeout(5)
-    sock.connect(address)
-    connection = TLSConnection(sock)
-    
-    settings = HandshakeSettings()
-    settings.useExperimentalTackExtension = True
-    
-    try:
-        start = time.clock()
-        if username and password:
-            connection.handshakeClientSRP(username, password, 
-                settings=settings, serverName=address[0])
-        else:
-            connection.handshakeClientCert(certChain, privateKey,
-                settings=settings, serverName=address[0])
-        stop = time.clock()        
-        print("Handshake success")        
-    except TLSLocalAlert as a:
-        if a.description == AlertDescription.user_canceled:
-            print(str(a))
-        else:
-            raise
-        sys.exit(-1)
-    except TLSRemoteAlert as a:
-        if a.description == AlertDescription.unknown_psk_identity:
-            if username:
-                print("Unknown username")
-            else:
-                raise
-        elif a.description == AlertDescription.bad_record_mac:
-            if username:
-                print("Bad username or password")
-            else:
-                raise
-        elif a.description == AlertDescription.handshake_failure:
-            print("Unable to negotiate mutually acceptable parameters")
-        else:
-            raise
-        sys.exit(-1)
-    printGoodConnection(connection, stop-start)
-    connection.close()
-
-
-def serverCmd(argv):
-    (address, privateKey, certChain, tacks, 
-        verifierDB, directory, reqCert) = handleArgs(argv, "kctbvd", ["reqcert"])
-
-
-    if (certChain and not privateKey) or (not certChain and privateKey):
-        raise SyntaxError("Must specify CERT and KEY together")
-    if tacks and not certChain:
-        raise SyntaxError("Must specify CERT with Tacks")
-    
-    print("I am an HTTPS test server, I will listen on %s:%d" % 
-            (address[0], address[1]))    
-    if directory:
-        os.chdir(directory)
-    print("Serving files from %s" % os.getcwd())
-    
-    if certChain and privateKey:
-        print("Using certificate and private key...")
-    if verifierDB:
-        print("Using verifier DB...")
-    if tacks:
-        print("Using Tacks...")
-        
-    #############
-    sessionCache = SessionCache()
-
-    class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer):
-        def handshake(self, connection):
-            print("About to handshake...")
-            activationFlags = 0
-            if tacks:
-                if len(tacks) == 1:
-                    activationFlags = 1
-                elif len(tacks) == 2:
-                    activationFlags = 3
-
-            try:
-                start = time.clock()
-                settings = HandshakeSettings()
-                settings.useExperimentalTackExtension=True
-                connection.handshakeServer(certChain=certChain,
-                                              privateKey=privateKey,
-                                              verifierDB=verifierDB,
-                                              tacks=tacks,
-                                              activationFlags=activationFlags,
-                                              sessionCache=sessionCache,
-                                              settings=settings,
-                                              nextProtos=[b"http/1.1"])
-                                              # As an example (does not work here):
-                                              #nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"])
-                stop = time.clock()
-            except TLSRemoteAlert as a:
-                if a.description == AlertDescription.user_canceled:
-                    print(str(a))
-                    return False
-                else:
-                    raise
-            except TLSLocalAlert as a:
-                if a.description == AlertDescription.unknown_psk_identity:
-                    if username:
-                        print("Unknown username")
-                        return False
-                    else:
-                        raise
-                elif a.description == AlertDescription.bad_record_mac:
-                    if username:
-                        print("Bad username or password")
-                        return False
-                    else:
-                        raise
-                elif a.description == AlertDescription.handshake_failure:
-                    print("Unable to negotiate mutually acceptable parameters")
-                    return False
-                else:
-                    raise
-                
-            connection.ignoreAbruptClose = True
-            printGoodConnection(connection, stop-start)
-            return True
-
-    httpd = MyHTTPServer(address, SimpleHTTPRequestHandler)
-    httpd.serve_forever()
-
-
-if __name__ == '__main__':
-    if len(sys.argv) < 2:
-        printUsage("Missing command")
-    elif sys.argv[1] == "client"[:len(sys.argv[1])]:
-        clientCmd(sys.argv[2:])
-    elif sys.argv[1] == "server"[:len(sys.argv[1])]:
-        serverCmd(sys.argv[2:])
-    else:
-        printUsage("Unknown command: %s" % sys.argv[1])
-
diff --git a/third_party/tlslite/scripts/tlsdb.py b/third_party/tlslite/scripts/tlsdb.py
deleted file mode 100755
index 476d618..0000000
--- a/third_party/tlslite/scripts/tlsdb.py
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env python
-
-# Authors: 
-#   Trevor Perrin
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-from __future__ import print_function
-import sys
-import os
-import socket
-import math
-
-if __name__ != "__main__":
-    raise "This must be run as a command, not used as a module!"
-
-
-from tlslite import *
-from tlslite import __version__
-
-if len(sys.argv) == 1 or (len(sys.argv)==2 and sys.argv[1].lower().endswith("help")):
-    print("")
-    print("Version: %s" % __version__)
-    print("")
-    print("RNG: %s" % prngName)
-    print("")
-    print("Modules:")
-    if m2cryptoLoaded:
-        print("  M2Crypto    : Loaded")
-    else:
-        print("  M2Crypto    : Not Loaded")
-    if pycryptoLoaded:
-        print("  pycrypto    : Loaded")
-    else:
-        print("  pycrypto    : Not Loaded")
-    if gmpyLoaded:
-        print("  GMPY        : Loaded")
-    else:
-        print("  GMPY        : Not Loaded")
-    print("")
-    print("Commands:")
-    print("")
-    print("  createsrp       <db>")
-    print("")
-    print("  add    <db> <user> <pass> [<bits>]")
-    print("  del    <db> <user>")
-    print("  check  <db> <user> [<pass>]")
-    print("  list   <db>")
-    sys.exit()
-
-cmd = sys.argv[1].lower()
-
-class Args:
-    def __init__(self, argv):
-        self.argv = argv
-    def get(self, index):
-        if len(self.argv)<=index:
-            raise SyntaxError("Not enough arguments")
-        return self.argv[index]
-    def getLast(self, index):
-        if len(self.argv)>index+1:
-            raise SyntaxError("Too many arguments")
-        return self.get(index)
-
-args = Args(sys.argv)
-
-def reformatDocString(s):
-    lines = s.splitlines()
-    newLines = []
-    for line in lines:
-        newLines.append("  " + line.strip())
-    return "\n".join(newLines)
-
-try:
-    if cmd == "help":
-        command = args.getLast(2).lower()
-        if command == "valid":
-            print("")
-        else:
-            print("Bad command: '%s'" % command)
-
-    elif cmd == "createsrp":
-        dbName = args.get(2)
-
-        db = VerifierDB(dbName)
-        db.create()
-
-    elif cmd == "add":
-        dbName = args.get(2)
-        username = args.get(3)
-        password = args.get(4)
-
-        db = VerifierDB(dbName)
-        db.open()
-        if username in db:
-            print("User already in database!")
-            sys.exit()
-        bits = int(args.getLast(5))
-        N, g, salt, verifier = VerifierDB.makeVerifier(username, password, bits)
-        db[username] = N, g, salt, verifier
-
-    elif cmd == "del":
-        dbName = args.get(2)
-        username = args.getLast(3)
-        db = VerifierDB(dbName)
-        db.open()
-        del(db[username])
-
-    elif cmd == "check":
-        dbName = args.get(2)
-        username = args.get(3)
-        if len(sys.argv)>=5:
-            password = args.getLast(4)
-        else:
-            password = None
-
-        db = VerifierDB(dbName)
-        db.open()
-
-        try:
-            db[username]
-            print("Username exists")
-
-            if password:
-                if db.check(username, password):
-                    print("Password is correct")
-                else:
-                    print("Password is wrong")
-        except KeyError:
-            print("Username does not exist")
-            sys.exit()
-
-    elif cmd == "list":
-        dbName = args.get(2)
-        db = VerifierDB(dbName)
-        db.open()
-
-        print("Verifier Database")
-        def numBits(n):
-            if n==0:
-                return 0
-            return int(math.floor(math.log(n, 2))+1)
-        for username in db.keys():
-            N, g, s, v = db[username]
-            print(numBits(N), username)
-    else:
-        print("Bad command: '%s'" % cmd)
-except:
-    raise
diff --git a/third_party/tlslite/setup.py b/third_party/tlslite/setup.py
deleted file mode 100755
index 3ce281a..0000000
--- a/third_party/tlslite/setup.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-from distutils.core import setup
-
-setup(name="tlslite",
-      version="0.4.8",
-      author="Trevor Perrin",
-      author_email="tlslite@trevp.net",
-      url="http://trevp.net/tlslite/",
-      description="tlslite implements SSL and TLS.",
-      license="public domain and BSD",
-      scripts=["scripts/tls.py", "scripts/tlsdb.py"],
-      packages=["tlslite", "tlslite.utils", "tlslite.integration"],)
diff --git a/third_party/tlslite/tests/TACK1.pem b/third_party/tlslite/tests/TACK1.pem
deleted file mode 100644
index 039d848..0000000
--- a/third_party/tlslite/tests/TACK1.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-Created by TACK.py 0.9.6
-Created at 2012-05-08T15:53:56Z
------BEGIN TACK-----
-lJ7JcxIC9y6i/jTkTh+MXf0aO23J58PjUQCAI4vCMINlcMGSC8Vyq9On51hk5zAz
-DlIdXzC7zcUC7AN7/alXYwAAAkJ0Bb8+RaM9YEywaJEGViKJJmpYG/gJHgfGaefI
-9kKbXSDmXHI2tbZPnCxzR4ZXz21HxFm1SPYijTKm4zm5dAzXzvneOTRf/SFbY0dZ
-s7UpHKK4yOhREoGH8z8kxxD5/BXb5A==
------END TACK-----
diff --git a/third_party/tlslite/tests/TACK2.pem b/third_party/tlslite/tests/TACK2.pem
deleted file mode 100644
index e037af9f..0000000
--- a/third_party/tlslite/tests/TACK2.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-Created by tack.py 0.9.7
-Created at 2012-08-31T19:15:38Z
------BEGIN TACK-----
-x7MspJSqsflA4qZ6qG8r8Hd5AB0+BB09n96vuF5Z1ayBeGzrny90WeCu3E3G2d8Y
-620TVYfnALIaMg//MZ8ovQAAAkMcxb8+RaM9YEywaJEGViKJJmpYG/gJHgfGaefI
-9kKbXSDmq3tmkncGftPeMAUh3T2vcXNiRnRqyFArnCKr2gCSj2vsCiS3F+qVhaUv
-OyxAcIhminamGruajdPSXMtlCCwWag==
------END TACK-----
diff --git a/third_party/tlslite/tests/TACK_Key1.pem b/third_party/tlslite/tests/TACK_Key1.pem
deleted file mode 100644
index 1ce731c..0000000
--- a/third_party/tlslite/tests/TACK_Key1.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-Created by TACK.py 0.9.6
-Created at 2012-05-08T15:53:52Z
------BEGIN TACK PRIVATE KEY-----
-AQAAIAA/48N0HFypVQPPrRP2xcMlomOznNFbI+Svx5TNjOD84sUAV/i0wvhAwz3q
-yyoVeSOUnslzEgL3LqL+NOROH4xd/Ro7bcnnw+NRAIAji8Iwg2VwwZILxXKr06fn
-WGTnMDMOUh1fMLvNxQLsA3v9qVdjES84mJMzUffdoSIMdXcMr6BP+8qqz7MaygMd
-u5jvi1o=
------END TACK PRIVATE KEY-----
diff --git a/third_party/tlslite/tests/TACK_Key2.pem b/third_party/tlslite/tests/TACK_Key2.pem
deleted file mode 100644
index f1f1e06..0000000
--- a/third_party/tlslite/tests/TACK_Key2.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-Created by tack.py 0.9.7
-Created at 2012-08-31T19:14:51Z
------BEGIN TACK PRIVATE KEY-----
-AQAAIABLL9BmznVXdNdz10CZz8Eyt3EDka+1c7By4eCOLpgBnk+50urYJhoR+k7b
-XeOB02DHsyyklKqx+UDipnqobyvwd3kAHT4EHT2f3q+4XlnVrIF4bOufL3RZ4K7c
-TcbZ3xjrbRNVh+cAshoyD/8xnyi9aSBVcOukGlmuX11I/dEAUwikVX0/LywYqgUn
-cBFiH1Y=
------END TACK PRIVATE KEY-----
diff --git a/third_party/tlslite/tests/TACKs.pem b/third_party/tlslite/tests/TACKs.pem
deleted file mode 100644
index 11965555..0000000
--- a/third_party/tlslite/tests/TACKs.pem
+++ /dev/null
@@ -1,16 +0,0 @@
-Created by TACK.py 0.9.6
-Created at 2012-05-08T15:53:56Z
------BEGIN TACK-----
-lJ7JcxIC9y6i/jTkTh+MXf0aO23J58PjUQCAI4vCMINlcMGSC8Vyq9On51hk5zAz
-DlIdXzC7zcUC7AN7/alXYwAAAkJ0Bb8+RaM9YEywaJEGViKJJmpYG/gJHgfGaefI
-9kKbXSDmXHI2tbZPnCxzR4ZXz21HxFm1SPYijTKm4zm5dAzXzvneOTRf/SFbY0dZ
-s7UpHKK4yOhREoGH8z8kxxD5/BXb5A==
------END TACK-----
-Created by tack.py 0.9.7
-Created at 2012-08-31T19:15:38Z
------BEGIN TACK-----
-x7MspJSqsflA4qZ6qG8r8Hd5AB0+BB09n96vuF5Z1ayBeGzrny90WeCu3E3G2d8Y
-620TVYfnALIaMg//MZ8ovQAAAkMcxb8+RaM9YEywaJEGViKJJmpYG/gJHgfGaefI
-9kKbXSDmq3tmkncGftPeMAUh3T2vcXNiRnRqyFArnCKr2gCSj2vsCiS3F+qVhaUv
-OyxAcIhminamGruajdPSXMtlCCwWag==
------END TACK-----
diff --git a/third_party/tlslite/tests/TACKunrelated.pem b/third_party/tlslite/tests/TACKunrelated.pem
deleted file mode 100644
index daf0c63..0000000
--- a/third_party/tlslite/tests/TACKunrelated.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-Created by TACK.py 0.9.6
-Created at 2012-05-08T17:12:57Z
------BEGIN TACK-----
-lJ7JcxIC9y6i/jTkTh+MXf0aO23J58PjUQCAI4vCMINlcMGSC8Vyq9On51hk5zAz
-DlIdXzC7zcUC7AN7/alXYwMFAchwkzK2S2ZyeiBj5AZvO5WMsKruV2pezv2VM5m7
-iHRzHZWHnUVusrs/d04QnVS2Btmt5hECAKdcWK0qZHnMxhZhom9DExiqLQW0A05E
-xHvWKhN8y6J9UATLvGjjm3U7oyNxzQ==
------END TACK-----
diff --git a/third_party/tlslite/tests/clientX509Cert.pem b/third_party/tlslite/tests/clientX509Cert.pem
deleted file mode 100644
index f2cfa36..0000000
--- a/third_party/tlslite/tests/clientX509Cert.pem
+++ /dev/null
@@ -1,16 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICfjCCAecCCQDgdeCLz7d92jANBgkqhkiG9w0BAQUFADCBgDELMAkGA1UEBhMC
-VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQ8wDQYDVQQKEwZUcmV2
-Q28xCzAJBgNVBAsTAkNBMRIwEAYDVQQDEwlUcmV2Q28gQ0ExIDAeBgkqhkiG9w0B
-CQEWEXRsc2xpdGVAdHJldnAubmV0MB4XDTEyMDIwNjAxMDMxMVoXDTQyMDEyOTAx
-MDMxMVowgYUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEBxMHT2Fr
-bGFuZDEPMA0GA1UEChMGVHJldkNvMQwwCgYDVQQLFANSJkQxFjAUBgNVBAMTDVRy
-ZXZvciBQZXJyaW4xIDAeBgkqhkiG9w0BCQEWEXRsc2xpdGVAdHJldnAubmV0MIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrncYzz0HWlT3ELBTZ1Jt/ZDFWlHW9
-SrhlwR5Pd8bEonXCxhomAssz4SkJMaByGFyAUAT4bqf41PV50y5lkYVfgUIy8qQS
-Gd/qJrNuFa6odWt3MExQdVCXKTOdjYQmhwvXo6zlf7u/Sj5NICAWmXRHZFBljqG8
-QasxPrLSbWUtWQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAJRqUTQ6pZ71rm46+qXo
-Sqc5tnj42uIn1eIfnm5pbPxXFvuP3RbuHVO140+LQL844c2JCOKeu9dQPKxoRNU7
-sQLdo8+o+KboiYif6m9Ial4ss0I5MhPPVi9heguRbcFHx+87q8xdN7vd6Wn2gw/l
-IV+b9EUQMWYFBCokR8o7o+IV
------END CERTIFICATE-----
diff --git a/third_party/tlslite/tests/clientX509Key.pem b/third_party/tlslite/tests/clientX509Key.pem
deleted file mode 100644
index e728c69..0000000
--- a/third_party/tlslite/tests/clientX509Key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXwIBAAKBgQCrncYzz0HWlT3ELBTZ1Jt/ZDFWlHW9SrhlwR5Pd8bEonXCxhom
-Assz4SkJMaByGFyAUAT4bqf41PV50y5lkYVfgUIy8qQSGd/qJrNuFa6odWt3MExQ
-dVCXKTOdjYQmhwvXo6zlf7u/Sj5NICAWmXRHZFBljqG8QasxPrLSbWUtWQIDAQAB
-AoGBAIo99cMWWTq5zZ+QwtsV4Iyl8PiFbrKk1hVhk0EAgyUymRnk6ntkFLwdzCiT
-yWMfLKRP0TEuMjDHm1YfP2ih6ITMh83SLF4og0dDzU+tn3PX/XWaoYZr8HsFTDMi
-FhrWXXBX8ST3F2aEyOxXZj8SGFu5YIJ8iemztANzZVSvYkWBAkEA2EbI6rnpXc5t
-fKhdkXa0c8l+Uyn/8JadHJ8sobzNhZ/CeC0a9PwhZLQvsRgNXXjYUFJ7N2igoIrk
-y0e8f+iD/QJBAMsjFrsrhmXcksf4RX6ZAg1rcJS115JjH2EnbbWd2nBLHUBwywGh
-VJhNyQRWBNlVGMrYWCQwHcZNOdUsvmLX140CQQC5v2GDpxQ0irwh2gAylH67CwzB
-pEq6eMCK+nI8nojtAJ7m0+ZZDcooUVC8imnAI6+0nIJSvjtmZqPFquDMAgiJAkEA
-ox/mXR+yqZHbfSHuDJ+qekRQ/9qW5kMbK9WR0EqW454uO1VYcFKxsCymxAiflDc1
-1Y6uGUFaZ6gUTQ/FQ3K48QJBAIlPKkD8VfNg/3B6wq7gmqRIy9MblLLZo2Qh4nZA
-4icCv/vpHH+o6Ccxad03LQKsTNJl3z52G4sKgASudWiBbLs=
------END RSA PRIVATE KEY-----
diff --git a/third_party/tlslite/tests/httpsclient.py b/third_party/tlslite/tests/httpsclient.py
deleted file mode 100755
index 1a764d7..0000000
--- a/third_party/tlslite/tests/httpsclient.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-from tlslite import HTTPTLSConnection, HandshakeSettings
-
-settings = HandshakeSettings()
-settings.useExperimentalTackExtension = True
-
-h = HTTPTLSConnection("localhost", 4443, settings=settings)    
-h.request("GET", "/index.html")
-r = h.getresponse()
-print(r.read())
diff --git a/third_party/tlslite/tests/httpsserver.sh b/third_party/tlslite/tests/httpsserver.sh
deleted file mode 100755
index 7449ad72..0000000
--- a/third_party/tlslite/tests/httpsserver.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-python ../scripts/tls.py server -k serverX509Key.pem -c serverX509Cert.pem -t TACK1.pem localhost:4443
diff --git a/third_party/tlslite/tests/index.html b/third_party/tlslite/tests/index.html
deleted file mode 100644
index 8cc93d31..0000000
--- a/third_party/tlslite/tests/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-<title>TLS Lite test server</title>
-</head>
-<body>
-<H1>TLS Lite test server</H1>
-<b>I am a TLS Lite HTTPS test server<br>
-</body>
-</html>
diff --git a/third_party/tlslite/tests/serverX509Cert.pem b/third_party/tlslite/tests/serverX509Cert.pem
deleted file mode 100644
index f3c86e4e..0000000
--- a/third_party/tlslite/tests/serverX509Cert.pem
+++ /dev/null
@@ -1,16 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICfzCCAegCCQDgdeCLz7d93DANBgkqhkiG9w0BAQUFADCBgDELMAkGA1UEBhMC
-VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQ8wDQYDVQQKEwZUcmV2
-Q28xCzAJBgNVBAsTAkNBMRIwEAYDVQQDEwlUcmV2Q28gQ0ExIDAeBgkqhkiG9w0B
-CQEWEXRsc2xpdGVAdHJldnAubmV0MB4XDTEyMDIwNjAxMDg0OFoXDTQyMDEyOTAx
-MDg0OFowgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEBxMHT2Fr
-bGFuZDEPMA0GA1UEChMGVHJldkNvMQwwCgYDVQQLFANSJkQxFzAVBgNVBAMTDnRl
-c3QudHJldnAubmV0MSAwHgYJKoZIhvcNAQkBFhF0bHNsaXRlQHRyZXZwLm5ldDCB
-nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqcLSY6l8mJQgMcSp6Vj0EohRlYEC
-5cj4xcMvkQ+tKEJpAs2r//4Xyn5vQrv2GHOgOTOCKa87tcAWGWrsbGYiRETBCz8k
-/1uf6FPTPN+FSOkuylPzNcuGk1bo+d9l3nyeNkDjem0SqZfmOwZc2h9+yLB8J4iU
-lt1Sv9IZfcioQ/cCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCz201zjXEC2yTuJBN3
-XT3Q/HXxPOnwkyU3+gKCGJmXeGoVoFDD23RbJ0Nabux1vnQHC4YsHNXPN1b++UOo
-NcewUzJbrg9R7VP1teQsLEfaj26oeJkp2yls0b1PrWu/4aTpG7VORdPBeiCn7Alu
-+3uDeYqQxcaaRGK2rWBJ3OeQkg==
------END CERTIFICATE-----
diff --git a/third_party/tlslite/tests/serverX509Key.pem b/third_party/tlslite/tests/serverX509Key.pem
deleted file mode 100644
index b1f74839..0000000
--- a/third_party/tlslite/tests/serverX509Key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQCpwtJjqXyYlCAxxKnpWPQSiFGVgQLlyPjFwy+RD60oQmkCzav/
-/hfKfm9Cu/YYc6A5M4Iprzu1wBYZauxsZiJERMELPyT/W5/oU9M834VI6S7KU/M1
-y4aTVuj532XefJ42QON6bRKpl+Y7BlzaH37IsHwniJSW3VK/0hl9yKhD9wIDAQAB
-AoGAf7+yX3ld39woVgtu6cEc+w1Gh8EsEwun2frGQt2PKuq+53Mq6lumP6XhyFB2
-I3RvsFwIqaHKxz0j5EDIZdJ+GbPwDIcgDONamVIpT8OZcEgBBDjLByfeGzCikCMI
-rBOVh5qRfpfJjs5tDzyceYHs7Yc3/Jh0AuRCZvprXp1rLnECQQDTuE0FyCGmykiy
-m/qYUI6ere9zRJLprUx8BLwhIGl1a32PJjKLQIyRVvf7wigIeRsaY/Q/nZ6ByKRz
-u9bXmQzrAkEAzUP/tIRI8OpczKYydlUL12f4F61sABrE0lP5cdvG6rky2AAR7BkG
-7Ftto4wuevFf3mz6PF5ifMD/l/NmwiqyJQJBAMgq4h9KRI6Vhz/eeoFRAFYDqnS3
-a5KkdsB2FYvYQfxywQX7HiRLxdqPd+s9eG3yWe6Me9s9YSPhF6IYAJpbqDsCQQCh
-zIbj+R4x4NrTafH++pzB569UopuuHWulyxGmITJT1TXxs2RtMXEWoB71Ostsl5UV
-E9vP+Coz4kHWucL3LIaNAkBvxJvpFwOENSKCoGaflkl6K1Rta3IQJzrb6cRpfGmR
-wT8Zbt5J8toXmGVqYnOnLfgJpVaCROe4CxOUL30FDuAl
------END RSA PRIVATE KEY-----
diff --git a/third_party/tlslite/tests/tlstest.py b/third_party/tlslite/tests/tlstest.py
deleted file mode 100755
index 7985d23..0000000
--- a/third_party/tlslite/tests/tlstest.py
+++ /dev/null
@@ -1,797 +0,0 @@
-#!/usr/bin/env python
-
-# Authors: 
-#   Trevor Perrin
-#   Kees Bos - Added tests for XML-RPC
-#   Dimitris Moraitis - Anon ciphersuites
-#   Marcelo Fernandez - Added test for NPN
-#   Martin von Loewis - python 3 port
-
-#
-# See the LICENSE file for legal information regarding use of this file.
-from __future__ import print_function
-import sys
-import os
-import os.path
-import socket
-import time
-import getopt
-try:
-    from BaseHTTPServer import HTTPServer
-    from SimpleHTTPServer import SimpleHTTPRequestHandler
-except ImportError:
-    from http.server import HTTPServer, SimpleHTTPRequestHandler
-
-from tlslite import TLSConnection, Fault, HandshakeSettings, \
-    X509, X509CertChain, IMAP4_TLS, VerifierDB, Session, SessionCache, \
-    parsePEMKey, constants, \
-    AlertDescription, HTTPTLSConnection, TLSSocketServerMixIn, \
-    POP3_TLS, m2cryptoLoaded, pycryptoLoaded, gmpyLoaded, tackpyLoaded, \
-    Checker, __version__
-
-from tlslite.errors import *
-from tlslite.utils.cryptomath import prngName
-try:
-    import xmlrpclib
-except ImportError:
-    # Python 3
-    from xmlrpc import client as xmlrpclib
-from tlslite import *
-
-try:
-    from tack.structures.Tack import Tack
-    
-except ImportError:
-    pass
-
-def printUsage(s=None):
-    if m2cryptoLoaded:
-        crypto = "M2Crypto/OpenSSL"
-    else:
-        crypto = "Python crypto"        
-    if s:
-        print("ERROR: %s" % s)
-    print("""\ntls.py version %s (using %s)  
-
-Commands:
-  server HOST:PORT DIRECTORY
-
-  client HOST:PORT DIRECTORY
-""" % (__version__, crypto))
-    sys.exit(-1)
-    
-
-def testConnClient(conn):
-    b1 = os.urandom(1)
-    b10 = os.urandom(10)
-    b100 = os.urandom(100)
-    b1000 = os.urandom(1000)
-    conn.write(b1)
-    conn.write(b10)
-    conn.write(b100)
-    conn.write(b1000)
-    assert(conn.read(min=1, max=1) == b1)
-    assert(conn.read(min=10, max=10) == b10)
-    assert(conn.read(min=100, max=100) == b100)
-    assert(conn.read(min=1000, max=1000) == b1000)
-
-def clientTestCmd(argv):
-    
-    address = argv[0]
-    dir = argv[1]    
-
-    #Split address into hostname/port tuple
-    address = address.split(":")
-    address = ( address[0], int(address[1]) )
-
-    def connect():
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        if hasattr(sock, 'settimeout'): #It's a python 2.3 feature
-            sock.settimeout(5)
-        sock.connect(address)
-        c = TLSConnection(sock)
-        return c
-
-    test = 0
-
-    badFault = False
-
-    print("Test 0 - anonymous handshake")
-    connection = connect()
-    connection.handshakeClientAnonymous()
-    testConnClient(connection)
-    connection.close()
-        
-    print("Test 1 - good X509 (plus SNI)")
-    connection = connect()
-    connection.handshakeClientCert(serverName=address[0])
-    testConnClient(connection)
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    assert(connection.session.serverName == address[0])
-    connection.close()
-
-    print("Test 1.a - good X509, SSLv3")
-    connection = connect()
-    settings = HandshakeSettings()
-    settings.minVersion = (3,0)
-    settings.maxVersion = (3,0)
-    connection.handshakeClientCert(settings=settings)
-    testConnClient(connection)    
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    connection.close()    
-
-    print("Test 1.b - good X509, RC4-MD5")
-    connection = connect()
-    settings = HandshakeSettings()
-    settings.macNames = ["md5"]
-    connection.handshakeClientCert(settings=settings)
-    testConnClient(connection)    
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    assert(connection.session.cipherSuite == constants.CipherSuite.TLS_RSA_WITH_RC4_128_MD5)
-    connection.close()
-
-    if tackpyLoaded:
-                    
-        settings = HandshakeSettings()
-        settings.useExperimentalTackExtension = True
-
-        print("Test 2.a - good X.509, TACK")
-        connection = connect()
-        connection.handshakeClientCert(settings=settings)
-        assert(connection.session.tackExt.tacks[0].getTackId() == "rrted.ptvtl.d2uiq.ox2xe.w4ss3")
-        assert(connection.session.tackExt.activation_flags == 1)        
-        testConnClient(connection)    
-        connection.close()    
-
-        print("Test 2.b - good X.509, TACK unrelated to cert chain")
-        connection = connect()
-        try:
-            connection.handshakeClientCert(settings=settings)
-            assert(False)
-        except TLSLocalAlert as alert:
-            if alert.description != AlertDescription.illegal_parameter:
-                raise        
-        connection.close()
-
-    print("Test 3 - good SRP")
-    connection = connect()
-    connection.handshakeClientSRP("test", "password")
-    testConnClient(connection)
-    connection.close()
-
-    print("Test 4 - SRP faults")
-    for fault in Fault.clientSrpFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeClientSRP("test", "password")
-            print("  Good Fault %s" % (Fault.faultNames[fault]))
-        except TLSFaultError as e:
-            print("  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e)))
-            badFault = True
-
-    print("Test 6 - good SRP: with X.509 certificate, TLSv1.0")
-    settings = HandshakeSettings()
-    settings.minVersion = (3,1)
-    settings.maxVersion = (3,1)    
-    connection = connect()
-    connection.handshakeClientSRP("test", "password", settings=settings)
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    testConnClient(connection)
-    connection.close()
-
-    print("Test 7 - X.509 with SRP faults")
-    for fault in Fault.clientSrpFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeClientSRP("test", "password")
-            print("  Good Fault %s" % (Fault.faultNames[fault]))
-        except TLSFaultError as e:
-            print("  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e)))
-            badFault = True
-
-    print("Test 11 - X.509 faults")
-    for fault in Fault.clientNoAuthFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeClientCert()
-            print("  Good Fault %s" % (Fault.faultNames[fault]))
-        except TLSFaultError as e:
-            print("  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e)))
-            badFault = True
-
-    print("Test 14 - good mutual X509")
-    x509Cert = X509().parse(open(os.path.join(dir, "clientX509Cert.pem")).read())
-    x509Chain = X509CertChain([x509Cert])
-    s = open(os.path.join(dir, "clientX509Key.pem")).read()
-    x509Key = parsePEMKey(s, private=True)
-
-    connection = connect()
-    connection.handshakeClientCert(x509Chain, x509Key)
-    testConnClient(connection)
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    connection.close()
-
-    print("Test 14.a - good mutual X509, SSLv3")
-    connection = connect()
-    settings = HandshakeSettings()
-    settings.minVersion = (3,0)
-    settings.maxVersion = (3,0)
-    connection.handshakeClientCert(x509Chain, x509Key, settings=settings)
-    testConnClient(connection)
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    connection.close()
-
-    print("Test 15 - mutual X.509 faults")
-    for fault in Fault.clientCertFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeClientCert(x509Chain, x509Key)
-            print("  Good Fault %s" % (Fault.faultNames[fault]))
-        except TLSFaultError as e:
-            print("  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e)))
-            badFault = True
-
-    print("Test 18 - good SRP, prepare to resume... (plus SNI)")
-    connection = connect()
-    connection.handshakeClientSRP("test", "password", serverName=address[0])
-    testConnClient(connection)
-    connection.close()
-    session = connection.session
-
-    print("Test 19 - resumption (plus SNI)")
-    connection = connect()
-    connection.handshakeClientSRP("test", "garbage", serverName=address[0], 
-                                    session=session)
-    testConnClient(connection)
-    #Don't close! -- see below
-
-    print("Test 20 - invalidated resumption (plus SNI)")
-    connection.sock.close() #Close the socket without a close_notify!
-    connection = connect()
-    try:
-        connection.handshakeClientSRP("test", "garbage", 
-                        serverName=address[0], session=session)
-        assert(False)
-    except TLSRemoteAlert as alert:
-        if alert.description != AlertDescription.bad_record_mac:
-            raise
-    connection.close()
-    
-    print("Test 21 - HTTPS test X.509")
-    address = address[0], address[1]+1
-    if hasattr(socket, "timeout"):
-        timeoutEx = socket.timeout
-    else:
-        timeoutEx = socket.error
-    while 1:
-        try:
-            time.sleep(2)
-            htmlBody = bytearray(open(os.path.join(dir, "index.html")).read(), "utf-8")
-            fingerprint = None
-            for y in range(2):
-                checker =Checker(x509Fingerprint=fingerprint)
-                h = HTTPTLSConnection(\
-                        address[0], address[1], checker=checker)
-                for x in range(3):
-                    h.request("GET", "/index.html")
-                    r = h.getresponse()
-                    assert(r.status == 200)
-                    b = bytearray(r.read())
-                    assert(b == htmlBody)
-                fingerprint = h.tlsSession.serverCertChain.getFingerprint()
-                assert(fingerprint)
-            time.sleep(2)
-            break
-        except timeoutEx:
-            print("timeout, retrying...")
-            pass
-
-    address = address[0], address[1]+1
-
-    implementations = []
-    if m2cryptoLoaded:
-        implementations.append("openssl")
-    if pycryptoLoaded:
-        implementations.append("pycrypto")
-    implementations.append("python")
-
-    print("Test 22 - different ciphers, TLSv1.0")
-    for implementation in implementations:
-        for cipher in ["aes128", "aes256", "rc4"]:
-
-            print("Test 22:", end=' ')
-            connection = connect()
-
-            settings = HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-            settings.minVersion = (3,1)
-            settings.maxVersion = (3,1)            
-            connection.handshakeClientCert(settings=settings)
-            testConnClient(connection)
-            print("%s %s" % (connection.getCipherName(), connection.getCipherImplementation()))
-            connection.close()
-
-    print("Test 23 - throughput test")
-    for implementation in implementations:
-        for cipher in ["aes128gcm", "aes128", "aes256", "3des", "rc4"]:
-            if cipher == "3des" and implementation not in ("openssl", "pycrypto"):
-                continue
-            if cipher == "aes128gcm" and implementation not in ("pycrypto", "python"):
-                continue
-
-            print("Test 23:", end=' ')
-            connection = connect()
-
-            settings = HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-            connection.handshakeClientCert(settings=settings)
-            print("%s %s:" % (connection.getCipherName(), connection.getCipherImplementation()), end=' ')
-
-            startTime = time.clock()
-            connection.write(b"hello"*10000)
-            h = connection.read(min=50000, max=50000)
-            stopTime = time.clock()
-            if stopTime-startTime:
-                print("100K exchanged at rate of %d bytes/sec" % int(100000/(stopTime-startTime)))
-            else:
-                print("100K exchanged very fast")
-
-            assert(h == b"hello"*10000)
-            connection.close()
-    
-    print("Test 24.a - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'http/1.1')
-    connection.close()
-
-    print("Test 24.b - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"spdy/2", b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'spdy/2')
-    connection.close()
-    
-    print("Test 24.c - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"spdy/2", b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'spdy/2')
-    connection.close()
-    
-    print("Test 24.d - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'spdy/2')
-    connection.close()
-    
-    print("Test 24.e - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'spdy/3')
-    connection.close()
-
-    print("Test 24.f - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'http/1.1')
-    connection.close()
-
-    print("Test 24.g - Next-Protocol Client Negotiation")
-    connection = connect()
-    connection.handshakeClientCert(nextProtos=[b"spdy/2", b"http/1.1"])
-    #print("  Next-Protocol Negotiated: %s" % connection.next_proto)
-    assert(connection.next_proto == b'spdy/2')
-    connection.close()
-    
-    print('Test 25 - good standard XMLRPC https client')
-    time.sleep(2) # Hack for lack of ability to set timeout here
-    address = address[0], address[1]+1
-    server = xmlrpclib.Server('https://%s:%s' % address)
-    assert server.add(1,2) == 3
-    assert server.pow(2,4) == 16
-
-    print('Test 26 - good tlslite XMLRPC client')
-    transport = XMLRPCTransport(ignoreAbruptClose=True)
-    server = xmlrpclib.Server('https://%s:%s' % address, transport)
-    assert server.add(1,2) == 3
-    assert server.pow(2,4) == 16
-
-    print('Test 27 - good XMLRPC ignored protocol')
-    server = xmlrpclib.Server('http://%s:%s' % address, transport)
-    assert server.add(1,2) == 3
-    assert server.pow(2,4) == 16
-        
-    print("Test 28 - Internet servers test")
-    try:
-        i = IMAP4_TLS("cyrus.andrew.cmu.edu")
-        i.login("anonymous", "anonymous@anonymous.net")
-        i.logout()
-        print("Test 28: IMAP4 good")
-        p = POP3_TLS("pop.gmail.com")
-        p.quit()
-        print("Test 29: POP3 good")
-    except socket.error as e:
-        print("Non-critical error: socket error trying to reach internet server: ", e)   
-
-    if not badFault:
-        print("Test succeeded")
-    else:
-        print("Test failed")
-
-
-
-def testConnServer(connection):
-    count = 0
-    while 1:
-        s = connection.read()
-        count += len(s)
-        if len(s) == 0:
-            break
-        connection.write(s)
-        if count == 1111:
-            break
-
-def serverTestCmd(argv):
-
-    address = argv[0]
-    dir = argv[1]
-    
-    #Split address into hostname/port tuple
-    address = address.split(":")
-    address = ( address[0], int(address[1]) )
-
-    #Connect to server
-    lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    lsock.bind(address)
-    lsock.listen(5)
-
-    def connect():
-        return TLSConnection(lsock.accept()[0])
-
-    x509Cert = X509().parse(open(os.path.join(dir, "serverX509Cert.pem")).read())
-    x509Chain = X509CertChain([x509Cert])
-    s = open(os.path.join(dir, "serverX509Key.pem")).read()
-    x509Key = parsePEMKey(s, private=True)
-
-    print("Test 0 - Anonymous server handshake")
-    connection = connect()
-    connection.handshakeServer(anon=True)
-    testConnServer(connection)    
-    connection.close() 
-    
-    print("Test 1 - good X.509")
-    connection = connect()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
-    assert(connection.session.serverName == address[0])    
-    testConnServer(connection)    
-    connection.close()
-
-    print("Test 1.a - good X.509, SSL v3")
-    connection = connect()
-    settings = HandshakeSettings()
-    settings.minVersion = (3,0)
-    settings.maxVersion = (3,0)
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, settings=settings)
-    testConnServer(connection)
-    connection.close()            
-
-    print("Test 1.b - good X.509, RC4-MD5")
-    connection = connect()
-    settings = HandshakeSettings()
-    settings.macNames = ["sha", "md5"]
-    settings.cipherNames = ["rc4"]
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, settings=settings)
-    testConnServer(connection)
-    connection.close()            
-    
-    if tackpyLoaded:
-        tack = Tack.createFromPem(open("./TACK1.pem", "rU").read())
-        tackUnrelated = Tack.createFromPem(open("./TACKunrelated.pem", "rU").read())    
-            
-        settings = HandshakeSettings()
-        settings.useExperimentalTackExtension = True
-
-        print("Test 2.a - good X.509, TACK")
-        connection = connect()
-        connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
-            tacks=[tack], activationFlags=1, settings=settings)
-        testConnServer(connection)    
-        connection.close()        
-
-        print("Test 2.b - good X.509, TACK unrelated to cert chain")
-        connection = connect()
-        try:
-            connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
-                tacks=[tackUnrelated], settings=settings)
-            assert(False)
-        except TLSRemoteAlert as alert:
-            if alert.description != AlertDescription.illegal_parameter:
-                raise        
-    
-    print("Test 3 - good SRP")
-    verifierDB = VerifierDB()
-    verifierDB.create()
-    entry = VerifierDB.makeVerifier("test", "password", 1536)
-    verifierDB["test"] = entry
-
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB)
-    testConnServer(connection)
-    connection.close()
-
-    print("Test 4 - SRP faults")
-    for fault in Fault.clientSrpFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeServer(verifierDB=verifierDB)
-            assert()
-        except:
-            pass
-        connection.close()
-
-    print("Test 6 - good SRP: with X.509 cert")
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB, \
-                               certChain=x509Chain, privateKey=x509Key)
-    testConnServer(connection)    
-    connection.close()
-
-    print("Test 7 - X.509 with SRP faults")
-    for fault in Fault.clientSrpFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeServer(verifierDB=verifierDB, \
-                                       certChain=x509Chain, privateKey=x509Key)
-            assert()
-        except:
-            pass
-        connection.close()
-
-    print("Test 11 - X.509 faults")
-    for fault in Fault.clientNoAuthFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
-            assert()
-        except:
-            pass
-        connection.close()
-
-    print("Test 14 - good mutual X.509")
-    connection = connect()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
-    testConnServer(connection)
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    connection.close()
-
-    print("Test 14a - good mutual X.509, SSLv3")
-    connection = connect()
-    settings = HandshakeSettings()
-    settings.minVersion = (3,0)
-    settings.maxVersion = (3,0)
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True, settings=settings)
-    testConnServer(connection)
-    assert(isinstance(connection.session.serverCertChain, X509CertChain))
-    connection.close()
-
-    print("Test 15 - mutual X.509 faults")
-    for fault in Fault.clientCertFaults + Fault.genericFaults:
-        connection = connect()
-        connection.fault = fault
-        try:
-            connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
-            assert()
-        except:
-            pass
-        connection.close()
-
-    print("Test 18 - good SRP, prepare to resume")
-    sessionCache = SessionCache()
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    assert(connection.session.serverName == address[0])    
-    testConnServer(connection)
-    connection.close()
-
-    print("Test 19 - resumption")
-    connection = connect()
-    connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    assert(connection.session.serverName == address[0])
-    testConnServer(connection)    
-    #Don't close! -- see next test
-
-    print("Test 20 - invalidated resumption")
-    try:
-        connection.read(min=1, max=1)
-        assert() #Client is going to close the socket without a close_notify
-    except TLSAbruptCloseError as e:
-        pass
-    connection = connect()
-    try:
-        connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    except TLSLocalAlert as alert:
-        if alert.description != AlertDescription.bad_record_mac:
-            raise
-    connection.close()
-
-    print("Test 21 - HTTPS test X.509")
-
-    #Close the current listening socket
-    lsock.close()
-
-    #Create and run an HTTP Server using TLSSocketServerMixIn
-    class MyHTTPServer(TLSSocketServerMixIn,
-                       HTTPServer):
-        def handshake(self, tlsConnection):
-                tlsConnection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
-                return True
-    cd = os.getcwd()
-    os.chdir(dir)
-    address = address[0], address[1]+1
-    httpd = MyHTTPServer(address, SimpleHTTPRequestHandler)
-    for x in range(6):
-        httpd.handle_request()
-    httpd.server_close()
-    cd = os.chdir(cd)
-
-    #Re-connect the listening socket
-    lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    address = address[0], address[1]+1
-    lsock.bind(address)
-    lsock.listen(5)
-
-    implementations = []
-    if m2cryptoLoaded:
-        implementations.append("openssl")
-    if pycryptoLoaded:
-        implementations.append("pycrypto")
-    implementations.append("python")
-
-    print("Test 22 - different ciphers")
-    for implementation in ["python"] * len(implementations):
-        for cipher in ["aes128", "aes256", "rc4"]:
-
-            print("Test 22:", end=' ')
-            connection = connect()
-
-            settings = HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-
-            connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
-                                        settings=settings)
-            print(connection.getCipherName(), connection.getCipherImplementation())
-            testConnServer(connection)
-            connection.close()
-
-    print("Test 23 - throughput test")
-    for implementation in implementations:
-        for cipher in ["aes128gcm", "aes128", "aes256", "3des", "rc4"]:
-            if cipher == "3des" and implementation not in ("openssl", "pycrypto"):
-                continue
-            if cipher == "aes128gcm" and implementation not in ("pycrypto", "python"):
-                continue
-
-            print("Test 23:", end=' ')
-            connection = connect()
-
-            settings = HandshakeSettings()
-            settings.cipherNames = [cipher]
-            settings.cipherImplementations = [implementation, "python"]
-
-            connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
-                                        settings=settings)
-            print(connection.getCipherName(), connection.getCipherImplementation())
-            h = connection.read(min=50000, max=50000)
-            assert(h == b"hello"*10000)
-            connection.write(h)
-            connection.close()
-
-    print("Test 24.a - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[b"http/1.1"])
-    testConnServer(connection)
-    connection.close()
-
-    print("Test 24.b - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[b"spdy/2", b"http/1.1"])
-    testConnServer(connection)
-    connection.close()
-    
-    print("Test 24.c - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[b"http/1.1", b"spdy/2"])
-    testConnServer(connection)
-    connection.close()
-
-    print("Test 24.d - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[b"spdy/2", b"http/1.1"])
-    testConnServer(connection)
-    connection.close()
-    
-    print("Test 24.e - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[b"http/1.1", b"spdy/2", b"spdy/3"])
-    testConnServer(connection)
-    connection.close()
-    
-    print("Test 24.f - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[b"spdy/3", b"spdy/2"])
-    testConnServer(connection)
-    connection.close()
-    
-    print("Test 24.g - Next-Protocol Server Negotiation")
-    connection = connect()
-    settings = HandshakeSettings()
-    connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, 
-                               settings=settings, nextProtos=[])
-    testConnServer(connection)
-    connection.close()
-
-    print("Tests 25-27 - XMLRPXC server")
-    address = address[0], address[1]+1
-    class Server(TLSXMLRPCServer):
-
-        def handshake(self, tlsConnection):
-          try:
-              tlsConnection.handshakeServer(certChain=x509Chain,
-                                            privateKey=x509Key,
-                                            sessionCache=sessionCache)
-              tlsConnection.ignoreAbruptClose = True
-              return True
-          except TLSError as error:
-              print("Handshake failure:", str(error))
-              return False
-
-    class MyFuncs:
-        def pow(self, x, y): return pow(x, y)
-        def add(self, x, y): return x + y
-
-    server = Server(address)
-    server.register_instance(MyFuncs())
-    #sa = server.socket.getsockname()
-    #print "Serving HTTPS on", sa[0], "port", sa[1]
-    for i in range(6):
-        server.handle_request()
-
-    print("Test succeeded")
-
-
-if __name__ == '__main__':
-    if len(sys.argv) < 2:
-        printUsage("Missing command")
-    elif sys.argv[1] == "client"[:len(sys.argv[1])]:
-        clientTestCmd(sys.argv[2:])
-    elif sys.argv[1] == "server"[:len(sys.argv[1])]:
-        serverTestCmd(sys.argv[2:])
-    else:
-        printUsage("Unknown command: %s" % sys.argv[1])
diff --git a/third_party/tlslite/tests/verifierDB b/third_party/tlslite/tests/verifierDB
deleted file mode 100644
index 8e23c9d..0000000
--- a/third_party/tlslite/tests/verifierDB
+++ /dev/null
Binary files differ
diff --git a/third_party/tlslite/tlslite/__init__.py b/third_party/tlslite/tlslite/__init__.py
deleted file mode 100644
index acb5d3a..0000000
--- a/third_party/tlslite/tlslite/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite is a free python library that implements SSL and TLS. TLS Lite
-supports RSA and SRP ciphersuites. TLS Lite is pure python, however it can use
-other libraries for faster crypto operations. TLS Lite integrates with several
-stdlib neworking libraries.
-
-API documentation is available in the 'docs' directory.
-
-If you have questions or feedback, feel free to contact me.
-
-To use, do::
-
-    from tlslite import TLSConnection, ...
-    
-If you want to import the most useful objects, the cleanest way is:
-
-    from tlslite.api import *
-
-Then use the L{tlslite.TLSConnection.TLSConnection} class with a socket.
-(Or, use one of the integration classes in L{tlslite.integration}).
-
-@version: 0.4.8
-"""
-
-from tlslite.api import *
-from tlslite.api import __version__ # Unsure why this is needed, but it is
diff --git a/third_party/tlslite/tlslite/api.py b/third_party/tlslite/tlslite/api.py
deleted file mode 100644
index aabcc14..0000000
--- a/third_party/tlslite/tlslite/api.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-__version__ = "0.4.8"
-from .constants import AlertLevel, AlertDescription, ClientCertificateType, \
-                       Fault
-from .errors import *
-from .checker import Checker
-from .handshakesettings import HandshakeSettings
-from .session import Session
-from .sessioncache import SessionCache
-from .tlsconnection import TLSConnection
-from .verifierdb import VerifierDB
-from .x509 import X509
-from .x509certchain import X509CertChain
-
-from .integration.httptlsconnection import HTTPTLSConnection
-from .integration.tlssocketservermixin import TLSSocketServerMixIn
-from .integration.tlsasyncdispatchermixin import TLSAsyncDispatcherMixIn
-from .integration.pop3_tls import POP3_TLS
-from .integration.imap4_tls import IMAP4_TLS
-from .integration.smtp_tls import SMTP_TLS
-from .integration.xmlrpctransport import XMLRPCTransport
-from .integration.xmlrpcserver import TLSXMLRPCRequestHandler, \
-                                      TLSXMLRPCServer, \
-                                      MultiPathTLSXMLRPCServer
-
-from .utils.cryptomath import m2cryptoLoaded, gmpyLoaded, \
-                             pycryptoLoaded, prngName
-from .utils.keyfactory import generateRSAKey, parsePEMKey, \
-                             parseAsPublicKey, parsePrivateKey
-from .utils.tackwrapper import tackpyLoaded
diff --git a/third_party/tlslite/tlslite/basedb.py b/third_party/tlslite/tlslite/basedb.py
deleted file mode 100644
index e6b7944..0000000
--- a/third_party/tlslite/tlslite/basedb.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Base class for SharedKeyDB and VerifierDB."""
-
-try:
-    import anydbm
-except ImportError:
-    # Python 3
-    import dbm as anydbm
-import threading
-
-class BaseDB(object):
-    def __init__(self, filename, type):
-        self.type = type
-        self.filename = filename
-        if self.filename:
-            self.db = None
-        else:
-            self.db = {}
-        self.lock = threading.Lock()
-
-    def create(self):
-        """Create a new on-disk database.
-
-        @raise anydbm.error: If there's a problem creating the database.
-        """
-        if self.filename:
-            self.db = anydbm.open(self.filename, "n") #raises anydbm.error
-            self.db["--Reserved--type"] = self.type
-            self.db.sync()
-        else:
-            self.db = {}
-
-    def open(self):
-        """Open a pre-existing on-disk database.
-
-        @raise anydbm.error: If there's a problem opening the database.
-        @raise ValueError: If the database is not of the right type.
-        """
-        if not self.filename:
-            raise ValueError("Can only open on-disk databases")
-        self.db = anydbm.open(self.filename, "w") #raises anydbm.error
-        try:
-            if self.db["--Reserved--type"] != self.type:
-                raise ValueError("Not a %s database" % self.type)
-        except KeyError:
-            raise ValueError("Not a recognized database")
-
-    def __getitem__(self, username):
-        if self.db == None:
-            raise AssertionError("DB not open")
-
-        self.lock.acquire()
-        try:
-            valueStr = self.db[username]
-        finally:
-            self.lock.release()
-
-        return self._getItem(username, valueStr)
-
-    def __setitem__(self, username, value):
-        if self.db == None:
-            raise AssertionError("DB not open")
-
-        valueStr = self._setItem(username, value)
-
-        self.lock.acquire()
-        try:
-            self.db[username] = valueStr
-            if self.filename:
-                self.db.sync()
-        finally:
-            self.lock.release()
-
-    def __delitem__(self, username):
-        if self.db == None:
-            raise AssertionError("DB not open")
-
-        self.lock.acquire()
-        try:
-            del(self.db[username])
-            if self.filename:
-                self.db.sync()
-        finally:
-            self.lock.release()
-
-    def __contains__(self, username):
-        """Check if the database contains the specified username.
-
-        @type username: str
-        @param username: The username to check for.
-
-        @rtype: bool
-        @return: True if the database contains the username, False
-        otherwise.
-
-        """
-        if self.db == None:
-            raise AssertionError("DB not open")
-
-        self.lock.acquire()
-        try:
-            return self.db.has_key(username)
-        finally:
-            self.lock.release()
-
-    def check(self, username, param):
-        value = self.__getitem__(username)
-        return self._checkItem(value, username, param)
-
-    def keys(self):
-        """Return a list of usernames in the database.
-
-        @rtype: list
-        @return: The usernames in the database.
-        """
-        if self.db == None:
-            raise AssertionError("DB not open")
-
-        self.lock.acquire()
-        try:
-            usernames = self.db.keys()
-        finally:
-            self.lock.release()
-        usernames = [u for u in usernames if not u.startswith("--Reserved--")]
-        return usernames
diff --git a/third_party/tlslite/tlslite/checker.py b/third_party/tlslite/tlslite/checker.py
deleted file mode 100644
index 4f2ee82..0000000
--- a/third_party/tlslite/tlslite/checker.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class for post-handshake certificate checking."""
-
-from .x509 import X509
-from .x509certchain import X509CertChain
-from .errors import *
-
-
-class Checker(object):
-    """This class is passed to a handshake function to check the other
-    party's certificate chain.
-
-    If a handshake function completes successfully, but the Checker
-    judges the other party's certificate chain to be missing or
-    inadequate, a subclass of
-    L{tlslite.errors.TLSAuthenticationError} will be raised.
-
-    Currently, the Checker can check an X.509 chain.
-    """
-
-    def __init__(self, 
-                 x509Fingerprint=None,
-                 checkResumedSession=False):
-        """Create a new Checker instance.
-
-        You must pass in one of these argument combinations:
-         - x509Fingerprint
-
-        @type x509Fingerprint: str
-        @param x509Fingerprint: A hex-encoded X.509 end-entity
-        fingerprint which the other party's end-entity certificate must
-        match.
-
-        @type checkResumedSession: bool
-        @param checkResumedSession: If resumed sessions should be
-        checked.  This defaults to False, on the theory that if the
-        session was checked once, we don't need to bother
-        re-checking it.
-        """
-
-        self.x509Fingerprint = x509Fingerprint
-        self.checkResumedSession = checkResumedSession
-
-    def __call__(self, connection):
-        """Check a TLSConnection.
-
-        When a Checker is passed to a handshake function, this will
-        be called at the end of the function.
-
-        @type connection: L{tlslite.tlsconnection.TLSConnection}
-        @param connection: The TLSConnection to examine.
-
-        @raise tlslite.errors.TLSAuthenticationError: If the other
-        party's certificate chain is missing or bad.
-        """
-        if not self.checkResumedSession and connection.resumed:
-            return
-
-        if self.x509Fingerprint:
-            if connection._client:
-                chain = connection.session.serverCertChain
-            else:
-                chain = connection.session.clientCertChain
-
-            if self.x509Fingerprint:
-                if isinstance(chain, X509CertChain):
-                    if self.x509Fingerprint:
-                        if chain.getFingerprint() != self.x509Fingerprint:
-                            raise TLSFingerprintError(\
-                                "X.509 fingerprint mismatch: %s, %s" % \
-                                (chain.getFingerprint(), self.x509Fingerprint))
-                elif chain:
-                    raise TLSAuthenticationTypeError()
-                else:
-                    raise TLSNoAuthenticationError()
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
deleted file mode 100644
index 3f994e7..0000000
--- a/third_party/tlslite/tlslite/constants.py
+++ /dev/null
@@ -1,471 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Google - defining ClientCertificateType
-#   Google (adapted by Sam Rushing) - NPN support
-#   Dimitris Moraitis - Anon ciphersuites
-#   Dave Baggett (Arcode Corporation) - canonicalCipherName
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Constants used in various places."""
-
-class CertificateType:
-    x509 = 0
-    openpgp = 1
-
-class ClientCertificateType:
-    # http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2
-    rsa_sign = 1
-    dss_sign = 2
-    rsa_fixed_dh = 3
-    dss_fixed_dh = 4
-    ecdsa_sign = 64
-    rsa_fixed_ecdh = 65
-    ecdsa_fixed_ecdh = 66
- 
-class HandshakeType:
-    hello_request = 0
-    client_hello = 1
-    server_hello = 2
-    certificate = 11
-    server_key_exchange = 12
-    certificate_request = 13
-    server_hello_done = 14
-    certificate_verify = 15
-    client_key_exchange = 16
-    finished = 20
-    certificate_status = 22
-    next_protocol = 67
-    encrypted_extensions = 203
-
-class ContentType:
-    change_cipher_spec = 20
-    alert = 21
-    handshake = 22
-    application_data = 23
-    all = (20,21,22,23)
-
-class CertificateStatusType:
-    ocsp = 1
-
-class ExtensionType:    # RFC 6066 / 4366
-    server_name = 0     # RFC 6066 / 4366
-    status_request = 5  # RFC 6066 / 4366
-    srp = 12            # RFC 5054
-    cert_type = 9       # RFC 6091
-    signature_algorithms = 13 # RFC 5246
-    alpn = 16           # RFC 7301
-    signed_cert_timestamps = 18  # RFC 6962
-    extended_master_secret = 23  # RFC 7627
-    token_binding = 24           # draft-ietf-tokbind-negotiation
-    supported_versions = 43      # RFC 8446
-    tack = 0xF300
-    supports_npn = 13172
-    channel_id = 30032
-    renegotiation_info = 0xFF01 # RFC 5746
-
-class HashAlgorithm:
-    none = 0
-    md5 = 1
-    sha1 = 2
-    sha224 = 3
-    sha256 = 4
-    sha384 = 5
-
-class SignatureAlgorithm:
-    anonymous = 0
-    rsa = 1
-    dsa = 2
-    ecdsa = 3
-    
-class NameType:
-    host_name = 0
-
-class ECCurveType:
-    explicit_prime = 1
-    explicit_char2 = 2
-    named_curve = 3
-
-class NamedCurve:
-    secp256r1 = 23
-
-class AlertLevel:
-    warning = 1
-    fatal = 2
-
-class AlertDescription:
-    """
-    @cvar bad_record_mac: A TLS record failed to decrypt properly.
-
-    If this occurs during a SRP handshake it most likely
-    indicates a bad password.  It may also indicate an implementation
-    error, or some tampering with the data in transit.
-
-    This alert will be signalled by the server if the SRP password is bad.  It
-    may also be signalled by the server if the SRP username is unknown to the
-    server, but it doesn't wish to reveal that fact.
-
-
-    @cvar handshake_failure: A problem occurred while handshaking.
-
-    This typically indicates a lack of common ciphersuites between client and
-    server, or some other disagreement (about SRP parameters or key sizes,
-    for example).
-
-    @cvar protocol_version: The other party's SSL/TLS version was unacceptable.
-
-    This indicates that the client and server couldn't agree on which version
-    of SSL or TLS to use.
-
-    @cvar user_canceled: The handshake is being cancelled for some reason.
-
-    """
-
-    close_notify = 0
-    unexpected_message = 10
-    bad_record_mac = 20
-    decryption_failed = 21
-    record_overflow = 22
-    decompression_failure = 30
-    handshake_failure = 40
-    no_certificate = 41 #SSLv3
-    bad_certificate = 42
-    unsupported_certificate = 43
-    certificate_revoked = 44
-    certificate_expired = 45
-    certificate_unknown = 46
-    illegal_parameter = 47
-    unknown_ca = 48
-    access_denied = 49
-    decode_error = 50
-    decrypt_error = 51
-    export_restriction = 60
-    protocol_version = 70
-    insufficient_security = 71
-    internal_error = 80
-    inappropriate_fallback = 86
-    user_canceled = 90
-    no_renegotiation = 100
-    unknown_psk_identity = 115
-
-
-class CipherSuite:
-    # Weird pseudo-ciphersuite from RFC 5746
-    # Signals that "secure renegotiation" is supported
-    # We actually don't do any renegotiation, but this
-    # prevents renegotiation attacks
-    TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF
-
-    # draft-ietf-tls-downgrade-scsv-03
-    TLS_FALLBACK_SCSV = 0x5600
-    
-    TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA  = 0xC01A
-    TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D
-    TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020
-
-    TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B
-    TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E
-    TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021
-
-
-    TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A
-    TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F
-    TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035
-    TLS_RSA_WITH_RC4_128_SHA = 0x0005
-    
-    TLS_RSA_WITH_RC4_128_MD5 = 0x0004
-
-    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
-
-    TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034
-    TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A
-
-    TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C
-    TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D
-
-    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
-    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
-
-    TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
-    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
-
-    TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xc011
-    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xc012
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013
-    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014
-    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027
-    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f
-
-    tripleDESSuites = []
-    tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-    tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-    tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
-    tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
-    tripleDESSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
-
-    aes128Suites = []
-    aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
-    aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
-    aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
-    aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
-    aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-    aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-    aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-    aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-    aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
-
-    aes256Suites = []
-    aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
-    aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
-    aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
-    aes256Suites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-    aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-    aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-    aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-    aes256Suites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-
-    aes128GcmSuites = []
-    aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-    aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-    aes128GcmSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-
-    rc4Suites = []
-    rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
-    rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5)
-    rc4Suites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
-    
-    shaSuites = []
-    shaSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-    shaSuites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
-    shaSuites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
-    shaSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-    shaSuites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
-    shaSuites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
-    shaSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
-    shaSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
-    shaSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
-    shaSuites.append(TLS_RSA_WITH_RC4_128_SHA)
-    shaSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
-    shaSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
-    shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-    shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-    shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-    shaSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
-    shaSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
-    shaSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-    shaSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-    
-    sha256Suites = []
-    sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-    sha256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-    sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-    sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-    sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-    sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-    sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
-    sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-
-
-    aeadSuites = aes128GcmSuites
-
-
-    md5Suites = []
-    md5Suites.append(TLS_RSA_WITH_RC4_128_MD5)
-
-    @staticmethod
-    def _filterSuites(suites, settings, version=None):
-        if version is None:
-            version = settings.maxVersion
-        macNames = settings.macNames
-        cipherNames = settings.cipherNames
-        keyExchangeNames = settings.keyExchangeNames
-        macSuites = []
-        if "sha" in macNames:
-            macSuites += CipherSuite.shaSuites
-        if "sha256" in macNames and version >= (3,3):
-            macSuites += CipherSuite.sha256Suites
-        if "md5" in macNames:
-            macSuites += CipherSuite.md5Suites
-        if "aead" in macNames and version >= (3,3):
-            macSuites += CipherSuite.aeadSuites
-
-        cipherSuites = []
-        if "aes128gcm" in cipherNames and version >= (3,3):
-            cipherSuites += CipherSuite.aes128GcmSuites
-        if "aes128" in cipherNames:
-            cipherSuites += CipherSuite.aes128Suites
-        if "aes256" in cipherNames:
-            cipherSuites += CipherSuite.aes256Suites
-        if "3des" in cipherNames:
-            cipherSuites += CipherSuite.tripleDESSuites
-        if "rc4" in cipherNames:
-            cipherSuites += CipherSuite.rc4Suites
-
-        keyExchangeSuites = []
-        if "rsa" in keyExchangeNames:
-            keyExchangeSuites += CipherSuite.certSuites
-        if "dhe_rsa" in keyExchangeNames:
-            keyExchangeSuites += CipherSuite.dheCertSuites
-        if "ecdhe_rsa" in keyExchangeNames:
-            keyExchangeSuites += CipherSuite.ecdheCertSuites
-        if "srp_sha" in keyExchangeNames:
-            keyExchangeSuites += CipherSuite.srpSuites
-        if "srp_sha_rsa" in keyExchangeNames:
-            keyExchangeSuites += CipherSuite.srpCertSuites
-        if "dh_anon" in keyExchangeNames:
-            keyExchangeSuites += CipherSuite.anonSuites
-
-        return [s for s in suites if s in macSuites and
-                s in cipherSuites and s in keyExchangeSuites]
-
-    srpSuites = []
-    srpSuites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
-    srpSuites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
-    srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
-    
-    @staticmethod
-    def getSrpSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.srpSuites, settings, version)
-
-    srpCertSuites = []
-    srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
-    srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
-    srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
-    
-    @staticmethod
-    def getSrpCertSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.srpCertSuites, settings, version)
-
-    srpAllSuites = srpSuites + srpCertSuites
-
-    @staticmethod
-    def getSrpAllSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.srpAllSuites, settings, version)
-
-    certSuites = []
-    certSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
-    certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
-    certSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
-    certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
-    certSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
-    certSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
-    certSuites.append(TLS_RSA_WITH_RC4_128_SHA)
-    certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
-    
-    @staticmethod
-    def getCertSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.certSuites, settings, version)
-
-    dheCertSuites = []
-    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
-    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
-    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
-    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
-    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
-    dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
-
-    @staticmethod
-    def getDheCertSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, version)
-
-    ecdheCertSuites = []
-    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
-    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
-    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)
-    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
-    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA)
-    ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA)
-
-    @staticmethod
-    def getEcdheCertSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.ecdheCertSuites, settings, version)
-
-    certAllSuites = srpCertSuites + certSuites + dheCertSuites + ecdheCertSuites
-
-    anonSuites = []
-    anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
-    anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
-    
-    @staticmethod
-    def getAnonSuites(settings, version=None):
-        return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, version)
-
-    dhAllSuites = dheCertSuites + anonSuites
-    ecdhAllSuites = ecdheCertSuites
-
-    @staticmethod
-    def canonicalCipherName(ciphersuite):
-        "Return the canonical name of the cipher whose number is provided."
-        if ciphersuite in CipherSuite.aes128Suites:
-            return "aes128"
-        elif ciphersuite in CipherSuite.aes256Suites:
-            return "aes256"
-        elif ciphersuite in CipherSuite.rc4Suites:
-            return "rc4"
-        elif ciphersuite in CipherSuite.tripleDESSuites:
-            return "3des"
-        else:
-            return None
-
-    @staticmethod
-    def canonicalMacName(ciphersuite):
-        "Return the canonical name of the MAC whose number is provided."
-        if ciphersuite in CipherSuite.shaSuites:
-            return "sha"
-        elif ciphersuite in CipherSuite.md5Suites:
-            return "md5"
-        else:
-            return None
-
-
-# The following faults are induced as part of testing.  The faultAlerts
-# dictionary describes the allowed alerts that may be triggered by these
-# faults.
-class Fault:
-    badUsername = 101
-    badPassword = 102
-    badA = 103
-    clientSrpFaults = list(range(101,104))
-
-    badVerifyMessage = 601
-    clientCertFaults = list(range(601,602))
-
-    badPremasterPadding = 501
-    shortPremasterSecret = 502
-    clientNoAuthFaults = list(range(501,503))
-
-    badB = 201
-    serverFaults = list(range(201,202))
-
-    badFinished = 300
-    badMAC = 301
-    badPadding = 302
-    genericFaults = list(range(300,303))
-
-    faultAlerts = {\
-        badUsername: (AlertDescription.unknown_psk_identity, \
-                      AlertDescription.bad_record_mac),\
-        badPassword: (AlertDescription.bad_record_mac,),\
-        badA: (AlertDescription.illegal_parameter,),\
-        badPremasterPadding: (AlertDescription.bad_record_mac,),\
-        shortPremasterSecret: (AlertDescription.bad_record_mac,),\
-        badVerifyMessage: (AlertDescription.decrypt_error,),\
-        badFinished: (AlertDescription.decrypt_error,),\
-        badMAC: (AlertDescription.bad_record_mac,),\
-        badPadding: (AlertDescription.bad_record_mac,)
-        }
-
-    faultNames = {\
-        badUsername: "bad username",\
-        badPassword: "bad password",\
-        badA: "bad A",\
-        badPremasterPadding: "bad premaster padding",\
-        shortPremasterSecret: "short premaster secret",\
-        badVerifyMessage: "bad verify message",\
-        badFinished: "bad finished message",\
-        badMAC: "bad MAC",\
-        badPadding: "bad padding"
-        }
diff --git a/third_party/tlslite/tlslite/errors.py b/third_party/tlslite/tlslite/errors.py
deleted file mode 100644
index 001ef33e..0000000
--- a/third_party/tlslite/tlslite/errors.py
+++ /dev/null
@@ -1,173 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Dave Baggett (Arcode Corporation) - Added TLSUnsupportedError.
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Exception classes.
-@sort: TLSError, TLSAbruptCloseError, TLSAlert, TLSLocalAlert, TLSRemoteAlert,
-TLSAuthenticationError, TLSNoAuthenticationError, TLSAuthenticationTypeError,
-TLSFingerprintError, TLSAuthorizationError, TLSValidationError, TLSFaultError,
-TLSUnsupportedError
-"""
-import socket
-
-from .constants import AlertDescription, AlertLevel
-
-class TLSError(Exception):
-    """Base class for all TLS Lite exceptions."""
-    
-    def __str__(self):
-        """"At least print out the Exception time for str(...)."""
-        return repr(self)    
-
-class TLSClosedConnectionError(TLSError, socket.error):
-    """An attempt was made to use the connection after it was closed."""
-    pass
-
-class TLSAbruptCloseError(TLSError):
-    """The socket was closed without a proper TLS shutdown.
-
-    The TLS specification mandates that an alert of some sort
-    must be sent before the underlying socket is closed.  If the socket
-    is closed without this, it could signify that an attacker is trying
-    to truncate the connection.  It could also signify a misbehaving
-    TLS implementation, or a random network failure.
-    """
-    pass
-
-class TLSAlert(TLSError):
-    """A TLS alert has been signalled."""
-    pass
-
-    _descriptionStr = {\
-        AlertDescription.close_notify: "close_notify",\
-        AlertDescription.unexpected_message: "unexpected_message",\
-        AlertDescription.bad_record_mac: "bad_record_mac",\
-        AlertDescription.decryption_failed: "decryption_failed",\
-        AlertDescription.record_overflow: "record_overflow",\
-        AlertDescription.decompression_failure: "decompression_failure",\
-        AlertDescription.handshake_failure: "handshake_failure",\
-        AlertDescription.no_certificate: "no certificate",\
-        AlertDescription.bad_certificate: "bad_certificate",\
-        AlertDescription.unsupported_certificate: "unsupported_certificate",\
-        AlertDescription.certificate_revoked: "certificate_revoked",\
-        AlertDescription.certificate_expired: "certificate_expired",\
-        AlertDescription.certificate_unknown: "certificate_unknown",\
-        AlertDescription.illegal_parameter: "illegal_parameter",\
-        AlertDescription.unknown_ca: "unknown_ca",\
-        AlertDescription.access_denied: "access_denied",\
-        AlertDescription.decode_error: "decode_error",\
-        AlertDescription.decrypt_error: "decrypt_error",\
-        AlertDescription.export_restriction: "export_restriction",\
-        AlertDescription.protocol_version: "protocol_version",\
-        AlertDescription.insufficient_security: "insufficient_security",\
-        AlertDescription.internal_error: "internal_error",\
-        AlertDescription.inappropriate_fallback: "inappropriate_fallback",\
-        AlertDescription.user_canceled: "user_canceled",\
-        AlertDescription.no_renegotiation: "no_renegotiation",\
-        AlertDescription.unknown_psk_identity: "unknown_psk_identity"}
-
-class TLSLocalAlert(TLSAlert):
-    """A TLS alert has been signalled by the local implementation.
-
-    @type description: int
-    @ivar description: Set to one of the constants in
-    L{tlslite.constants.AlertDescription}
-
-    @type level: int
-    @ivar level: Set to one of the constants in
-    L{tlslite.constants.AlertLevel}
-
-    @type message: str
-    @ivar message: Description of what went wrong.
-    """
-    def __init__(self, alert, message=None):
-        self.description = alert.description
-        self.level = alert.level
-        self.message = message
-
-    def __str__(self):
-        alertStr = TLSAlert._descriptionStr.get(self.description)
-        if alertStr == None:
-            alertStr = str(self.description)
-        if self.message:
-            return alertStr + ": " + self.message
-        else:
-            return alertStr
-
-class TLSRemoteAlert(TLSAlert):
-    """A TLS alert has been signalled by the remote implementation.
-
-    @type description: int
-    @ivar description: Set to one of the constants in
-    L{tlslite.constants.AlertDescription}
-
-    @type level: int
-    @ivar level: Set to one of the constants in
-    L{tlslite.constants.AlertLevel}
-    """
-    def __init__(self, alert):
-        self.description = alert.description
-        self.level = alert.level
-
-    def __str__(self):
-        alertStr = TLSAlert._descriptionStr.get(self.description)
-        if alertStr == None:
-            alertStr = str(self.description)
-        return alertStr
-
-class TLSAuthenticationError(TLSError):
-    """The handshake succeeded, but the other party's authentication
-    was inadequate.
-
-    This exception will only be raised when a
-    L{tlslite.Checker.Checker} has been passed to a handshake function.
-    The Checker will be invoked once the handshake completes, and if
-    the Checker objects to how the other party authenticated, a
-    subclass of this exception will be raised.
-    """
-    pass
-
-class TLSNoAuthenticationError(TLSAuthenticationError):
-    """The Checker was expecting the other party to authenticate with a
-    certificate chain, but this did not occur."""
-    pass
-
-class TLSAuthenticationTypeError(TLSAuthenticationError):
-    """The Checker was expecting the other party to authenticate with a
-    different type of certificate chain."""
-    pass
-
-class TLSFingerprintError(TLSAuthenticationError):
-    """The Checker was expecting the other party to authenticate with a
-    certificate chain that matches a different fingerprint."""
-    pass
-
-class TLSAuthorizationError(TLSAuthenticationError):
-    """The Checker was expecting the other party to authenticate with a
-    certificate chain that has a different authorization."""
-    pass
-
-class TLSValidationError(TLSAuthenticationError):
-    """The Checker has determined that the other party's certificate
-    chain is invalid."""
-    def __init__(self, msg, info=None):
-        # Include a dict containing info about this validation failure
-        TLSAuthenticationError.__init__(self, msg)
-        self.info = info
-
-class TLSFaultError(TLSError):
-    """The other party responded incorrectly to an induced fault.
-
-    This exception will only occur during fault testing, when a
-    TLSConnection's fault variable is set to induce some sort of
-    faulty behavior, and the other party doesn't respond appropriately.
-    """
-    pass
-
-
-class TLSUnsupportedError(TLSError):
-    """The implementation doesn't support the requested (or required)
-    capabilities."""
-    pass
diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
deleted file mode 100644
index a647af5..0000000
--- a/third_party/tlslite/tlslite/handshakesettings.py
+++ /dev/null
@@ -1,252 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Dave Baggett (Arcode Corporation) - cleanup handling of constants
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class for setting handshake parameters."""
-
-from .constants import CertificateType
-from .utils import cryptomath
-from .utils import cipherfactory
-
-CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"]
-MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default.
-ALL_MAC_NAMES = MAC_NAMES + ["md5"]
-KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
-CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
-CERTIFICATE_TYPES = ["x509"]
-TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"]
-
-class HandshakeSettings(object):
-    """This class encapsulates various parameters that can be used with
-    a TLS handshake.
-    @sort: minKeySize, maxKeySize, cipherNames, macNames, certificateTypes,
-    minVersion, maxVersion
-
-    @type minKeySize: int
-    @ivar minKeySize: The minimum bit length for asymmetric keys.
-
-    If the other party tries to use SRP, RSA, or Diffie-Hellman
-    parameters smaller than this length, an alert will be
-    signalled.  The default is 1023.
-
-    @type maxKeySize: int
-    @ivar maxKeySize: The maximum bit length for asymmetric keys.
-
-    If the other party tries to use SRP, RSA, or Diffie-Hellman
-    parameters larger than this length, an alert will be signalled.
-    The default is 8193.
-
-    @type cipherNames: list
-    @ivar cipherNames: The allowed ciphers.
-
-    The allowed values in this list are 'aes256', 'aes128', '3des', and
-    'rc4'.  If these settings are used with a client handshake, they
-    determine the order of the ciphersuites offered in the ClientHello
-    message.
-
-    If these settings are used with a server handshake, the server will
-    choose whichever ciphersuite matches the earliest entry in this
-    list.
-
-    NOTE:  If '3des' is used in this list, but TLS Lite can't find an
-    add-on library that supports 3DES, then '3des' will be silently
-    removed.
-
-    The default value is ['rc4', 'aes256', 'aes128', '3des'].
-
-    @type macNames: list
-    @ivar macNames: The allowed MAC algorithms.
-    
-    The allowed values in this list are 'sha' and 'md5'.
-    
-    The default value is ['sha'].
-
-
-    @type certificateTypes: list
-    @ivar certificateTypes: The allowed certificate types.
-
-    The only allowed certificate type is 'x509'.  This list is only used with a
-    client handshake.  The client will advertise to the server which certificate
-    types are supported, and will check that the server uses one of the
-    appropriate types.
-
-
-    @type minVersion: tuple
-    @ivar minVersion: The minimum allowed SSL/TLS version.
-
-    This variable can be set to (3,0) for SSL 3.0, (3,1) for TLS 1.0, (3,2) for
-    TLS 1.1, or (3,3) for TLS 1.2.  If the other party wishes to use a lower
-    version, a protocol_version alert will be signalled.  The default is (3,1).
-
-    @type maxVersion: tuple
-    @ivar maxVersion: The maximum allowed SSL/TLS version.
-
-    This variable can be set to (3,0) for SSL 3.0, (3,1) for TLS 1.0, (3,2) for
-    TLS 1.1, or (3,3) for TLS 1.2.  If the other party wishes to use a higher
-    version, a protocol_version alert will be signalled.  The default is (3,3).
-    (WARNING: Some servers may (improperly) reject clients which offer support
-    for TLS 1.1.  In this case, try lowering maxVersion to (3,1)).
-
-    @type tlsIntolerant: tuple
-    @ivar tlsIntolerant: The TLS ClientHello version which the server
-    simulates intolerance of.
-
-    If tlsIntolerant is not None, the server will simulate TLS version
-    intolerance by aborting the handshake in response to all TLS versions
-    tlsIntolerant or higher.
-
-    @type tlsIntoleranceType: str
-    @ivar tlsIntoleranceType: How the server should react when simulating TLS
-    intolerance.
-
-    The allowed values are "alert" (return a fatal handshake_failure alert),
-    "close" (abruptly close the connection), and "reset" (send a TCP reset).
-    
-    @type useExperimentalTackExtension: bool
-    @ivar useExperimentalTackExtension: Whether to enabled TACK support.
-
-    @type alertAfterHandshake: bool
-    @ivar alertAfterHandshake: If true, the server will send a fatal
-    alert immediately after the handshake completes.
-
-    @type enableChannelID: bool
-    @ivar enableChannelID: If true, the server supports channel ID.
-
-    @type enableExtendedMasterSecret: bool
-    @ivar enableExtendedMasterSecret: If true, the server supports the extended
-    master secret TLS extension and will negotiated it with supporting clients.
-
-    @type supportedTokenBindingParams: list
-    @ivar supportedTokenBindingParams: A list of token binding parameters that
-    the server supports when negotiating token binding. List values are integers
-    corresponding to the TokenBindingKeyParameters enum in the Token Binding
-    Negotiation spec (draft-ietf-tokbind-negotiation-00). Values are in server's
-    preference order, with most preferred params first.
-
-    @type simulateTLS13Downgrade: bool
-    @ivar simulateTLS13Downgrade: If true, the server will simulate a TLS 1.3
-    to TLS 1.2 downgrade in the ServerHello random.
-
-    @type simulateTLS12Downgrade: bool
-    @ivar simulateTLS12Downgrade: If true, the server will simulate a TLS 1.2
-    to TLS 1.1 downgrade in the ServerHello random.
-
-    Note that TACK support is not standardized by IETF and uses a temporary
-    TLS Extension number, so should NOT be used in production software.
-
-    @type alpnProtos: list of strings.
-    @param alpnProtos: A list of supported upper layer protocols to use in the
-    Application-Layer Protocol Negotiation Extension (RFC 7301).  For the
-    client, the order does not matter.  For the server, the list is in
-    decreasing order of preference.
-    """
-    def __init__(self):
-        self.minKeySize = 1023
-        self.maxKeySize = 8193
-        self.cipherNames = CIPHER_NAMES
-        self.macNames = MAC_NAMES
-        self.keyExchangeNames = KEY_EXCHANGE_NAMES
-        self.cipherImplementations = CIPHER_IMPLEMENTATIONS
-        self.certificateTypes = CERTIFICATE_TYPES
-        self.minVersion = (3,1)
-        self.maxVersion = (3,3)
-        self.tlsIntolerant = None
-        self.tlsIntoleranceType = 'alert'
-        self.useExperimentalTackExtension = False
-        self.alertAfterHandshake = False
-        self.enableChannelID = True
-        self.enableExtendedMasterSecret = True
-        self.supportedTokenBindingParams = []
-        self.alpnProtos = None
-        self.simulateTLS13Downgrade = False
-        self.simulateTLS12Downgrade = False
-
-    # Validates the min/max fields, and certificateTypes
-    # Filters out unsupported cipherNames and cipherImplementations
-    def _filter(self):
-        other = HandshakeSettings()
-        other.minKeySize = self.minKeySize
-        other.maxKeySize = self.maxKeySize
-        other.cipherNames = self.cipherNames
-        other.macNames = self.macNames
-        other.keyExchangeNames = self.keyExchangeNames
-        other.cipherImplementations = self.cipherImplementations
-        other.certificateTypes = self.certificateTypes
-        other.minVersion = self.minVersion
-        other.maxVersion = self.maxVersion
-        other.tlsIntolerant = self.tlsIntolerant
-        other.tlsIntoleranceType = self.tlsIntoleranceType
-        other.alertAfterHandshake = self.alertAfterHandshake
-        other.enableChannelID = self.enableChannelID
-        other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
-        other.supportedTokenBindingParams = self.supportedTokenBindingParams
-        other.alpnProtos = self.alpnProtos;
-        other.simulateTLS13Downgrade = self.simulateTLS13Downgrade
-        other.simulateTLS12Downgrade = self.simulateTLS12Downgrade
-
-        if not cipherfactory.tripleDESPresent:
-            other.cipherNames = [e for e in self.cipherNames if e != "3des"]
-        if len(other.cipherNames)==0:
-            raise ValueError("No supported ciphers")
-        if len(other.certificateTypes)==0:
-            raise ValueError("No supported certificate types")
-
-        if not cryptomath.m2cryptoLoaded:
-            other.cipherImplementations = \
-                [e for e in other.cipherImplementations if e != "openssl"]
-        if not cryptomath.pycryptoLoaded:
-            other.cipherImplementations = \
-                [e for e in other.cipherImplementations if e != "pycrypto"]
-        if len(other.cipherImplementations)==0:
-            raise ValueError("No supported cipher implementations")
-
-        if other.minKeySize<512:
-            raise ValueError("minKeySize too small")
-        if other.minKeySize>16384:
-            raise ValueError("minKeySize too large")
-        if other.maxKeySize<512:
-            raise ValueError("maxKeySize too small")
-        if other.maxKeySize>16384:
-            raise ValueError("maxKeySize too large")
-        for s in other.cipherNames:
-            if s not in CIPHER_NAMES:
-                raise ValueError("Unknown cipher name: '%s'" % s)
-        for s in other.macNames:
-            if s not in ALL_MAC_NAMES:
-                raise ValueError("Unknown MAC name: '%s'" % s)
-        for s in other.keyExchangeNames:
-            if s not in KEY_EXCHANGE_NAMES:
-                raise ValueError("Unknown key exchange name: '%s'" % s)
-        for s in other.cipherImplementations:
-            if s not in CIPHER_IMPLEMENTATIONS:
-                raise ValueError("Unknown cipher implementation: '%s'" % s)
-        for s in other.certificateTypes:
-            if s not in CERTIFICATE_TYPES:
-                raise ValueError("Unknown certificate type: '%s'" % s)
-
-        if other.tlsIntoleranceType not in TLS_INTOLERANCE_TYPES:
-            raise ValueError(
-                "Unknown TLS intolerance type: '%s'" % other.tlsIntoleranceType)
-
-        if other.minVersion > other.maxVersion:
-            raise ValueError("Versions set incorrectly")
-
-        if not other.minVersion in ((3,0), (3,1), (3,2), (3,3)):
-            raise ValueError("minVersion set incorrectly")
-
-        if not other.maxVersion in ((3,0), (3,1), (3,2), (3,3)):
-            raise ValueError("maxVersion set incorrectly")
-
-        return other
-
-    def _getCertificateTypes(self):
-        l = []
-        for ct in self.certificateTypes:
-            if ct == "x509":
-                l.append(CertificateType.x509)
-            else:
-                raise AssertionError()
-        return l
diff --git a/third_party/tlslite/tlslite/integration/__init__.py b/third_party/tlslite/tlslite/integration/__init__.py
deleted file mode 100644
index 663dfb6..0000000
--- a/third_party/tlslite/tlslite/integration/__init__.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Classes for integrating TLS Lite with other packages."""
-
-__all__ = ["asyncstatemachine",
-           "httptlsconnection",
-           "pop3_tls",
-           "imap4_tls",
-           "smtp_tls",
-           "xmlrpctransport",
-           "tlssocketservermixin",
-           "tlsasyncdispatchermixin"]
diff --git a/third_party/tlslite/tlslite/integration/asyncstatemachine.py b/third_party/tlslite/tlslite/integration/asyncstatemachine.py
deleted file mode 100644
index 9faf84f9..0000000
--- a/third_party/tlslite/tlslite/integration/asyncstatemachine.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""
-A state machine for using TLS Lite with asynchronous I/O.
-"""
-
-class AsyncStateMachine:
-    """
-    This is an abstract class that's used to integrate TLS Lite with
-    asyncore and Twisted.
-
-    This class signals wantsReadsEvent() and wantsWriteEvent().  When
-    the underlying socket has become readable or writeable, the event
-    should be passed to this class by calling inReadEvent() or
-    inWriteEvent().  This class will then try to read or write through
-    the socket, and will update its state appropriately.
-
-    This class will forward higher-level events to its subclass.  For
-    example, when a complete TLS record has been received,
-    outReadEvent() will be called with the decrypted data.
-    """
-
-    def __init__(self):
-        self._clear()
-
-    def _clear(self):
-        #These store the various asynchronous operations (i.e.
-        #generators).  Only one of them, at most, is ever active at a
-        #time.
-        self.handshaker = None
-        self.closer = None
-        self.reader = None
-        self.writer = None
-
-        #This stores the result from the last call to the
-        #currently active operation.  If 0 it indicates that the
-        #operation wants to read, if 1 it indicates that the
-        #operation wants to write.  If None, there is no active
-        #operation.
-        self.result = None
-
-    def _checkAssert(self, maxActive=1):
-        #This checks that only one operation, at most, is
-        #active, and that self.result is set appropriately.
-        activeOps = 0
-        if self.handshaker:
-            activeOps += 1
-        if self.closer:
-            activeOps += 1
-        if self.reader:
-            activeOps += 1
-        if self.writer:
-            activeOps += 1
-
-        if self.result == None:
-            if activeOps != 0:
-                raise AssertionError()
-        elif self.result in (0,1):
-            if activeOps != 1:
-                raise AssertionError()
-        else:
-            raise AssertionError()
-        if activeOps > maxActive:
-            raise AssertionError()
-
-    def wantsReadEvent(self):
-        """If the state machine wants to read.
-
-        If an operation is active, this returns whether or not the
-        operation wants to read from the socket.  If an operation is
-        not active, this returns None.
-
-        @rtype: bool or None
-        @return: If the state machine wants to read.
-        """
-        if self.result != None:
-            return self.result == 0
-        return None
-
-    def wantsWriteEvent(self):
-        """If the state machine wants to write.
-
-        If an operation is active, this returns whether or not the
-        operation wants to write to the socket.  If an operation is
-        not active, this returns None.
-
-        @rtype: bool or None
-        @return: If the state machine wants to write.
-        """
-        if self.result != None:
-            return self.result == 1
-        return None
-
-    def outConnectEvent(self):
-        """Called when a handshake operation completes.
-
-        May be overridden in subclass.
-        """
-        pass
-
-    def outCloseEvent(self):
-        """Called when a close operation completes.
-
-        May be overridden in subclass.
-        """
-        pass
-
-    def outReadEvent(self, readBuffer):
-        """Called when a read operation completes.
-
-        May be overridden in subclass."""
-        pass
-
-    def outWriteEvent(self):
-        """Called when a write operation completes.
-
-        May be overridden in subclass."""
-        pass
-
-    def inReadEvent(self):
-        """Tell the state machine it can read from the socket."""
-        try:
-            self._checkAssert()
-            if self.handshaker:
-                self._doHandshakeOp()
-            elif self.closer:
-                self._doCloseOp()
-            elif self.reader:
-                self._doReadOp()
-            elif self.writer:
-                self._doWriteOp()
-            else:
-                self.reader = self.tlsConnection.readAsync(16384)
-                self._doReadOp()
-        except:
-            self._clear()
-            raise
-
-    def inWriteEvent(self):
-        """Tell the state machine it can write to the socket."""
-        try:
-            self._checkAssert()
-            if self.handshaker:
-                self._doHandshakeOp()
-            elif self.closer:
-                self._doCloseOp()
-            elif self.reader:
-                self._doReadOp()
-            elif self.writer:
-                self._doWriteOp()
-            else:
-                self.outWriteEvent()
-        except:
-            self._clear()
-            raise
-
-    def _doHandshakeOp(self):
-        try:
-            self.result = self.handshaker.next()
-        except StopIteration:
-            self.handshaker = None
-            self.result = None
-            self.outConnectEvent()
-
-    def _doCloseOp(self):
-        try:
-            self.result = self.closer.next()
-        except StopIteration:
-            self.closer = None
-            self.result = None
-            self.outCloseEvent()
-
-    def _doReadOp(self):
-        self.result = self.reader.next()
-        if not self.result in (0,1):
-            readBuffer = self.result
-            self.reader = None
-            self.result = None
-            self.outReadEvent(readBuffer)
-
-    def _doWriteOp(self):
-        try:
-            self.result = self.writer.next()
-        except StopIteration:
-            self.writer = None
-            self.result = None
-
-    def setHandshakeOp(self, handshaker):
-        """Start a handshake operation.
-
-        @type handshaker: generator
-        @param handshaker: A generator created by using one of the
-        asynchronous handshake functions (i.e. handshakeServerAsync, or
-        handshakeClientxxx(..., is_async=True).
-        """
-        try:
-            self._checkAssert(0)
-            self.handshaker = handshaker
-            self._doHandshakeOp()
-        except:
-            self._clear()
-            raise
-
-    def setServerHandshakeOp(self, **args):
-        """Start a handshake operation.
-
-        The arguments passed to this function will be forwarded to
-        L{tlslite.tlsconnection.TLSConnection.handshakeServerAsync}.
-        """
-        handshaker = self.tlsConnection.handshakeServerAsync(**args)
-        self.setHandshakeOp(handshaker)
-
-    def setCloseOp(self):
-        """Start a close operation.
-        """
-        try:
-            self._checkAssert(0)
-            self.closer = self.tlsConnection.closeAsync()
-            self._doCloseOp()
-        except:
-            self._clear()
-            raise
-
-    def setWriteOp(self, writeBuffer):
-        """Start a write operation.
-
-        @type writeBuffer: str
-        @param writeBuffer: The string to transmit.
-        """
-        try:
-            self._checkAssert(0)
-            self.writer = self.tlsConnection.writeAsync(writeBuffer)
-            self._doWriteOp()
-        except:
-            self._clear()
-            raise
-
diff --git a/third_party/tlslite/tlslite/integration/clienthelper.py b/third_party/tlslite/tlslite/integration/clienthelper.py
deleted file mode 100644
index 62e5961..0000000
--- a/third_party/tlslite/tlslite/integration/clienthelper.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Dimitris Moraitis - Anon ciphersuites
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""
-A helper class for using TLS Lite with stdlib clients
-(httplib, xmlrpclib, imaplib, poplib).
-"""
-
-from tlslite.checker import Checker
-
-class ClientHelper(object):
-    """This is a helper class used to integrate TLS Lite with various
-    TLS clients (e.g. poplib, smtplib, httplib, etc.)"""
-
-    def __init__(self,
-              username=None, password=None,
-              certChain=None, privateKey=None,
-              checker=None,
-              settings = None, 
-              anon = False):
-        """
-        For client authentication, use one of these argument
-        combinations:
-         - username, password (SRP)
-         - certChain, privateKey (certificate)
-
-        For server authentication, you can either rely on the
-        implicit mutual authentication performed by SRP,
-        or you can do certificate-based server
-        authentication with one of these argument combinations:
-         - x509Fingerprint
-
-        Certificate-based server authentication is compatible with
-        SRP or certificate-based client authentication.
-
-        The constructor does not perform the TLS handshake itself, but
-        simply stores these arguments for later.  The handshake is
-        performed only when this class needs to connect with the
-        server.  Then you should be prepared to handle TLS-specific
-        exceptions.  See the client handshake functions in
-        L{tlslite.TLSConnection.TLSConnection} for details on which
-        exceptions might be raised.
-
-        @type username: str
-        @param username: SRP username.  Requires the
-        'password' argument.
-
-        @type password: str
-        @param password: SRP password for mutual authentication.
-        Requires the 'username' argument.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: Certificate chain for client authentication.
-        Requires the 'privateKey' argument.  Excludes the SRP arguments.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: Private key for client authentication.
-        Requires the 'certChain' argument.  Excludes the SRP arguments.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: Callable object called after handshaking to 
-        evaluate the connection and raise an Exception if necessary.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-        """
-
-        self.username = None
-        self.password = None
-        self.certChain = None
-        self.privateKey = None
-        self.checker = None
-        self.anon = anon
-
-        #SRP Authentication
-        if username and password and not \
-                (certChain or privateKey):
-            self.username = username
-            self.password = password
-
-        #Certificate Chain Authentication
-        elif certChain and privateKey and not \
-                (username or password):
-            self.certChain = certChain
-            self.privateKey = privateKey
-
-        #No Authentication
-        elif not password and not username and not \
-                certChain and not privateKey:
-            pass
-
-        else:
-            raise ValueError("Bad parameters")
-
-        self.checker = checker
-        self.settings = settings
-
-        self.tlsSession = None
-
-    def _handshake(self, tlsConnection):
-        if self.username and self.password:
-            tlsConnection.handshakeClientSRP(username=self.username,
-                                             password=self.password,
-                                             checker=self.checker,
-                                             settings=self.settings,
-                                             session=self.tlsSession)
-        elif self.anon:
-            tlsConnection.handshakeClientAnonymous(session=self.tlsSession,
-                                                settings=self.settings,
-                                                checker=self.checker)
-        else:
-            tlsConnection.handshakeClientCert(certChain=self.certChain,
-                                              privateKey=self.privateKey,
-                                              checker=self.checker,
-                                              settings=self.settings,
-                                              session=self.tlsSession)
-        self.tlsSession = tlsConnection.session
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/integration/httptlsconnection.py b/third_party/tlslite/tlslite/integration/httptlsconnection.py
deleted file mode 100644
index d8a002f..0000000
--- a/third_party/tlslite/tlslite/integration/httptlsconnection.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Kees Bos - Added ignoreAbruptClose parameter
-#   Dimitris Moraitis - Anon ciphersuites
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite + httplib."""
-
-import socket
-try:
-    import httplib
-except ImportError:
-    # Python 3
-    from http import client as httplib
-from tlslite.tlsconnection import TLSConnection
-from tlslite.integration.clienthelper import ClientHelper
-
-
-class HTTPTLSConnection(httplib.HTTPConnection, ClientHelper):
-    """This class extends L{httplib.HTTPConnection} to support TLS."""
-
-    def __init__(self, host, port=None, strict=None, 
-                timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
-                source_address=None,
-                username=None, password=None,
-                certChain=None, privateKey=None,
-                checker=None,
-                settings=None,
-                ignoreAbruptClose=False, 
-                anon=False):
-        """Create a new HTTPTLSConnection.
-
-        For client authentication, use one of these argument
-        combinations:
-         - username, password (SRP)
-         - certChain, privateKey (certificate)
-
-        For server authentication, you can either rely on the
-        implicit mutual authentication performed by SRP
-        or you can do certificate-based server
-        authentication with one of these argument combinations:
-         - x509Fingerprint
-
-        Certificate-based server authentication is compatible with
-        SRP or certificate-based client authentication.
-
-        The constructor does not perform the TLS handshake itself, but
-        simply stores these arguments for later.  The handshake is
-        performed only when this class needs to connect with the
-        server.  Thus you should be prepared to handle TLS-specific
-        exceptions when calling methods inherited from
-        L{httplib.HTTPConnection} such as request(), connect(), and
-        send().  See the client handshake functions in
-        L{tlslite.TLSConnection.TLSConnection} for details on which
-        exceptions might be raised.
-
-        @type host: str
-        @param host: Server to connect to.
-
-        @type port: int
-        @param port: Port to connect to.
-
-        @type username: str
-        @param username: SRP username.  Requires the
-        'password' argument.
-
-        @type password: str
-        @param password: SRP password for mutual authentication.
-        Requires the 'username' argument.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain} or
-        @param certChain: Certificate chain for client authentication.
-        Requires the 'privateKey' argument.  Excludes the SRP arguments.
-        
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: Private key for client authentication.
-        Requires the 'certChain' argument.  Excludes the SRP arguments. 
-        
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: Callable object called after handshaking to 
-        evaluate the connection and raise an Exception if necessary.          
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-
-        @type ignoreAbruptClose: bool
-        @param ignoreAbruptClose: ignore the TLSAbruptCloseError on 
-        unexpected hangup.
-        """
-        if source_address:
-            httplib.HTTPConnection.__init__(self, host, port, strict,
-                                            timeout, source_address)
-        if not source_address:
-            httplib.HTTPConnection.__init__(self, host, port, strict,
-                                            timeout)
-        self.ignoreAbruptClose = ignoreAbruptClose
-        ClientHelper.__init__(self,
-                 username, password, 
-                 certChain, privateKey,
-                 checker,
-                 settings, 
-                 anon)
-
-    def connect(self):
-        httplib.HTTPConnection.connect(self)
-        self.sock = TLSConnection(self.sock)
-        self.sock.ignoreAbruptClose = self.ignoreAbruptClose
-        ClientHelper._handshake(self, self.sock)
diff --git a/third_party/tlslite/tlslite/integration/imap4_tls.py b/third_party/tlslite/tlslite/integration/imap4_tls.py
deleted file mode 100644
index 4703a31..0000000
--- a/third_party/tlslite/tlslite/integration/imap4_tls.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite + imaplib."""
-
-import socket
-from imaplib import IMAP4
-from tlslite.tlsconnection import TLSConnection
-from tlslite.integration.clienthelper import ClientHelper
-
-# IMAP TLS PORT
-IMAP4_TLS_PORT = 993
-
-class IMAP4_TLS(IMAP4, ClientHelper):
-    """This class extends L{imaplib.IMAP4} with TLS support."""
-
-    def __init__(self, host = '', port = IMAP4_TLS_PORT,
-                 username=None, password=None,
-                 certChain=None, privateKey=None,
-                 checker=None,
-                 settings=None):
-        """Create a new IMAP4_TLS.
-
-        For client authentication, use one of these argument
-        combinations:
-         - username, password (SRP)
-         - certChain, privateKey (certificate)
-
-        For server authentication, you can either rely on the
-        implicit mutual authentication performed by SRP
-        or you can do certificate-based server
-        authentication with one of these argument combinations:
-         - x509Fingerprint
-
-        Certificate-based server authentication is compatible with
-        SRP or certificate-based client authentication.
-
-        The caller should be prepared to handle TLS-specific
-        exceptions.  See the client handshake functions in
-        L{tlslite.TLSConnection.TLSConnection} for details on which
-        exceptions might be raised.
-
-        @type host: str
-        @param host: Server to connect to.
-
-        @type port: int
-        @param port: Port to connect to.
-
-        @type username: str
-        @param username: SRP username.  Requires the
-        'password' argument.
-
-        @type password: str
-        @param password: SRP password for mutual authentication.
-        Requires the 'username' argument.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: Certificate chain for client authentication.
-        Requires the 'privateKey' argument.  Excludes the SRP arguments.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: Private key for client authentication.
-        Requires the 'certChain' argument.  Excludes the SRP arguments.
-        
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: Callable object called after handshaking to 
-        evaluate the connection and raise an Exception if necessary.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-        """
-
-        ClientHelper.__init__(self,
-                 username, password,
-                 certChain, privateKey,
-                 checker,
-                 settings)
-
-        IMAP4.__init__(self, host, port)
-
-
-    def open(self, host = '', port = IMAP4_TLS_PORT):
-        """Setup connection to remote server on "host:port".
-
-        This connection will be used by the routines:
-        read, readline, send, shutdown.
-        """
-        self.host = host
-        self.port = port
-        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.sock.connect((host, port))
-        self.sock = TLSConnection(self.sock)
-        ClientHelper._handshake(self, self.sock)
-        self.file = self.sock.makefile('rb')
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/integration/pop3_tls.py b/third_party/tlslite/tlslite/integration/pop3_tls.py
deleted file mode 100644
index 64f6124e..0000000
--- a/third_party/tlslite/tlslite/integration/pop3_tls.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite + poplib."""
-
-import socket
-from poplib import POP3, POP3_SSL_PORT
-from tlslite.tlsconnection import TLSConnection
-from tlslite.integration.clienthelper import ClientHelper
-
-class POP3_TLS(POP3, ClientHelper):
-    """This class extends L{poplib.POP3} with TLS support."""
-
-    def __init__(self, host, port = POP3_SSL_PORT,
-                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
-                 username=None, password=None,
-                 certChain=None, privateKey=None,
-                 checker=None,
-                 settings=None):
-        """Create a new POP3_TLS.
-
-        For client authentication, use one of these argument
-        combinations:
-         - username, password (SRP)
-         - certChain, privateKey (certificate)
-
-        For server authentication, you can either rely on the
-        implicit mutual authentication performed by SRP or
-        you can do certificate-based server
-        authentication with one of these argument combinations:
-         - x509Fingerprint
-
-        Certificate-based server authentication is compatible with
-        SRP or certificate-based client authentication.
-
-        The caller should be prepared to handle TLS-specific
-        exceptions.  See the client handshake functions in
-        L{tlslite.TLSConnection.TLSConnection} for details on which
-        exceptions might be raised.
-
-        @type host: str
-        @param host: Server to connect to.
-
-        @type port: int
-        @param port: Port to connect to.
-
-        @type username: str
-        @param username: SRP username.
-        
-        @type password: str
-        @param password: SRP password for mutual authentication.
-        Requires the 'username' argument.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: Certificate chain for client authentication.
-        Requires the 'privateKey' argument.  Excludes the SRP argument.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: Private key for client authentication.
-        Requires the 'certChain' argument.  Excludes the SRP argument.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: Callable object called after handshaking to 
-        evaluate the connection and raise an Exception if necessary.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-        """
-        self.host = host
-        self.port = port
-        sock = socket.create_connection((host, port), timeout)
-        ClientHelper.__init__(self,
-                 username, password,
-                 certChain, privateKey,
-                 checker,
-                 settings)
-        connection = TLSConnection(sock) 
-        ClientHelper._handshake(self, connection)
-        self.sock = connection
-        self.file = self.sock.makefile('rb')
-        self._debugging = 0
-        self.welcome = self._getresp()
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/integration/smtp_tls.py b/third_party/tlslite/tlslite/integration/smtp_tls.py
deleted file mode 100644
index d4214732..0000000
--- a/third_party/tlslite/tlslite/integration/smtp_tls.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite + smtplib."""
-
-from smtplib import SMTP
-from tlslite.tlsconnection import TLSConnection
-from tlslite.integration.clienthelper import ClientHelper
-
-class SMTP_TLS(SMTP):
-    """This class extends L{smtplib.SMTP} with TLS support."""
-
-    def starttls(self,
-                 username=None, password=None,
-                 certChain=None, privateKey=None,
-                 checker=None,
-                 settings=None):
-        """Puts the connection to the SMTP server into TLS mode.
-
-        If the server supports TLS, this will encrypt the rest of the SMTP
-        session.
-
-        For client authentication, use one of these argument
-        combinations:
-         - username, password (SRP)
-         - certChain, privateKey (certificate)
-
-        For server authentication, you can either rely on the
-        implicit mutual authentication performed by SRP or
-        you can do certificate-based server
-        authentication with one of these argument combinations:
-         - x509Fingerprint
-
-        Certificate-based server authentication is compatible with
-        SRP or certificate-based client authentication.
-
-        The caller should be prepared to handle TLS-specific
-        exceptions.  See the client handshake functions in
-        L{tlslite.TLSConnection.TLSConnection} for details on which
-        exceptions might be raised.
-
-        @type username: str
-        @param username: SRP username.  Requires the
-        'password' argument.
-
-        @type password: str
-        @param password: SRP password for mutual authentication.
-        Requires the 'username' argument.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: Certificate chain for client authentication.
-        Requires the 'privateKey' argument.  Excludes the SRP arguments.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: Private key for client authentication.
-        Requires the 'certChain' argument.  Excludes the SRP arguments.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: Callable object called after handshaking to 
-        evaluate the connection and raise an Exception if necessary.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-        """
-        (resp, reply) = self.docmd("STARTTLS")
-        if resp == 220:
-            helper = ClientHelper(
-                     username, password, 
-                     certChain, privateKey,
-                     checker,
-                     settings)
-            conn = TLSConnection(self.sock)
-            helper._handshake(conn)
-            self.sock = conn
-            self.file = conn.makefile('rb')
-        return (resp, reply)
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/integration/tlsasyncdispatchermixin.py b/third_party/tlslite/tlslite/integration/tlsasyncdispatchermixin.py
deleted file mode 100644
index dc32596..0000000
--- a/third_party/tlslite/tlslite/integration/tlsasyncdispatchermixin.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite + asyncore."""
-
-
-import asyncore
-from tlslite.tlsconnection import TLSConnection
-from .asyncstatemachine import AsyncStateMachine
-
-
-class TLSAsyncDispatcherMixIn(AsyncStateMachine):
-    """This class can be "mixed in" with an
-    L{asyncore.dispatcher} to add TLS support.
-
-    This class essentially sits between the dispatcher and the select
-    loop, intercepting events and only calling the dispatcher when
-    applicable.
-
-    In the case of handle_read(), a read operation will be activated,
-    and when it completes, the bytes will be placed in a buffer where
-    the dispatcher can retrieve them by calling recv(), and the
-    dispatcher's handle_read() will be called.
-
-    In the case of handle_write(), the dispatcher's handle_write() will
-    be called, and when it calls send(), a write operation will be
-    activated.
-
-    To use this class, you must combine it with an asyncore.dispatcher,
-    and pass in a handshake operation with setServerHandshakeOp().
-
-    Below is an example of using this class with medusa.  This class is
-    mixed in with http_channel to create http_tls_channel.  Note:
-     1. the mix-in is listed first in the inheritance list
-
-     2. the input buffer size must be at least 16K, otherwise the
-       dispatcher might not read all the bytes from the TLS layer,
-       leaving some bytes in limbo.
-
-     3. IE seems to have a problem receiving a whole HTTP response in a
-     single TLS record, so HTML pages containing '\\r\\n\\r\\n' won't
-     be displayed on IE.
-
-    Add the following text into 'start_medusa.py', in the 'HTTP Server'
-    section::
-
-        from tlslite import *
-        s = open("./serverX509Cert.pem").read()
-        x509 = X509()
-        x509.parse(s)
-        certChain = X509CertChain([x509])
-
-        s = open("./serverX509Key.pem").read()
-        privateKey = parsePEMKey(s, private=True)
-
-        class http_tls_channel(TLSAsyncDispatcherMixIn,
-                               http_server.http_channel):
-            ac_in_buffer_size = 16384
-
-            def __init__ (self, server, conn, addr):
-                http_server.http_channel.__init__(self, server, conn, addr)
-                TLSAsyncDispatcherMixIn.__init__(self, conn)
-                self.tlsConnection.ignoreAbruptClose = True
-                self.setServerHandshakeOp(certChain=certChain,
-                                          privateKey=privateKey)
-
-        hs.channel_class = http_tls_channel
-
-    If the TLS layer raises an exception, the exception will be caught
-    in asyncore.dispatcher, which will call close() on this class.  The
-    TLS layer always closes the TLS connection before raising an
-    exception, so the close operation will complete right away, causing
-    asyncore.dispatcher.close() to be called, which closes the socket
-    and removes this instance from the asyncore loop.
-
-    """
-
-
-    def __init__(self, sock=None):
-        AsyncStateMachine.__init__(self)
-
-        if sock:
-            self.tlsConnection = TLSConnection(sock)
-
-        #Calculate the sibling I'm being mixed in with.
-        #This is necessary since we override functions
-        #like readable(), handle_read(), etc., but we
-        #also want to call the sibling's versions.
-        for cl in self.__class__.__bases__:
-            if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
-                self.siblingClass = cl
-                break
-        else:
-            raise AssertionError()
-
-    def readable(self):
-        result = self.wantsReadEvent()
-        if result != None:
-            return result
-        return self.siblingClass.readable(self)
-
-    def writable(self):
-        result = self.wantsWriteEvent()
-        if result != None:
-            return result
-        return self.siblingClass.writable(self)
-
-    def handle_read(self):
-        self.inReadEvent()
-
-    def handle_write(self):
-        self.inWriteEvent()
-
-    def outConnectEvent(self):
-        self.siblingClass.handle_connect(self)
-
-    def outCloseEvent(self):
-        asyncore.dispatcher.close(self)
-
-    def outReadEvent(self, readBuffer):
-        self.readBuffer = readBuffer
-        self.siblingClass.handle_read(self)
-
-    def outWriteEvent(self):
-        self.siblingClass.handle_write(self)
-
-    def recv(self, bufferSize=16384):
-        if bufferSize < 16384 or self.readBuffer == None:
-            raise AssertionError()
-        returnValue = self.readBuffer
-        self.readBuffer = None
-        return returnValue
-
-    def send(self, writeBuffer):
-        self.setWriteOp(writeBuffer)
-        return len(writeBuffer)
-
-    def close(self):
-        if hasattr(self, "tlsConnection"):
-            self.setCloseOp()
-        else:
-            asyncore.dispatcher.close(self)
diff --git a/third_party/tlslite/tlslite/integration/tlssocketservermixin.py b/third_party/tlslite/tlslite/integration/tlssocketservermixin.py
deleted file mode 100644
index 8e2182f..0000000
--- a/third_party/tlslite/tlslite/integration/tlssocketservermixin.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""TLS Lite + SocketServer."""
-
-from tlslite.tlsconnection import TLSConnection
-
-class TLSSocketServerMixIn:
-    """
-    This class can be mixed in with any L{SocketServer.TCPServer} to
-    add TLS support.
-
-    To use this class, define a new class that inherits from it and
-    some L{SocketServer.TCPServer} (with the mix-in first). Then
-    implement the handshake() method, doing some sort of server
-    handshake on the connection argument.  If the handshake method
-    returns True, the RequestHandler will be triggered.  Below is a
-    complete example of a threaded HTTPS server::
-
-        from SocketServer import *
-        from BaseHTTPServer import *
-        from SimpleHTTPServer import *
-        from tlslite import *
-
-        s = open("./serverX509Cert.pem").read()
-        x509 = X509()
-        x509.parse(s)
-        certChain = X509CertChain([x509])
-
-        s = open("./serverX509Key.pem").read()
-        privateKey = parsePEMKey(s, private=True)
-
-        sessionCache = SessionCache()
-
-        class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn,
-                           HTTPServer):
-          def handshake(self, tlsConnection):
-              try:
-                  tlsConnection.handshakeServer(certChain=certChain,
-                                                privateKey=privateKey,
-                                                sessionCache=sessionCache)
-                  tlsConnection.ignoreAbruptClose = True
-                  return True
-              except TLSError, error:
-                  print "Handshake failure:", str(error)
-                  return False
-
-        httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
-        httpd.serve_forever()
-    """
-
-
-    def finish_request(self, sock, client_address):
-        tlsConnection = TLSConnection(sock)
-        if self.handshake(tlsConnection) == True:
-            self.RequestHandlerClass(tlsConnection, client_address, self)
-            tlsConnection.close()
-
-    #Implement this method to do some form of handshaking.  Return True
-    #if the handshake finishes properly and the request is authorized.
-    def handshake(self, tlsConnection):
-        raise NotImplementedError()
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/integration/xmlrpcserver.py b/third_party/tlslite/tlslite/integration/xmlrpcserver.py
deleted file mode 100644
index c4f40cd9..0000000
--- a/third_party/tlslite/tlslite/integration/xmlrpcserver.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Authors:
-#   Kees Bos
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""xmlrpcserver.py - simple XML RPC server supporting TLS"""
-try:
-    from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
-except ImportError:
-    # Python 3
-    from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
-from .tlssocketservermixin import TLSSocketServerMixIn
-
-
-class TLSXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
-    """XMLRPCRequestHandler using TLS"""
-    
-    # Redefine the setup method (see SocketServer.StreamRequestHandler)
-    def setup(self):
-        self.connection = self.request
-        if getattr(self, 'timeout', None) is not None:
-            # Python 2.7
-            self.connection.settimeout(self.timeout)
-        self.rfile = self.connection.makefile('rb', self.rbufsize)
-        self.wfile = self.connection.makefile('wb', self.wbufsize)
-        
-    def do_POST(self):
-        """Handles the HTTPS POST request."""
-        SimpleXMLRPCRequestHandler.do_POST(self)
-        try:
-            # shut down the connection
-            self.connection.shutdown()
-        except:
-            pass
-
-
-class TLSXMLRPCServer(TLSSocketServerMixIn,
-                      SimpleXMLRPCServer):
-    """Simple XML-RPC server using TLS""" 
-
-    def __init__(self, addr, *args, **kwargs):
-        if not args and not 'requestHandler' in kwargs:
-            kwargs['requestHandler'] = TLSXMLRPCRequestHandler
-        SimpleXMLRPCServer.__init__(self, addr, *args, **kwargs)
-
-
-class MultiPathTLSXMLRPCServer(TLSXMLRPCServer):
-    """Multipath XML-RPC Server using TLS"""
-
-    def __init__(self, addr, *args, **kwargs):
-        TLSXMLRPCServer.__init__(addr, *args, **kwargs)
-        self.dispatchers = {}
-        self.allow_none = allow_none
-        self.encoding = encoding
diff --git a/third_party/tlslite/tlslite/integration/xmlrpctransport.py b/third_party/tlslite/tlslite/integration/xmlrpctransport.py
deleted file mode 100644
index de7fc5a..0000000
--- a/third_party/tlslite/tlslite/integration/xmlrpctransport.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Kees Bos - Fixes for compatibility with different Python versions
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-
-"""TLS Lite + xmlrpclib."""
-
-try:
-    import xmlrpclib
-    import httplib
-except ImportError:
-    # Python 3
-    from xmlrpc import client as xmlrpclib
-    from http import client as httplib
-from tlslite.integration.httptlsconnection import HTTPTLSConnection
-from tlslite.integration.clienthelper import ClientHelper
-import tlslite.errors
-
-
-class XMLRPCTransport(xmlrpclib.Transport, ClientHelper):
-    """Handles an HTTPS transaction to an XML-RPC server."""
-
-    # Pre python 2.7, the make_connection returns a HTTP class
-    transport = xmlrpclib.Transport()
-    conn_class_is_http = not hasattr(transport, '_connection')
-    del(transport)
-
-    def __init__(self, use_datetime=0,
-                 username=None, password=None,
-                 certChain=None, privateKey=None,
-                 checker=None,
-                 settings=None,
-                 ignoreAbruptClose=False):
-        """Create a new XMLRPCTransport.
-
-        An instance of this class can be passed to L{xmlrpclib.ServerProxy}
-        to use TLS with XML-RPC calls::
-
-            from tlslite import XMLRPCTransport
-            from xmlrpclib import ServerProxy
-
-            transport = XMLRPCTransport(user="alice", password="abra123")
-            server = ServerProxy("https://localhost", transport)
-
-        For client authentication, use one of these argument
-        combinations:
-         - username, password (SRP)
-         - certChain, privateKey (certificate)
-
-        For server authentication, you can either rely on the
-        implicit mutual authentication performed by SRP or
-        you can do certificate-based server
-        authentication with one of these argument combinations:
-         - x509Fingerprint
-
-        Certificate-based server authentication is compatible with
-        SRP or certificate-based client authentication.
-
-        The constructor does not perform the TLS handshake itself, but
-        simply stores these arguments for later.  The handshake is
-        performed only when this class needs to connect with the
-        server.  Thus you should be prepared to handle TLS-specific
-        exceptions when calling methods of L{xmlrpclib.ServerProxy}.  See the
-        client handshake functions in
-        L{tlslite.TLSConnection.TLSConnection} for details on which
-        exceptions might be raised.
-
-        @type username: str
-        @param username: SRP username.  Requires the
-        'password' argument.
-
-        @type password: str
-        @param password: SRP password for mutual authentication.
-        Requires the 'username' argument.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: Certificate chain for client authentication.
-        Requires the 'privateKey' argument.  Excludes the SRP arguments.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: Private key for client authentication.
-        Requires the 'certChain' argument.  Excludes the SRP arguments.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: Callable object called after handshaking to 
-        evaluate the connection and raise an Exception if necessary.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-
-        @type ignoreAbruptClose: bool
-        @param ignoreAbruptClose: ignore the TLSAbruptCloseError on 
-        unexpected hangup.
-        """
-
-        # self._connection is new in python 2.7, since we're using it here,
-        # we'll add this ourselves too, just in case we're pre-2.7
-        self._connection = (None, None)
-        xmlrpclib.Transport.__init__(self, use_datetime)
-        self.ignoreAbruptClose = ignoreAbruptClose
-        ClientHelper.__init__(self,
-                 username, password, 
-                 certChain, privateKey,
-                 checker,
-                 settings)
-
-    def make_connection(self, host):
-        # return an existing connection if possible.  This allows
-        # HTTP/1.1 keep-alive.
-        if self._connection and host == self._connection[0]:
-            http = self._connection[1]
-        else:
-            # create a HTTPS connection object from a host descriptor
-            chost, extra_headers, x509 = self.get_host_info(host)
-
-            http = HTTPTLSConnection(chost, None,
-                                     username=self.username, password=self.password,
-                                     certChain=self.certChain, privateKey=self.privateKey,
-                                     checker=self.checker,
-                                     settings=self.settings,
-                                     ignoreAbruptClose=self.ignoreAbruptClose)
-            # store the host argument along with the connection object
-            self._connection = host, http
-        if not self.conn_class_is_http:
-            return http
-        http2 = httplib.HTTP()
-        http2._setup(http)
-        return http2
diff --git a/third_party/tlslite/tlslite/mathtls.py b/third_party/tlslite/tlslite/mathtls.py
deleted file mode 100644
index 0a23fe19..0000000
--- a/third_party/tlslite/tlslite/mathtls.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Dave Baggett (Arcode Corporation) - MD5 support for MAC_SSL
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Miscellaneous helper functions."""
-
-from .utils.compat import *
-from .utils.cryptomath import *
-
-import hmac
-
-#1024, 1536, 2048, 3072, 4096, 6144, and 8192 bit groups]
-goodGroupParameters = [(2,0xEEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3),\
-                       (2,0x9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB),\
-                       (2,0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73),\
-                       (2,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF),\
-                       (5,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF),\
-                       (5,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF),\
-                       (5,0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF)]
-
-def P_hash(macFunc, secret, seed, length):
-    bytes = bytearray(length)
-    A = seed
-    index = 0
-    while 1:
-        A = macFunc(secret, A)
-        output = macFunc(secret, A + seed)
-        for c in output:
-            if index >= length:
-                return bytes
-            bytes[index] = c
-            index += 1
-    return bytes
-
-def PRF(secret, label, seed, length):
-    #Split the secret into left and right halves
-    # which may share a byte if len is odd
-    S1 = secret[ : int(math.ceil(len(secret)/2.0))]
-    S2 = secret[ int(math.floor(len(secret)/2.0)) : ]
-
-    #Run the left half through P_MD5 and the right half through P_SHA1
-    p_md5 = P_hash(HMAC_MD5, S1, label + seed, length)
-    p_sha1 = P_hash(HMAC_SHA1, S2, label + seed, length)
-
-    #XOR the output values and return the result
-    for x in range(length):
-        p_md5[x] ^= p_sha1[x]
-    return p_md5
-
-def PRF_1_2(secret, label, seed, length):
-    return P_hash(HMAC_SHA256, secret, label + seed, length)
-
-def PRF_SSL(secret, seed, length):
-    bytes = bytearray(length)
-    index = 0
-    for x in range(26):
-        A = bytearray([ord('A')+x] * (x+1)) # 'A', 'BB', 'CCC', etc..
-        input = secret + SHA1(A + secret + seed)
-        output = MD5(input)
-        for c in output:
-            if index >= length:
-                return bytes
-            bytes[index] = c
-            index += 1
-    return bytes
-
-def calcMasterSecret(version, premasterSecret, clientRandom, serverRandom,
-                     handshakeHash, useExtendedMasterSecret):
-    label = b"master secret"
-    seed = clientRandom + serverRandom
-    if useExtendedMasterSecret:
-        label = b"extended master secret"
-        seed = handshakeHash
-
-    if version == (3,0):
-        masterSecret = PRF_SSL(premasterSecret, seed, 48)
-    elif version in ((3,1), (3,2)):
-        masterSecret = PRF(premasterSecret, label, seed, 48)
-    elif version == (3,3):
-        masterSecret = PRF_1_2(premasterSecret, label, seed, 48)
-    else:
-        raise AssertionError()
-    return masterSecret
-
-
-def makeX(salt, username, password):
-    if len(username)>=256:
-        raise ValueError("username too long")
-    if len(salt)>=256:
-        raise ValueError("salt too long")
-    innerHashResult = SHA1(username + bytearray(b":") + password)
-    outerHashResult = SHA1(salt + innerHashResult)
-    return bytesToNumber(outerHashResult)
-
-#This function is used by VerifierDB.makeVerifier
-def makeVerifier(username, password, bits):
-    bitsIndex = {1024:0, 1536:1, 2048:2, 3072:3, 4096:4, 6144:5, 8192:6}[bits]
-    g,N = goodGroupParameters[bitsIndex]
-    salt = getRandomBytes(16)
-    x = makeX(salt, username, password)
-    verifier = powMod(g, x, N)
-    return N, g, salt, verifier
-
-def PAD(n, x):
-    nLength = len(numberToByteArray(n))
-    b = numberToByteArray(x)
-    if len(b) < nLength:
-        b = (b"\0" * (nLength-len(b))) + b
-    return b
-
-def makeU(N, A, B):
-  return bytesToNumber(SHA1(PAD(N, A) + PAD(N, B)))
-
-def makeK(N, g):
-  return bytesToNumber(SHA1(numberToByteArray(N) + PAD(N, g)))
-
-def createHMAC(k, digestmod=hashlib.sha1):
-    return hmac.HMAC(k, digestmod=digestmod)
-
-def createMAC_SSL(k, digestmod=None):
-    mac = MAC_SSL()
-    mac.create(k, digestmod=digestmod)
-    return mac
-
-
-class MAC_SSL(object):
-    def create(self, k, digestmod=None):
-        self.digestmod = digestmod or hashlib.sha1
-        # Repeat pad bytes 48 times for MD5; 40 times for other hash functions.
-        self.digest_size = 16 if (self.digestmod is hashlib.md5) else 20
-        repeat = 40 if self.digest_size == 20 else 48
-        opad = b"\x5C" * repeat
-        ipad = b"\x36" * repeat
-
-        self.ohash = self.digestmod(k + opad)
-        self.ihash = self.digestmod(k + ipad)
-
-    def update(self, m):
-        self.ihash.update(m)
-
-    def copy(self):
-        new = MAC_SSL()
-        new.ihash = self.ihash.copy()
-        new.ohash = self.ohash.copy()
-        new.digestmod = self.digestmod
-        new.digest_size = self.digest_size
-        return new
-
-    def digest(self):
-        ohash2 = self.ohash.copy()
-        ohash2.update(self.ihash.digest())
-        return bytearray(ohash2.digest())
diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
deleted file mode 100644
index 5df50d3..0000000
--- a/third_party/tlslite/tlslite/messages.py
+++ /dev/null
@@ -1,900 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Google - handling CertificateRequest.certificate_types
-#   Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support
-#   Dimitris Moraitis - Anon ciphersuites
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Classes representing TLS messages."""
-
-from __future__ import division
-
-from .utils.compat import *
-from .utils.cryptomath import *
-from .errors import *
-from .utils.codec import *
-from .constants import *
-from .x509 import X509
-from .x509certchain import X509CertChain
-from .utils.tackwrapper import *
-
-def parse_next_protos(b):
-    protos = []
-    while True:
-        if len(b) == 0:
-            break
-        l = b[0]
-        b = b[1:]
-        if len(b) < l:
-            raise BadNextProtos(len(b))
-        protos.append(b[:l])
-        b = b[l:]
-    return protos
-
-def next_protos_encoded(protocol_list):
-    b = bytearray()
-    for e in protocol_list:
-        if len(e) > 255 or len(e) == 0:
-            raise BadNextProtos(len(e))
-        b += bytearray( [len(e)] ) + bytearray(e)
-    return b
-
-class RecordHeader3(object):
-    def __init__(self):
-        self.type = 0
-        self.version = (0,0)
-        self.length = 0
-        self.ssl2 = False
-
-    def create(self, version, type, length):
-        self.type = type
-        self.version = version
-        self.length = length
-        return self
-
-    def write(self):
-        w = Writer()
-        w.add(self.type, 1)
-        w.add(self.version[0], 1)
-        w.add(self.version[1], 1)
-        w.add(self.length, 2)
-        return w.bytes
-
-    def parse(self, p):
-        self.type = p.get(1)
-        self.version = (p.get(1), p.get(1))
-        self.length = p.get(2)
-        self.ssl2 = False
-        return self
-
-class RecordHeader2(object):
-    def __init__(self):
-        self.type = 0
-        self.version = (0,0)
-        self.length = 0
-        self.ssl2 = True
-
-    def parse(self, p):
-        if p.get(1)!=128:
-            raise SyntaxError()
-        self.type = ContentType.handshake
-        self.version = (2,0)
-        #We don't support 2-byte-length-headers; could be a problem
-        self.length = p.get(1)
-        return self
-
-
-class Alert(object):
-    def __init__(self):
-        self.contentType = ContentType.alert
-        self.level = 0
-        self.description = 0
-
-    def create(self, description, level=AlertLevel.fatal):
-        self.level = level
-        self.description = description
-        return self
-
-    def parse(self, p):
-        p.setLengthCheck(2)
-        self.level = p.get(1)
-        self.description = p.get(1)
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.add(self.level, 1)
-        w.add(self.description, 1)
-        return w.bytes
-
-
-class HandshakeMsg(object):
-    def __init__(self, handshakeType):
-        self.contentType = ContentType.handshake
-        self.handshakeType = handshakeType
-    
-    def postWrite(self, w):
-        headerWriter = Writer()
-        headerWriter.add(self.handshakeType, 1)
-        headerWriter.add(len(w.bytes), 3)
-        return headerWriter.bytes + w.bytes
-
-class ClientHello(HandshakeMsg):
-    def __init__(self, ssl2=False):
-        HandshakeMsg.__init__(self, HandshakeType.client_hello)
-        self.ssl2 = ssl2
-        self.client_version = (0,0)
-        self.random = bytearray(32)
-        self.session_id = bytearray(0)
-        self.cipher_suites = []         # a list of 16-bit values
-        self.certificate_types = [CertificateType.x509]
-        self.compression_methods = []   # a list of 8-bit values
-        self.srp_username = None        # a string
-        self.tack = False
-        self.alpn_protos_advertised = None
-        self.supports_npn = False
-        self.server_name = bytearray(0)
-        self.channel_id = False
-        self.extended_master_secret = False
-        self.tb_client_params = []
-        self.support_signed_cert_timestamps = False
-        self.status_request = False
-        self.has_supported_versions = False
-        self.ri = False
-        self.signature_algorithms = []
-
-    def create(self, version, random, session_id, cipher_suites,
-               certificate_types=None, srpUsername=None,
-               tack=False, alpn_protos_advertised=None,
-               supports_npn=False, serverName=None):
-        self.client_version = version
-        self.random = random
-        self.session_id = session_id
-        self.cipher_suites = cipher_suites
-        self.certificate_types = certificate_types
-        self.compression_methods = [0]
-        if srpUsername:
-            self.srp_username = bytearray(srpUsername, "utf-8")
-        self.tack = tack
-        self.alpn_protos_advertised = alpn_protos_advertised
-        self.supports_npn = supports_npn
-        if serverName:
-            self.server_name = bytearray(serverName, "utf-8")
-        return self
-
-    def parse(self, p):
-        if self.ssl2:
-            self.client_version = (p.get(1), p.get(1))
-            cipherSpecsLength = p.get(2)
-            sessionIDLength = p.get(2)
-            randomLength = p.get(2)
-            self.cipher_suites = p.getFixList(3, cipherSpecsLength//3)
-            self.session_id = p.getFixBytes(sessionIDLength)
-            self.random = p.getFixBytes(randomLength)
-            if len(self.random) < 32:
-                zeroBytes = 32-len(self.random)
-                self.random = bytearray(zeroBytes) + self.random
-            self.compression_methods = [0]#Fake this value
-
-            #We're not doing a stopLengthCheck() for SSLv2, oh well..
-        else:
-            p.startLengthCheck(3)
-            self.client_version = (p.get(1), p.get(1))
-            self.random = p.getFixBytes(32)
-            self.session_id = p.getVarBytes(1)
-            self.cipher_suites = p.getVarList(2, 2)
-            self.compression_methods = p.getVarList(1, 1)
-            if not p.atLengthCheck():
-                totalExtLength = p.get(2)
-                soFar = 0
-                while soFar != totalExtLength:
-                    extType = p.get(2)
-                    extLength = p.get(2)
-                    index1 = p.index
-                    if extType == ExtensionType.srp:
-                        self.srp_username = p.getVarBytes(1)
-                    elif extType == ExtensionType.cert_type:
-                        self.certificate_types = p.getVarList(1, 1)
-                    elif extType == ExtensionType.tack:
-                        self.tack = True
-                    elif extType == ExtensionType.alpn:
-                        structLength = p.get(2)
-                        if structLength + 2 != extLength:
-                            raise SyntaxError()
-                        self.alpn_protos_advertised = parse_next_protos(p.getFixBytes(structLength))
-                    elif extType == ExtensionType.supports_npn:
-                        self.supports_npn = True
-                    elif extType == ExtensionType.server_name:
-                        serverNameListBytes = p.getFixBytes(extLength)
-                        p2 = Parser(serverNameListBytes)
-                        p2.startLengthCheck(2)
-                        while 1:
-                            if p2.atLengthCheck():
-                                break # no host_name, oh well
-                            name_type = p2.get(1)
-                            hostNameBytes = p2.getVarBytes(2)
-                            if name_type == NameType.host_name:
-                                self.server_name = hostNameBytes
-                                break
-                    elif extType == ExtensionType.channel_id:
-                        self.channel_id = True
-                    elif extType == ExtensionType.extended_master_secret:
-                        self.extended_master_secret = True
-                    elif extType == ExtensionType.token_binding:
-                        tokenBindingBytes = p.getFixBytes(extLength)
-                        p2 = Parser(tokenBindingBytes)
-                        ver_minor = p2.get(1)
-                        ver_major = p2.get(1)
-                        if (ver_major, ver_minor) >= (0, 13):
-                            p2.startLengthCheck(1)
-                            while not p2.atLengthCheck():
-                                self.tb_client_params.append(p2.get(1))
-                    elif extType == ExtensionType.signed_cert_timestamps:
-                        if extLength:
-                            raise SyntaxError()
-                        self.support_signed_cert_timestamps = True
-                    elif extType == ExtensionType.status_request:
-                        # Extension contents are currently ignored.
-                        # According to RFC 6066, this is not strictly forbidden
-                        # (although it is suboptimal):
-                        # Servers that receive a client hello containing the
-                        # "status_request" extension MAY return a suitable
-                        # certificate status response to the client along with
-                        # their certificate.  If OCSP is requested, they
-                        # SHOULD use the information contained in the extension
-                        # when selecting an OCSP responder and SHOULD include
-                        # request_extensions in the OCSP request.
-                        p.getFixBytes(extLength)
-                        self.status_request = True
-                    elif extType == ExtensionType.renegotiation_info:
-                        # We don't support renegotiation, so if we receive this
-                        # extension, it should contain a single null byte.
-                        if extLength != 1 or p.getFixBytes(extLength)[0] != 0:
-                            raise SyntaxError()
-                        self.ri = True
-                    elif extType == ExtensionType.supported_versions:
-                        # Ignore the extension, but make a note of it for
-                        # intolerance simulation.
-                        self.has_supported_versions = True
-                        _ = p.getFixBytes(extLength)
-                    elif extType == ExtensionType.signature_algorithms:
-                        numBytes = p.get(2)
-                        if numBytes + 2 != extLength or numBytes % 2 != 0:
-                            raise SyntaxError()
-                        for _ in range(numBytes // 2):
-                            hashAlg = p.get(1)
-                            sigAlg = p.get(1)
-                            self.signature_algorithms.append((hashAlg, sigAlg))
-                    else:
-                        _ = p.getFixBytes(extLength)
-                    index2 = p.index
-                    if index2 - index1 != extLength:
-                        raise SyntaxError("Bad length for extension_data")
-                    soFar += 4 + extLength
-            if CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV in self.cipher_suites:
-                self.ri = True
-            p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.add(self.client_version[0], 1)
-        w.add(self.client_version[1], 1)
-        w.addFixSeq(self.random, 1)
-        w.addVarSeq(self.session_id, 1, 1)
-        w.addVarSeq(self.cipher_suites, 2, 2)
-        w.addVarSeq(self.compression_methods, 1, 1)
-
-        w2 = Writer() # For Extensions
-        if self.certificate_types and self.certificate_types != \
-                [CertificateType.x509]:
-            w2.add(ExtensionType.cert_type, 2)
-            w2.add(len(self.certificate_types)+1, 2)
-            w2.addVarSeq(self.certificate_types, 1, 1)
-        if self.srp_username:
-            w2.add(ExtensionType.srp, 2)
-            w2.add(len(self.srp_username)+1, 2)
-            w2.addVarSeq(self.srp_username, 1, 1)
-        if self.alpn_protos_advertised is not None:
-            encoded_alpn_protos_advertised = next_protos_encoded(self.alpn_protos_advertised)
-            w2.add(ExtensionType.alpn, 2)
-            w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
-            w2.add(len(encoded_alpn_protos_advertised), 2)
-            w2.addFixSeq(encoded_alpn_protos_advertised, 1)
-        if self.supports_npn:
-            w2.add(ExtensionType.supports_npn, 2)
-            w2.add(0, 2)
-        if self.server_name:
-            w2.add(ExtensionType.server_name, 2)
-            w2.add(len(self.server_name)+5, 2)
-            w2.add(len(self.server_name)+3, 2)            
-            w2.add(NameType.host_name, 1)
-            w2.addVarSeq(self.server_name, 1, 2) 
-        if self.tack:
-            w2.add(ExtensionType.tack, 2)
-            w2.add(0, 2)
-        if len(w2.bytes):
-            w.add(len(w2.bytes), 2)
-            w.bytes += w2.bytes
-        return self.postWrite(w)
-
-class BadNextProtos(Exception):
-    def __init__(self, l):
-        self.length = l
-
-    def __str__(self):
-        return 'Cannot encode a list of next protocols because it contains an element with invalid length %d. Element lengths must be 0 < x < 256' % self.length
-
-class InvalidALPNResponse(Exception):
-    def __init__(self, l):
-        self.length = l
-
-    def __str__(self):
-        return 'ALPN server response protocol list has invalid length %d.  It must be of length one.' % self.length
-
-class ServerHello(HandshakeMsg):
-    def __init__(self):
-        HandshakeMsg.__init__(self, HandshakeType.server_hello)
-        self.server_version = (0,0)
-        self.random = bytearray(32)
-        self.session_id = bytearray(0)
-        self.cipher_suite = 0
-        self.certificate_type = CertificateType.x509
-        self.compression_method = 0
-        self.tackExt = None
-        self.alpn_proto_selected = None
-        self.next_protos_advertised = None
-        self.next_protos = None
-        self.channel_id = False
-        self.extended_master_secret = False
-        self.tb_params = None
-        self.signed_cert_timestamps = None
-        self.status_request = False
-        self.send_ri = False
-
-    def create(self, version, random, session_id, cipher_suite,
-               certificate_type, tackExt, alpn_proto_selected,
-               next_protos_advertised):
-        self.server_version = version
-        self.random = random
-        self.session_id = session_id
-        self.cipher_suite = cipher_suite
-        self.certificate_type = certificate_type
-        self.compression_method = 0
-        self.tackExt = tackExt
-        self.alpn_proto_selected = alpn_proto_selected
-        self.next_protos_advertised = next_protos_advertised
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        self.server_version = (p.get(1), p.get(1))
-        self.random = p.getFixBytes(32)
-        self.session_id = p.getVarBytes(1)
-        self.cipher_suite = p.get(2)
-        self.compression_method = p.get(1)
-        if not p.atLengthCheck():
-            totalExtLength = p.get(2)
-            soFar = 0
-            while soFar != totalExtLength:
-                extType = p.get(2)
-                extLength = p.get(2)
-                if extType == ExtensionType.cert_type:
-                    if extLength != 1:
-                        raise SyntaxError()
-                    self.certificate_type = p.get(1)
-                elif extType == ExtensionType.tack and tackpyLoaded:
-                    self.tackExt = TackExtension(p.getFixBytes(extLength))
-                elif extType == ExtensionType.alpn:
-                    structLength = p.get(2)
-                    if structLength + 2 != extLength:
-                        raise SyntaxError()
-                    alpn_protos = parse_next_protos(p.getFixBytes(structLength))
-                    if len(alpn_protos) != 1:
-                        raise InvalidALPNResponse(len(alpn_protos));
-                    self.alpn_proto_selected = alpn_protos[0]
-                elif extType == ExtensionType.supports_npn:
-                    self.next_protos = parse_next_protos(p.getFixBytes(extLength))
-                else:
-                    p.getFixBytes(extLength)
-                soFar += 4 + extLength
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.add(self.server_version[0], 1)
-        w.add(self.server_version[1], 1)
-        w.addFixSeq(self.random, 1)
-        w.addVarSeq(self.session_id, 1, 1)
-        w.add(self.cipher_suite, 2)
-        w.add(self.compression_method, 1)
-
-        w2 = Writer() # For Extensions
-        if self.certificate_type and self.certificate_type != \
-                CertificateType.x509:
-            w2.add(ExtensionType.cert_type, 2)
-            w2.add(1, 2)
-            w2.add(self.certificate_type, 1)
-        if self.tackExt:
-            b = self.tackExt.serialize()
-            w2.add(ExtensionType.tack, 2)
-            w2.add(len(b), 2)
-            w2.bytes += b
-        if self.alpn_proto_selected is not None:
-            alpn_protos_single_element_list = [self.alpn_proto_selected]
-            encoded_alpn_protos_advertised = next_protos_encoded(alpn_protos_single_element_list)
-            w2.add(ExtensionType.alpn, 2)
-            w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
-            w2.add(len(encoded_alpn_protos_advertised), 2)
-            w2.addFixSeq(encoded_alpn_protos_advertised, 1)
-        if self.next_protos_advertised is not None:
-            encoded_next_protos_advertised = next_protos_encoded(self.next_protos_advertised)
-            w2.add(ExtensionType.supports_npn, 2)
-            w2.add(len(encoded_next_protos_advertised), 2)
-            w2.addFixSeq(encoded_next_protos_advertised, 1)
-        if self.channel_id:
-            w2.add(ExtensionType.channel_id, 2)
-            w2.add(0, 2)
-        if self.extended_master_secret:
-            w2.add(ExtensionType.extended_master_secret, 2)
-            w2.add(0, 2)
-        if self.tb_params:
-            w2.add(ExtensionType.token_binding, 2)
-            # length of extension
-            w2.add(4, 2)
-            # version
-            w2.add(0, 1)
-            w2.add(13, 1)
-            # length of params (defined as variable length <1..2^8-1>, but in
-            # this context the server can only send a single value.
-            w2.add(1, 1)
-            w2.add(self.tb_params, 1)
-        if self.signed_cert_timestamps:
-            w2.add(ExtensionType.signed_cert_timestamps, 2)
-            w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2)
-        if self.status_request:
-            w2.add(ExtensionType.status_request, 2)
-            w2.add(0, 2)
-        if self.send_ri:
-            w2.add(ExtensionType.renegotiation_info, 2)
-            w2.add(1, 2)
-            w2.add(0, 1)
-        if len(w2.bytes):
-            w.add(len(w2.bytes), 2)
-            w.bytes += w2.bytes        
-        return self.postWrite(w)
-
-
-class Certificate(HandshakeMsg):
-    def __init__(self, certificateType):
-        HandshakeMsg.__init__(self, HandshakeType.certificate)
-        self.certificateType = certificateType
-        self.certChain = None
-
-    def create(self, certChain):
-        self.certChain = certChain
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        if self.certificateType == CertificateType.x509:
-            chainLength = p.get(3)
-            index = 0
-            certificate_list = []
-            while index != chainLength:
-                certBytes = p.getVarBytes(3)
-                x509 = X509()
-                x509.parseBinary(certBytes)
-                certificate_list.append(x509)
-                index += len(certBytes)+3
-            if certificate_list:
-                self.certChain = X509CertChain(certificate_list)
-        else:
-            raise AssertionError()
-
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        if self.certificateType == CertificateType.x509:
-            chainLength = 0
-            if self.certChain:
-                certificate_list = self.certChain.x509List
-            else:
-                certificate_list = []
-            #determine length
-            for cert in certificate_list:
-                bytes = cert.writeBytes()
-                chainLength += len(bytes)+3
-            #add bytes
-            w.add(chainLength, 3)
-            for cert in certificate_list:
-                bytes = cert.writeBytes()
-                w.addVarSeq(bytes, 1, 3)
-        else:
-            raise AssertionError()
-        return self.postWrite(w)
-
-class CertificateStatus(HandshakeMsg):
-    def __init__(self):
-        HandshakeMsg.__init__(self, HandshakeType.certificate_status)
-
-    def create(self, ocsp_response):
-        self.ocsp_response = ocsp_response
-        return self
-
-    # Defined for the sake of completeness, even though we currently only
-    # support sending the status message (server-side), not requesting
-    # or receiving it (client-side).
-    def parse(self, p):
-        p.startLengthCheck(3)
-        status_type = p.get(1)
-        # Only one type is specified, so hardwire it.
-        if status_type != CertificateStatusType.ocsp:
-            raise SyntaxError()
-        ocsp_response = p.getVarBytes(3)
-        if not ocsp_response:
-            # Can't be empty
-            raise SyntaxError()
-        self.ocsp_response = ocsp_response
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.add(CertificateStatusType.ocsp, 1)
-        w.addVarSeq(bytearray(self.ocsp_response), 1, 3)
-        return self.postWrite(w)
-
-class CertificateRequest(HandshakeMsg):
-    def __init__(self, version):
-        HandshakeMsg.__init__(self, HandshakeType.certificate_request)
-        self.certificate_types = []
-        self.certificate_authorities = []
-        self.version = version
-        self.supported_signature_algs = []
-
-    def create(self, certificate_types, certificate_authorities, sig_algs):
-        self.certificate_types = certificate_types
-        self.certificate_authorities = certificate_authorities
-        self.supported_signature_algs = sig_algs
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        self.certificate_types = p.getVarList(1, 1)
-        if self.version >= (3,3):
-            self.supported_signature_algs = \
-                [(b >> 8, b & 0xff) for b in p.getVarList(2, 2)]
-        ca_list_length = p.get(2)
-        index = 0
-        self.certificate_authorities = []
-        while index != ca_list_length:
-          ca_bytes = p.getVarBytes(2)
-          self.certificate_authorities.append(ca_bytes)
-          index += len(ca_bytes)+2
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.addVarSeq(self.certificate_types, 1, 1)
-        if self.version >= (3,3):
-            w.add(2 * len(self.supported_signature_algs), 2)
-            for (hash, signature) in self.supported_signature_algs:
-                w.add(hash, 1)
-                w.add(signature, 1)
-        caLength = 0
-        #determine length
-        for ca_dn in self.certificate_authorities:
-            caLength += len(ca_dn)+2
-        w.add(caLength, 2)
-        #add bytes
-        for ca_dn in self.certificate_authorities:
-            w.addVarSeq(ca_dn, 1, 2)
-        return self.postWrite(w)
-
-class ServerKeyExchange(HandshakeMsg):
-    def __init__(self, cipherSuite, version):
-        HandshakeMsg.__init__(self, HandshakeType.server_key_exchange)
-        self.cipherSuite = cipherSuite
-        self.version = version
-        self.srp_N = 0
-        self.srp_g = 0
-        self.srp_s = bytearray(0)
-        self.srp_B = 0
-        # DH params:
-        self.dh_p = 0
-        self.dh_g = 0
-        self.dh_Ys = 0
-        # ECDH params:
-        self.ecdhCurve = 0
-        self.ecdhPublic = bytearray(0)
-        self.signature = bytearray(0)
-        self.signature_algorithm = None
-
-    def createSRP(self, srp_N, srp_g, srp_s, srp_B):
-        self.srp_N = srp_N
-        self.srp_g = srp_g
-        self.srp_s = srp_s
-        self.srp_B = srp_B
-        return self
-    
-    def createDH(self, dh_p, dh_g, dh_Ys):
-        self.dh_p = dh_p
-        self.dh_g = dh_g
-        self.dh_Ys = dh_Ys
-        return self
-
-    def createECDH(self, ecdhCurve, ecdhPublic):
-        self.ecdhCurve = ecdhCurve
-        self.ecdhPublic = ecdhPublic
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        if self.cipherSuite in CipherSuite.srpAllSuites:
-            self.srp_N = bytesToNumber(p.getVarBytes(2))
-            self.srp_g = bytesToNumber(p.getVarBytes(2))
-            self.srp_s = p.getVarBytes(1)
-            self.srp_B = bytesToNumber(p.getVarBytes(2))
-            if self.cipherSuite in CipherSuite.srpCertSuites:
-                self.signature = p.getVarBytes(2)
-        elif self.cipherSuite in CipherSuite.anonSuites:
-            self.dh_p = bytesToNumber(p.getVarBytes(2))
-            self.dh_g = bytesToNumber(p.getVarBytes(2))
-            self.dh_Ys = bytesToNumber(p.getVarBytes(2))
-        p.stopLengthCheck()
-        return self
-
-    def write_params(self):
-        w = Writer()
-        if self.cipherSuite in CipherSuite.srpAllSuites:
-            w.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
-            w.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
-            w.addVarSeq(self.srp_s, 1, 1)
-            w.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
-        elif self.cipherSuite in CipherSuite.dhAllSuites:
-            w.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
-            w.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
-            w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
-        elif self.cipherSuite in CipherSuite.ecdhAllSuites:
-            w.add(ECCurveType.named_curve, 1)
-            w.add(self.ecdhCurve, 2)
-            w.addVarSeq(self.ecdhPublic, 1, 1)
-        else:
-            assert(False)
-        return w.bytes
-
-    def write(self):
-        w = Writer()
-        w.bytes += self.write_params()
-        if self.cipherSuite in CipherSuite.certAllSuites:
-            if self.version >= (3,3):
-                w.add(self.signature_algorithm[0], 1)
-                w.add(self.signature_algorithm[1], 1)
-            w.addVarSeq(self.signature, 1, 2)
-        return self.postWrite(w)
-
-    def signingPayload(self, clientRandom, serverRandom):
-        return clientRandom + serverRandom + self.write_params()
-
-class ServerHelloDone(HandshakeMsg):
-    def __init__(self):
-        HandshakeMsg.__init__(self, HandshakeType.server_hello_done)
-
-    def create(self):
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        return self.postWrite(w)
-
-class ClientKeyExchange(HandshakeMsg):
-    def __init__(self, cipherSuite, version=None):
-        HandshakeMsg.__init__(self, HandshakeType.client_key_exchange)
-        self.cipherSuite = cipherSuite
-        self.version = version
-        self.srp_A = 0
-        self.encryptedPreMasterSecret = bytearray(0)
-
-    def createSRP(self, srp_A):
-        self.srp_A = srp_A
-        return self
-
-    def createRSA(self, encryptedPreMasterSecret):
-        self.encryptedPreMasterSecret = encryptedPreMasterSecret
-        return self
-    
-    def createDH(self, dh_Yc):
-        self.dh_Yc = dh_Yc
-        return self
-    
-    def parse(self, p):
-        p.startLengthCheck(3)
-        if self.cipherSuite in CipherSuite.srpAllSuites:
-            self.srp_A = bytesToNumber(p.getVarBytes(2))
-        elif self.cipherSuite in CipherSuite.certSuites:
-            if self.version in ((3,1), (3,2), (3,3)):
-                self.encryptedPreMasterSecret = p.getVarBytes(2)
-            elif self.version == (3,0):
-                self.encryptedPreMasterSecret = \
-                    p.getFixBytes(len(p.bytes)-p.index)
-            else:
-                raise AssertionError()
-        elif self.cipherSuite in CipherSuite.dhAllSuites:
-            self.dh_Yc = bytesToNumber(p.getVarBytes(2))
-        elif self.cipherSuite in CipherSuite.ecdhAllSuites:
-            self.ecdh_Yc = p.getVarBytes(1)
-        else:
-            raise AssertionError()
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        if self.cipherSuite in CipherSuite.srpAllSuites:
-            w.addVarSeq(numberToByteArray(self.srp_A), 1, 2)
-        elif self.cipherSuite in CipherSuite.certSuites:
-            if self.version in ((3,1), (3,2), (3,3)):
-                w.addVarSeq(self.encryptedPreMasterSecret, 1, 2)
-            elif self.version == (3,0):
-                w.addFixSeq(self.encryptedPreMasterSecret, 1)
-            else:
-                raise AssertionError()
-        elif self.cipherSuite in CipherSuite.anonSuites:
-            w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2)            
-        else:
-            raise AssertionError()
-        return self.postWrite(w)
-
-class CertificateVerify(HandshakeMsg):
-    def __init__(self, version):
-        HandshakeMsg.__init__(self, HandshakeType.certificate_verify)
-        self.version = version
-        self.signature_algorithm = None
-        self.signature = bytearray(0)
-
-    def create(self, signature_algorithm, signature):
-        self.signature_algorithm = signature_algorithm
-        self.signature = signature
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        if self.version >= (3,3):
-            self.signature_algorithm = (p.get(1), p.get(1))
-        self.signature = p.getVarBytes(2)
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        if self.version >= (3,3):
-            w.add(self.signature_algorithm[0], 1)
-            w.add(self.signature_algorithm[1], 1)
-        w.addVarSeq(self.signature, 1, 2)
-        return self.postWrite(w)
-
-class ChangeCipherSpec(object):
-    def __init__(self):
-        self.contentType = ContentType.change_cipher_spec
-        self.type = 1
-
-    def create(self):
-        self.type = 1
-        return self
-
-    def parse(self, p):
-        p.setLengthCheck(1)
-        self.type = p.get(1)
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.add(self.type,1)
-        return w.bytes
-
-
-class NextProtocol(HandshakeMsg):
-    def __init__(self):
-        HandshakeMsg.__init__(self, HandshakeType.next_protocol)
-        self.next_proto = None
-
-    def create(self, next_proto):
-        self.next_proto = next_proto
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        self.next_proto = p.getVarBytes(1)
-        _ = p.getVarBytes(1)
-        p.stopLengthCheck()
-        return self
-
-    def write(self, trial=False):
-        w = Writer()
-        w.addVarSeq(self.next_proto, 1, 1)
-        paddingLen = 32 - ((len(self.next_proto) + 2) % 32)
-        w.addVarSeq(bytearray(paddingLen), 1, 1)
-        return self.postWrite(w)
-
-class Finished(HandshakeMsg):
-    def __init__(self, version):
-        HandshakeMsg.__init__(self, HandshakeType.finished)
-        self.version = version
-        self.verify_data = bytearray(0)
-
-    def create(self, verify_data):
-        self.verify_data = verify_data
-        return self
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        if self.version == (3,0):
-            self.verify_data = p.getFixBytes(36)
-        elif self.version in ((3,1), (3,2), (3,3)):
-            self.verify_data = p.getFixBytes(12)
-        else:
-            raise AssertionError()
-        p.stopLengthCheck()
-        return self
-
-    def write(self):
-        w = Writer()
-        w.addFixSeq(self.verify_data, 1)
-        return self.postWrite(w)
-
-class EncryptedExtensions(HandshakeMsg):
-    def __init__(self):
-        self.channel_id_key = None
-        self.channel_id_proof = None
-
-    def parse(self, p):
-        p.startLengthCheck(3)
-        soFar = 0
-        while soFar != p.lengthCheck:
-            extType = p.get(2)
-            extLength = p.get(2)
-            if extType == ExtensionType.channel_id:
-                if extLength != 32*4:
-                    raise SyntaxError()
-                self.channel_id_key = p.getFixBytes(64)
-                self.channel_id_proof = p.getFixBytes(64)
-            else:
-                p.getFixBytes(extLength)
-            soFar += 4 + extLength
-        p.stopLengthCheck()
-        return self
-
-class ApplicationData(object):
-    def __init__(self):
-        self.contentType = ContentType.application_data
-        self.bytes = bytearray(0)
-
-    def create(self, bytes):
-        self.bytes = bytes
-        return self
-        
-    def splitFirstByte(self):
-        newMsg = ApplicationData().create(self.bytes[:1])
-        self.bytes = self.bytes[1:]
-        return newMsg
-
-    def parse(self, p):
-        self.bytes = p.bytes
-        return self
-
-    def write(self):
-        return self.bytes
diff --git a/third_party/tlslite/tlslite/session.py b/third_party/tlslite/tlslite/session.py
deleted file mode 100644
index 6aadf58e..0000000
--- a/third_party/tlslite/tlslite/session.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Dave Baggett (Arcode Corporation) - canonicalCipherName
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class representing a TLS session."""
-
-from .utils.compat import *
-from .mathtls import *
-from .constants import *
-
-class Session(object):
-    """
-    This class represents a TLS session.
-
-    TLS distinguishes between connections and sessions.  A new
-    handshake creates both a connection and a session.  Data is
-    transmitted over the connection.
-
-    The session contains a more permanent record of the handshake.  The
-    session can be inspected to determine handshake results.  The
-    session can also be used to create a new connection through
-    "session resumption". If the client and server both support this,
-    they can create a new connection based on an old session without
-    the overhead of a full handshake.
-
-    The session for a L{tlslite.TLSConnection.TLSConnection} can be
-    retrieved from the connection's 'session' attribute.
-
-    @type srpUsername: str
-    @ivar srpUsername: The client's SRP username (or None).
-
-    @type clientCertChain: L{tlslite.x509certchain.X509CertChain}
-    @ivar clientCertChain: The client's certificate chain (or None).
-
-    @type serverCertChain: L{tlslite.x509certchain.X509CertChain}
-    @ivar serverCertChain: The server's certificate chain (or None).
-
-    @type tackExt: L{tack.structures.TackExtension.TackExtension}
-    @ivar tackExt: The server's TackExtension (or None).
-
-    @type tackInHelloExt: L{bool}
-    @ivar tackInHelloExt: True if a TACK was presented via TLS Extension.
-    """
-
-    def __init__(self):
-        self.masterSecret = bytearray(0)
-        self.sessionID = bytearray(0)
-        self.cipherSuite = 0
-        self.srpUsername = ""
-        self.clientCertChain = None
-        self.serverCertChain = None
-        self.tackExt = None
-        self.tackInHelloExt = False
-        self.serverName = ""
-        self.resumable = False
-
-    def create(self, masterSecret, sessionID, cipherSuite,
-            srpUsername, clientCertChain, serverCertChain, 
-            tackExt, tackInHelloExt, serverName, resumable=True):
-        self.masterSecret = masterSecret
-        self.sessionID = sessionID
-        self.cipherSuite = cipherSuite
-        self.srpUsername = srpUsername
-        self.clientCertChain = clientCertChain
-        self.serverCertChain = serverCertChain
-        self.tackExt = tackExt
-        self.tackInHelloExt = tackInHelloExt  
-        self.serverName = serverName
-        self.resumable = resumable
-
-    def _clone(self):
-        other = Session()
-        other.masterSecret = self.masterSecret
-        other.sessionID = self.sessionID
-        other.cipherSuite = self.cipherSuite
-        other.srpUsername = self.srpUsername
-        other.clientCertChain = self.clientCertChain
-        other.serverCertChain = self.serverCertChain
-        other.tackExt = self.tackExt
-        other.tackInHelloExt = self.tackInHelloExt
-        other.serverName = self.serverName
-        other.resumable = self.resumable
-        return other
-
-    def valid(self):
-        """If this session can be used for session resumption.
-
-        @rtype: bool
-        @return: If this session can be used for session resumption.
-        """
-        return self.resumable and self.sessionID
-
-    def _setResumable(self, boolean):
-        #Only let it be set to True if the sessionID is non-null
-        if (not boolean) or (boolean and self.sessionID):
-            self.resumable = boolean
-
-    def getTackId(self):
-        if self.tackExt and self.tackExt.tack:
-            return self.tackExt.tack.getTackId()
-        else:
-            return None
-        
-    def getBreakSigs(self):
-        if self.tackExt and self.tackExt.break_sigs:
-            return self.tackExt.break_sigs
-        else:
-            return None
-
-    def getCipherName(self):
-        """Get the name of the cipher used with this connection.
-
-        @rtype: str
-        @return: The name of the cipher used with this connection.
-        """
-        return CipherSuite.canonicalCipherName(self.cipherSuite)
-        
-    def getMacName(self):
-        """Get the name of the HMAC hash algo used with this connection.
-
-        @rtype: str
-        @return: The name of the HMAC hash algo used with this connection.
-        """
-        return CipherSuite.canonicalMacName(self.cipherSuite)
diff --git a/third_party/tlslite/tlslite/sessioncache.py b/third_party/tlslite/tlslite/sessioncache.py
deleted file mode 100644
index 7071d10..0000000
--- a/third_party/tlslite/tlslite/sessioncache.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Martin von Loewis - python 3 port
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class for caching TLS sessions."""
-
-import threading
-import time
-
-class SessionCache(object):
-    """This class is used by the server to cache TLS sessions.
-
-    Caching sessions allows the client to use TLS session resumption
-    and avoid the expense of a full handshake.  To use this class,
-    simply pass a SessionCache instance into the server handshake
-    function.
-
-    This class is thread-safe.
-    """
-
-    #References to these instances
-    #are also held by the caller, who may change the 'resumable'
-    #flag, so the SessionCache must return the same instances
-    #it was passed in.
-
-    def __init__(self, maxEntries=10000, maxAge=14400):
-        """Create a new SessionCache.
-
-        @type maxEntries: int
-        @param maxEntries: The maximum size of the cache.  When this
-        limit is reached, the oldest sessions will be deleted as
-        necessary to make room for new ones.  The default is 10000.
-
-        @type maxAge: int
-        @param maxAge:  The number of seconds before a session expires
-        from the cache.  The default is 14400 (i.e. 4 hours)."""
-
-        self.lock = threading.Lock()
-
-        # Maps sessionIDs to sessions
-        self.entriesDict = {}
-
-        #Circular list of (sessionID, timestamp) pairs
-        self.entriesList = [(None,None)] * maxEntries
-
-        self.firstIndex = 0
-        self.lastIndex = 0
-        self.maxAge = maxAge
-
-    def __getitem__(self, sessionID):
-        self.lock.acquire()
-        try:
-            self._purge() #Delete old items, so we're assured of a new one
-            session = self.entriesDict[bytes(sessionID)]
-
-            #When we add sessions they're resumable, but it's possible
-            #for the session to be invalidated later on (if a fatal alert
-            #is returned), so we have to check for resumability before
-            #returning the session.
-
-            if session.valid():
-                return session
-            else:
-                raise KeyError()
-        finally:
-            self.lock.release()
-
-
-    def __setitem__(self, sessionID, session):
-        self.lock.acquire()
-        try:
-            #Add the new element
-            self.entriesDict[bytes(sessionID)] = session
-            self.entriesList[self.lastIndex] = (sessionID, time.time())
-            self.lastIndex = (self.lastIndex+1) % len(self.entriesList)
-
-            #If the cache is full, we delete the oldest element to make an
-            #empty space
-            if self.lastIndex == self.firstIndex:
-                del(self.entriesDict[self.entriesList[self.firstIndex][0]])
-                self.firstIndex = (self.firstIndex+1) % len(self.entriesList)
-        finally:
-            self.lock.release()
-
-    #Delete expired items
-    def _purge(self):
-        currentTime = time.time()
-
-        #Search through the circular list, deleting expired elements until
-        #we reach a non-expired element.  Since elements in list are
-        #ordered in time, we can break once we reach the first non-expired
-        #element
-        index = self.firstIndex
-        while index != self.lastIndex:
-            if currentTime - self.entriesList[index][1] > self.maxAge:
-                del(self.entriesDict[self.entriesList[index][0]])
-                index = (index+1) % len(self.entriesList)
-            else:
-                break
-        self.firstIndex = index
-
-def _test():
-    import doctest, SessionCache
-    return doctest.testmod(SessionCache)
-
-if __name__ == "__main__":
-    _test()
diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
deleted file mode 100644
index f64c848a..0000000
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ /dev/null
@@ -1,2115 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Google - added reqCAs parameter
-#   Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support
-#   Dimitris Moraitis - Anon ciphersuites
-#   Martin von Loewis - python 3 port
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""
-MAIN CLASS FOR TLS LITE (START HERE!).
-"""
-
-import socket
-from .utils.compat import formatExceptionTrace
-from .tlsrecordlayer import TLSRecordLayer
-from .session import Session
-from .constants import *
-from .utils.cryptomath import getRandomBytes, MD5, SHA1, SHA256
-from .errors import *
-from .messages import *
-from .mathtls import *
-from .handshakesettings import HandshakeSettings
-from .utils.tackwrapper import *
-from .utils.rsakey import RSAKey
-from .utils import p256
-
-class KeyExchange(object):
-    def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
-        """
-        Initializes the KeyExchange. privateKey is the signing private key.
-        """
-        self.cipherSuite = cipherSuite
-        self.clientHello = clientHello
-        self.serverHello = serverHello
-        self.privateKey = privateKey
-
-    def makeServerKeyExchange():
-        """
-        Returns a ServerKeyExchange object for the server's initial leg in the
-        handshake. If the key exchange method does not send ServerKeyExchange
-        (e.g. RSA), it returns None.
-        """
-        raise NotImplementedError()
-
-    def processClientKeyExchange(clientKeyExchange):
-        """
-        Processes the client's ClientKeyExchange message and returns the
-        premaster secret. Raises TLSLocalAlert on error.
-        """
-        raise NotImplementedError()
-
-    def sign(self, inpBytes):
-        algorithm = None
-        if self.serverHello.server_version >= (3, 3):
-            # Negotiate a signature algorithm.
-            peerPrefs = self.clientHello.signature_algorithms
-            if (HashAlgorithm.sha256, SignatureAlgorithm.rsa) in peerPrefs:
-                algorithm = (HashAlgorithm.sha256, SignatureAlgorithm.rsa)
-                inpBytes = RSAKey.addPKCS1SHA256Prefix(SHA256(inpBytes))
-            elif (HashAlgorithm.sha1, SignatureAlgorithm.rsa) in peerPrefs:
-                algorithm = (HashAlgorithm.sha1, SignatureAlgorithm.rsa)
-                inpBytes = RSAKey.addPKCS1SHA1Prefix(SHA1(inpBytes))
-            else:
-                raise TLSLocalAlert(AlertDescription.handshake_failure,
-                                   "no common signature algorithms")
-        else:
-            inpBytes = MD5(inpBytes) + SHA1(inpBytes)
-        return algorithm, self.privateKey.sign(inpBytes)
-
-class RSAKeyExchange(KeyExchange):
-    def makeServerKeyExchange(self):
-        return None
-
-    def processClientKeyExchange(self, clientKeyExchange):
-        premasterSecret = self.privateKey.decrypt(\
-            clientKeyExchange.encryptedPreMasterSecret)
-
-        # On decryption failure randomize premaster secret to avoid
-        # Bleichenbacher's "million message" attack
-        randomPreMasterSecret = getRandomBytes(48)
-        if not premasterSecret:
-            premasterSecret = randomPreMasterSecret
-        elif len(premasterSecret)!=48:
-            premasterSecret = randomPreMasterSecret
-        else:
-            versionCheck = (premasterSecret[0], premasterSecret[1])
-            if versionCheck != self.clientHello.client_version:
-                #Tolerate buggy IE clients
-                if versionCheck != self.serverHello.server_version:
-                    premasterSecret = randomPreMasterSecret
-        return premasterSecret
-
-def _hexStringToNumber(s):
-    s = s.replace(" ", "").replace("\n", "")
-    if len(s) % 2 != 0:
-        raise ValueError("Length is not even")
-    return bytesToNumber(bytearray.fromhex(s))
-
-class DHE_RSAKeyExchange(KeyExchange):
-    # 2048-bit MODP Group (RFC 3526, Section 3)
-    dh_p = _hexStringToNumber("""
-FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
-29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
-EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
-E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
-EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
-C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
-83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
-670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
-E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
-DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
-15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""")
-    dh_g = 2
-
-    # RFC 3526, Section 8.
-    strength = 160
-
-    def makeServerKeyExchange(self):
-        # Per RFC 3526, Section 1, the exponent should have double the entropy
-        # of the strength of the curve.
-        self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8))
-        dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
-
-        version = self.serverHello.server_version
-        serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
-        serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
-        serverKeyExchange.signature_algorithm, serverKeyExchange.signature = \
-            self.sign(serverKeyExchange.signingPayload(self.clientHello.random,
-                                                       self.serverHello.random))
-        return serverKeyExchange
-
-    def processClientKeyExchange(self, clientKeyExchange):
-        dh_Yc = clientKeyExchange.dh_Yc
-
-        # First half of RFC 2631, Section 2.1.5. Validate the client's public
-        # key.
-        if not 2 <= dh_Yc <= self.dh_p - 1:
-            raise TLSLocalAlert(AlertDescription.illegal_parameter,
-                                "Invalid dh_Yc value")
-
-        S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
-        return numberToByteArray(S)
-
-class ECDHE_RSAKeyExchange(KeyExchange):
-    def makeServerKeyExchange(self):
-        public, self.private = p256.generatePublicPrivate()
-
-        version = self.serverHello.server_version
-        serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
-        serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public))
-        serverKeyExchange.signature_algorithm, serverKeyExchange.signature = \
-            self.sign(serverKeyExchange.signingPayload(self.clientHello.random,
-                                                       self.serverHello.random))
-        return serverKeyExchange
-
-    def processClientKeyExchange(self, clientKeyExchange):
-        ecdh_Yc = clientKeyExchange.ecdh_Yc
-        return bytearray(p256.generateSharedValue(bytes(ecdh_Yc), self.private))
-
-class TLSConnection(TLSRecordLayer):
-    """
-    This class wraps a socket and provides TLS handshaking and data
-    transfer.
-
-    To use this class, create a new instance, passing a connected
-    socket into the constructor.  Then call some handshake function.
-    If the handshake completes without raising an exception, then a TLS
-    connection has been negotiated.  You can transfer data over this
-    connection as if it were a socket.
-
-    This class provides both synchronous and asynchronous versions of
-    its key functions.  The synchronous versions should be used when
-    writing single-or multi-threaded code using blocking sockets.  The
-    asynchronous versions should be used when performing asynchronous,
-    event-based I/O with non-blocking sockets.
-
-    Asynchronous I/O is a complicated subject; typically, you should
-    not use the asynchronous functions directly, but should use some
-    framework like asyncore or Twisted which TLS Lite integrates with
-    (see
-    L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}).
-    """
-
-    def __init__(self, sock):
-        """Create a new TLSConnection instance.
-
-        @param sock: The socket data will be transmitted on.  The
-        socket should already be connected.  It may be in blocking or
-        non-blocking mode.
-
-        @type sock: L{socket.socket}
-        """
-        TLSRecordLayer.__init__(self, sock)
-        self.clientRandom = b""
-        self.serverRandom = b""
-
-    #*********************************************************
-    # Client Handshake Functions
-    #*********************************************************
-
-    def handshakeClientAnonymous(self, session=None, settings=None, 
-                                checker=None, serverName="",
-                                is_async=False):
-        """Perform an anonymous handshake in the role of client.
-
-        This function performs an SSL or TLS handshake using an
-        anonymous Diffie Hellman ciphersuite.
-        
-        Like any handshake function, this can be called on a closed
-        TLS connection, or on a TLS connection that is already open.
-        If called on an open connection it performs a re-handshake.
-
-        If the function completes without raising an exception, the
-        TLS connection will be open and available for data transfer.
-
-        If an exception is raised, the connection will have been
-        automatically closed (if it was ever open).
-
-        @type session: L{tlslite.Session.Session}
-        @param session: A TLS session to attempt to resume.  If the
-        resumption does not succeed, a full handshake will be
-        performed.
-
-        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-
-        @type checker: L{tlslite.Checker.Checker}
-        @param checker: A Checker instance.  This instance will be
-        invoked to examine the other party's authentication
-        credentials, if the handshake completes succesfully.
-        
-        @type serverName: string
-        @param serverName: The ServerNameIndication TLS Extension.
-
-        @type is_async: bool
-        @param is_async: If False, this function will block until the
-        handshake is completed.  If True, this function will return a
-        generator.  Successive invocations of the generator will
-        return 0 if it is waiting to read from the socket, 1 if it is
-        waiting to write to the socket, or will raise StopIteration if
-        the handshake operation is completed.
-
-        @rtype: None or an iterable
-        @return: If 'is_async' is True, a generator object will be
-        returned.
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        @raise tlslite.errors.TLSAuthenticationError: If the checker
-        doesn't like the other party's authentication credentials.
-        """
-        handshaker = self._handshakeClientAsync(anonParams=(True),
-                                                session=session,
-                                                settings=settings,
-                                                checker=checker,
-                                                serverName=serverName)
-        if is_async:
-            return handshaker
-        for result in handshaker:
-            pass
-
-    def handshakeClientSRP(self, username, password, session=None,
-                           settings=None, checker=None, 
-                           reqTack=True, serverName="",
-                           is_async=False):
-        """Perform an SRP handshake in the role of client.
-
-        This function performs a TLS/SRP handshake.  SRP mutually
-        authenticates both parties to each other using only a
-        username and password.  This function may also perform a
-        combined SRP and server-certificate handshake, if the server
-        chooses to authenticate itself with a certificate chain in
-        addition to doing SRP.
-
-        If the function completes without raising an exception, the
-        TLS connection will be open and available for data transfer.
-
-        If an exception is raised, the connection will have been
-        automatically closed (if it was ever open).
-
-        @type username: str
-        @param username: The SRP username.
-
-        @type password: str
-        @param password: The SRP password.
-
-        @type session: L{tlslite.session.Session}
-        @param session: A TLS session to attempt to resume.  This
-        session must be an SRP session performed with the same username
-        and password as were passed in.  If the resumption does not
-        succeed, a full SRP handshake will be performed.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: A Checker instance.  This instance will be
-        invoked to examine the other party's authentication
-        credentials, if the handshake completes succesfully.
-
-        @type reqTack: bool
-        @param reqTack: Whether or not to send a "tack" TLS Extension, 
-        requesting the server return a TackExtension if it has one.
-
-        @type serverName: string
-        @param serverName: The ServerNameIndication TLS Extension.
-
-        @type is_async: bool
-        @param is_async: If False, this function will block until the
-        handshake is completed.  If True, this function will return a
-        generator.  Successive invocations of the generator will
-        return 0 if it is waiting to read from the socket, 1 if it is
-        waiting to write to the socket, or will raise StopIteration if
-        the handshake operation is completed.
-
-        @rtype: None or an iterable
-        @return: If 'is_async' is True, a generator object will be
-        returned.
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        @raise tlslite.errors.TLSAuthenticationError: If the checker
-        doesn't like the other party's authentication credentials.
-        """
-        handshaker = self._handshakeClientAsync(srpParams=(username, password),
-                        session=session, settings=settings, checker=checker,
-                        reqTack=reqTack, serverName=serverName)
-        # The handshaker is a Python Generator which executes the handshake.
-        # It allows the handshake to be run in a "piecewise", asynchronous
-        # fashion, returning 1 when it is waiting to able to write, 0 when
-        # it is waiting to read.
-        #
-        # If 'is_async' is True, the generator is returned to the caller,
-        # otherwise it is executed to completion here.
-        if is_async:
-            return handshaker
-        for result in handshaker:
-            pass
-
-    def handshakeClientCert(self, certChain=None, privateKey=None,
-                            session=None, settings=None, checker=None,
-                            nextProtos=None, reqTack=True, serverName="",
-                            is_async=False):
-        """Perform a certificate-based handshake in the role of client.
-
-        This function performs an SSL or TLS handshake.  The server
-        will authenticate itself using an X.509 certificate
-        chain.  If the handshake succeeds, the server's certificate
-        chain will be stored in the session's serverCertChain attribute.
-        Unless a checker object is passed in, this function does no
-        validation or checking of the server's certificate chain.
-
-        If the server requests client authentication, the
-        client will send the passed-in certificate chain, and use the
-        passed-in private key to authenticate itself.  If no
-        certificate chain and private key were passed in, the client
-        will attempt to proceed without client authentication.  The
-        server may or may not allow this.
-
-        If the function completes without raising an exception, the
-        TLS connection will be open and available for data transfer.
-
-        If an exception is raised, the connection will have been
-        automatically closed (if it was ever open).
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: The certificate chain to be used if the
-        server requests client authentication.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: The private key to be used if the server
-        requests client authentication.
-
-        @type session: L{tlslite.session.Session}
-        @param session: A TLS session to attempt to resume.  If the
-        resumption does not succeed, a full handshake will be
-        performed.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites, certificate types, and SSL/TLS versions
-        offered by the client.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: A Checker instance.  This instance will be
-        invoked to examine the other party's authentication
-        credentials, if the handshake completes succesfully.
-        
-        @type nextProtos: list of strings.
-        @param nextProtos: A list of upper layer protocols ordered by
-        preference, to use in the Next-Protocol Negotiation Extension.
-        
-        @type reqTack: bool
-        @param reqTack: Whether or not to send a "tack" TLS Extension, 
-        requesting the server return a TackExtension if it has one.        
-
-        @type serverName: string
-        @param serverName: The ServerNameIndication TLS Extension.
-
-        @type is_async: bool
-        @param is_async: If False, this function will block until the
-        handshake is completed.  If True, this function will return a
-        generator.  Successive invocations of the generator will
-        return 0 if it is waiting to read from the socket, 1 if it is
-        waiting to write to the socket, or will raise StopIteration if
-        the handshake operation is completed.
-
-        @rtype: None or an iterable
-        @return: If 'is_async' is True, a generator object will be
-        returned.
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        @raise tlslite.errors.TLSAuthenticationError: If the checker
-        doesn't like the other party's authentication credentials.
-        """
-        handshaker = self._handshakeClientAsync(certParams=(certChain,
-                        privateKey), session=session, settings=settings,
-                        checker=checker, serverName=serverName, 
-                        nextProtos=nextProtos, reqTack=reqTack)
-        # The handshaker is a Python Generator which executes the handshake.
-        # It allows the handshake to be run in a "piecewise", asynchronous
-        # fashion, returning 1 when it is waiting to able to write, 0 when
-        # it is waiting to read.
-        #
-        # If 'is_async' is True, the generator is returned to the caller,
-        # otherwise it is executed to completion here.
-        if is_async:
-            return handshaker
-        for result in handshaker:
-            pass
-
-
-    def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
-                             session=None, settings=None, checker=None,
-                             nextProtos=None, serverName="", reqTack=True):
-
-        handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
-                certParams=certParams,
-                anonParams=anonParams,
-                session=session,
-                settings=settings,
-                serverName=serverName,
-                nextProtos=nextProtos,
-                reqTack=reqTack)
-        for result in self._handshakeWrapperAsync(handshaker, checker):
-            yield result
-
-
-    def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams,
-                               session, settings, serverName, nextProtos, reqTack):
-        
-        self._handshakeStart(client=True)
-
-        #Unpack parameters
-        srpUsername = None      # srpParams[0]
-        password = None         # srpParams[1]
-        clientCertChain = None  # certParams[0]
-        privateKey = None       # certParams[1]
-
-        # Allow only one of (srpParams, certParams, anonParams)
-        if srpParams:
-            assert(not certParams)
-            assert(not anonParams)
-            srpUsername, password = srpParams
-        if certParams:
-            assert(not srpParams)
-            assert(not anonParams)            
-            clientCertChain, privateKey = certParams
-        if anonParams:
-            assert(not srpParams)         
-            assert(not certParams)
-
-        #Validate parameters
-        if srpUsername and not password:
-            raise ValueError("Caller passed a username but no password")
-        if password and not srpUsername:
-            raise ValueError("Caller passed a password but no username")
-        if clientCertChain and not privateKey:
-            raise ValueError("Caller passed a certChain but no privateKey")
-        if privateKey and not clientCertChain:
-            raise ValueError("Caller passed a privateKey but no certChain")
-        if reqTack:
-            if not tackpyLoaded:
-                reqTack = False
-            if not settings or not settings.useExperimentalTackExtension:
-                reqTack = False
-        if nextProtos is not None:
-            if len(nextProtos) == 0:
-                raise ValueError("Caller passed no nextProtos")
-        
-        # Validates the settings and filters out any unsupported ciphers
-        # or crypto libraries that were requested        
-        if not settings:
-            settings = HandshakeSettings()
-        settings = settings._filter()
-
-        if settings.alpnProtos is not None:
-            if len(settings.alpnProtos) == 0:
-                raise ValueError("Caller passed no alpnProtos")
-
-        if clientCertChain:
-            if not isinstance(clientCertChain, X509CertChain):
-                raise ValueError("Unrecognized certificate type")
-            if "x509" not in settings.certificateTypes:
-                raise ValueError("Client certificate doesn't match "\
-                                 "Handshake Settings")
-                                  
-        if session:
-            # session.valid() ensures session is resumable and has 
-            # non-empty sessionID
-            if not session.valid():
-                session = None #ignore non-resumable sessions...
-            elif session.resumable: 
-                if session.srpUsername != srpUsername:
-                    raise ValueError("Session username doesn't match")
-                if session.serverName != serverName:
-                    raise ValueError("Session servername doesn't match")
-
-        #Add Faults to parameters
-        if srpUsername and self.fault == Fault.badUsername:
-            srpUsername += "GARBAGE"
-        if password and self.fault == Fault.badPassword:
-            password += "GARBAGE"
-
-        #Tentatively set the version to the client's minimum version.
-        #We'll use this for the ClientHello, and if an error occurs
-        #parsing the Server Hello, we'll use this version for the response
-        self.version = settings.maxVersion
-        
-        # OK Start sending messages!
-        # *****************************
-
-        # Send the ClientHello.
-        for result in self._clientSendClientHello(settings, session, 
-                                        srpUsername, srpParams, certParams,
-                                        anonParams, serverName, nextProtos,
-                                        reqTack):
-            if result in (0,1): yield result
-            else: break
-        clientHello = result
-        
-        #Get the ServerHello.
-        for result in self._clientGetServerHello(settings, clientHello):
-            if result in (0,1): yield result
-            else: break
-        serverHello = result
-        cipherSuite = serverHello.cipher_suite
-        
-        # Choose a matching Next Protocol from server list against ours
-        # (string or None)
-        nextProto = self._clientSelectNextProto(nextProtos, serverHello)
-
-        #If the server elected to resume the session, it is handled here.
-        for result in self._clientResume(session, serverHello, 
-                        clientHello.random, 
-                        settings.cipherImplementations,
-                        nextProto):
-            if result in (0,1): yield result
-            else: break
-        if result == "resumed_and_finished":
-            self._handshakeDone(resumed=True)
-            return
-
-        #If the server selected an SRP ciphersuite, the client finishes
-        #reading the post-ServerHello messages, then derives a
-        #premasterSecret and sends a corresponding ClientKeyExchange.
-        if cipherSuite in CipherSuite.srpAllSuites:
-            for result in self._clientSRPKeyExchange(\
-                    settings, cipherSuite, serverHello.certificate_type, 
-                    srpUsername, password,
-                    clientHello.random, serverHello.random, 
-                    serverHello.tackExt):                
-                if result in (0,1): yield result
-                else: break                
-            (premasterSecret, serverCertChain, tackExt) = result
-
-        #If the server selected an anonymous ciphersuite, the client
-        #finishes reading the post-ServerHello messages.
-        elif cipherSuite in CipherSuite.anonSuites:
-            for result in self._clientAnonKeyExchange(settings, cipherSuite,
-                                    clientHello.random, serverHello.random):
-                if result in (0,1): yield result
-                else: break
-            (premasterSecret, serverCertChain, tackExt) = result     
-               
-        #If the server selected a certificate-based RSA ciphersuite,
-        #the client finishes reading the post-ServerHello messages. If 
-        #a CertificateRequest message was sent, the client responds with
-        #a Certificate message containing its certificate chain (if any),
-        #and also produces a CertificateVerify message that signs the 
-        #ClientKeyExchange.
-        else:
-            for result in self._clientRSAKeyExchange(settings, cipherSuite,
-                                    clientCertChain, privateKey,
-                                    serverHello.certificate_type,
-                                    clientHello.random, serverHello.random,
-                                    serverHello.tackExt):
-                if result in (0,1): yield result
-                else: break
-            (premasterSecret, serverCertChain, clientCertChain, 
-             tackExt) = result
-                        
-        #After having previously sent a ClientKeyExchange, the client now
-        #initiates an exchange of Finished messages.
-        for result in self._clientFinished(premasterSecret,
-                            clientHello.random, 
-                            serverHello.random,
-                            cipherSuite, settings.cipherImplementations,
-                            nextProto):
-                if result in (0,1): yield result
-                else: break
-        masterSecret = result
-        
-        self.clientRandom = clientHello.random
-        self.serverRandom = serverHello.random
-
-        # Create the session object which is used for resumptions
-        self.session = Session()
-        self.session.create(masterSecret, serverHello.session_id, cipherSuite,
-            srpUsername, clientCertChain, serverCertChain,
-            tackExt, serverHello.tackExt!=None, serverName)
-        self._handshakeDone(resumed=False)
-
-
-    def _clientSendClientHello(self, settings, session, srpUsername,
-                                srpParams, certParams, anonParams, 
-                                serverName, nextProtos, reqTack):
-        #Initialize acceptable ciphersuites
-        cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
-        if srpParams:
-            cipherSuites += CipherSuite.getSrpAllSuites(settings)
-        elif certParams:
-            # TODO: Client DHE_RSA not supported.
-            # cipherSuites += CipherSuite.getDheCertSuites(settings)
-            cipherSuites += CipherSuite.getCertSuites(settings)
-        elif anonParams:
-            cipherSuites += CipherSuite.getAnonSuites(settings)
-        else:
-            assert(False)
-
-        #Initialize acceptable certificate types
-        certificateTypes = settings._getCertificateTypes()
-            
-        #Either send ClientHello (with a resumable session)...
-        if session and session.sessionID:
-            #If it's resumable, then its
-            #ciphersuite must be one of the acceptable ciphersuites
-            if session.cipherSuite not in cipherSuites:
-                raise ValueError("Session's cipher suite not consistent "\
-                                 "with parameters")
-            else:
-                clientHello = ClientHello()
-                clientHello.create(settings.maxVersion, getRandomBytes(32),
-                                   session.sessionID, cipherSuites,
-                                   certificateTypes, 
-                                   session.srpUsername,
-                                   reqTack, settings.alpnProtos,
-                                   nextProtos is not None,
-                                   session.serverName)
-
-        #Or send ClientHello (without)
-        else:
-            clientHello = ClientHello()
-            clientHello.create(settings.maxVersion, getRandomBytes(32),
-                               bytearray(0), cipherSuites,
-                               certificateTypes, 
-                               srpUsername,
-                               reqTack, settings.alpnProtos,
-                               nextProtos is not None,
-                               serverName)
-        for result in self._sendMsg(clientHello):
-            yield result
-        yield clientHello
-
-
-    def _clientGetServerHello(self, settings, clientHello):
-        for result in self._getMsg(ContentType.handshake,
-                                  HandshakeType.server_hello):
-            if result in (0,1): yield result
-            else: break
-        serverHello = result
-
-        #Get the server version.  Do this before anything else, so any
-        #error alerts will use the server's version
-        self.version = serverHello.server_version
-
-        #Future responses from server must use this version
-        self._versionCheck = True
-
-        #Check ServerHello
-        if serverHello.server_version < settings.minVersion:
-            for result in self._sendError(\
-                AlertDescription.protocol_version,
-                "Too old version: %s" % str(serverHello.server_version)):
-                yield result
-        if serverHello.server_version > settings.maxVersion:
-            for result in self._sendError(\
-                AlertDescription.protocol_version,
-                "Too new version: %s" % str(serverHello.server_version)):
-                yield result
-        if serverHello.cipher_suite not in clientHello.cipher_suites:
-            for result in self._sendError(\
-                AlertDescription.illegal_parameter,
-                "Server responded with incorrect ciphersuite"):
-                yield result
-        if serverHello.certificate_type not in clientHello.certificate_types:
-            for result in self._sendError(\
-                AlertDescription.illegal_parameter,
-                "Server responded with incorrect certificate type"):
-                yield result
-        if serverHello.compression_method != 0:
-            for result in self._sendError(\
-                AlertDescription.illegal_parameter,
-                "Server responded with incorrect compression method"):
-                yield result
-        if serverHello.tackExt:            
-            if not clientHello.tack:
-                for result in self._sendError(\
-                    AlertDescription.illegal_parameter,
-                    "Server responded with unrequested Tack Extension"):
-                    yield result
-        if serverHello.alpn_proto_selected and not clientHello.alpn_protos_advertised:
-            for result in self._sendError(\
-                AlertDescription.illegal_parameter,
-                "Server responded with unrequested ALPN Extension"):
-                yield result
-        if serverHello.alpn_proto_selected and serverHello.next_protos:
-            for result in self._sendError(\
-                AlertDescription.illegal_parameter,
-                "Server responded with both ALPN and NPN extension"):
-                yield result
-        if serverHello.next_protos and not clientHello.supports_npn:
-            for result in self._sendError(\
-                AlertDescription.illegal_parameter,
-                "Server responded with unrequested NPN Extension"):
-                yield result
-            if not serverHello.tackExt.verifySignatures():
-                for result in self._sendError(\
-                    AlertDescription.decrypt_error,
-                    "TackExtension contains an invalid signature"):
-                    yield result
-        yield serverHello
-
-    def _clientSelectNextProto(self, nextProtos, serverHello):
-        # nextProtos is None or non-empty list of strings
-        # serverHello.next_protos is None or possibly-empty list of strings
-        #
-        # !!! We assume the client may have specified nextProtos as a list of
-        # strings so we convert them to bytearrays (it's awkward to require
-        # the user to specify a list of bytearrays or "bytes", and in 
-        # Python 2.6 bytes() is just an alias for str() anyways...
-        if nextProtos is not None and serverHello.next_protos is not None:
-            for p in nextProtos:
-                if bytearray(p) in serverHello.next_protos:
-                    return bytearray(p)
-            else:
-                # If the client doesn't support any of server's protocols,
-                # or the server doesn't advertise any (next_protos == [])
-                # the client SHOULD select the first protocol it supports.
-                return bytearray(nextProtos[0])
-        return None
- 
-    def _clientResume(self, session, serverHello, clientRandom, 
-                      cipherImplementations, nextProto):
-        #If the server agrees to resume
-        if session and session.sessionID and \
-            serverHello.session_id == session.sessionID:
-
-            if serverHello.cipher_suite != session.cipherSuite:
-                for result in self._sendError(\
-                    AlertDescription.illegal_parameter,\
-                    "Server's ciphersuite doesn't match session"):
-                    yield result
-
-            #Calculate pending connection states
-            self._calcPendingStates(session.cipherSuite, 
-                                    session.masterSecret, 
-                                    clientRandom, serverHello.random, 
-                                    cipherImplementations)                                   
-
-            #Exchange ChangeCipherSpec and Finished messages
-            for result in self._getFinished(session.masterSecret):
-                yield result
-            for result in self._sendFinished(session.masterSecret, nextProto):
-                yield result
-
-            #Set the session for this connection
-            self.session = session
-            yield "resumed_and_finished"        
-            
-    def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType, 
-            srpUsername, password,
-            clientRandom, serverRandom, tackExt):
-
-        #If the server chose an SRP+RSA suite...
-        if cipherSuite in CipherSuite.srpCertSuites:
-            #Get Certificate, ServerKeyExchange, ServerHelloDone
-            for result in self._getMsg(ContentType.handshake,
-                    HandshakeType.certificate, certificateType):
-                if result in (0,1): yield result
-                else: break
-            serverCertificate = result
-        else:
-            serverCertificate = None
-
-        for result in self._getMsg(ContentType.handshake,
-                HandshakeType.server_key_exchange, cipherSuite):
-            if result in (0,1): yield result
-            else: break
-        serverKeyExchange = result
-
-        for result in self._getMsg(ContentType.handshake,
-                HandshakeType.server_hello_done):
-            if result in (0,1): yield result
-            else: break
-        serverHelloDone = result
-            
-        #Calculate SRP premaster secret
-        #Get and check the server's group parameters and B value
-        N = serverKeyExchange.srp_N
-        g = serverKeyExchange.srp_g
-        s = serverKeyExchange.srp_s
-        B = serverKeyExchange.srp_B
-
-        if (g,N) not in goodGroupParameters:
-            for result in self._sendError(\
-                    AlertDescription.insufficient_security,
-                    "Unknown group parameters"):
-                yield result
-        if numBits(N) < settings.minKeySize:
-            for result in self._sendError(\
-                    AlertDescription.insufficient_security,
-                    "N value is too small: %d" % numBits(N)):
-                yield result
-        if numBits(N) > settings.maxKeySize:
-            for result in self._sendError(\
-                    AlertDescription.insufficient_security,
-                    "N value is too large: %d" % numBits(N)):
-                yield result
-        if B % N == 0:
-            for result in self._sendError(\
-                    AlertDescription.illegal_parameter,
-                    "Suspicious B value"):
-                yield result
-
-        #Check the server's signature, if server chose an
-        #SRP+RSA suite
-        serverCertChain = None
-        if cipherSuite in CipherSuite.srpCertSuites:
-            #Hash ServerKeyExchange/ServerSRPParams
-            hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
-
-            #Extract signature bytes from ServerKeyExchange
-            sigBytes = serverKeyExchange.signature
-            if len(sigBytes) == 0:
-                for result in self._sendError(\
-                        AlertDescription.illegal_parameter,
-                        "Server sent an SRP ServerKeyExchange "\
-                        "message without a signature"):
-                    yield result
-
-            # Get server's public key from the Certificate message
-            # Also validate the chain against the ServerHello's TACKext (if any)
-            # If none, and a TACK cert is present, return its TACKext  
-            for result in self._clientGetKeyFromChain(serverCertificate,
-                                               settings, tackExt):
-                if result in (0,1): yield result
-                else: break
-            publicKey, serverCertChain, tackExt = result
-
-            #Verify signature
-            if not publicKey.verify(sigBytes, hashBytes):
-                for result in self._sendError(\
-                        AlertDescription.decrypt_error,
-                        "Signature failed to verify"):
-                    yield result
-
-        #Calculate client's ephemeral DH values (a, A)
-        a = bytesToNumber(getRandomBytes(32))
-        A = powMod(g, a, N)
-
-        #Calculate client's static DH values (x, v)
-        x = makeX(s, bytearray(srpUsername, "utf-8"),
-                    bytearray(password, "utf-8"))
-        v = powMod(g, x, N)
-
-        #Calculate u
-        u = makeU(N, A, B)
-
-        #Calculate premaster secret
-        k = makeK(N, g)
-        S = powMod((B - (k*v)) % N, a+(u*x), N)
-
-        if self.fault == Fault.badA:
-            A = N
-            S = 0
-            
-        premasterSecret = numberToByteArray(S)
-
-        #Send ClientKeyExchange
-        for result in self._sendMsg(\
-                ClientKeyExchange(cipherSuite).createSRP(A)):
-            yield result
-        yield (premasterSecret, serverCertChain, tackExt)
-                   
-
-    def _clientRSAKeyExchange(self, settings, cipherSuite, 
-                                clientCertChain, privateKey,
-                                certificateType,
-                                clientRandom, serverRandom,
-                                tackExt):
-
-        #Get Certificate[, CertificateRequest], ServerHelloDone
-        for result in self._getMsg(ContentType.handshake,
-                HandshakeType.certificate, certificateType):
-            if result in (0,1): yield result
-            else: break
-        serverCertificate = result
-
-        # Get CertificateRequest or ServerHelloDone
-        for result in self._getMsg(ContentType.handshake,
-                (HandshakeType.server_hello_done,
-                HandshakeType.certificate_request)):
-            if result in (0,1): yield result
-            else: break
-        msg = result
-        certificateRequest = None
-        if isinstance(msg, CertificateRequest):
-            certificateRequest = msg
-            # We got CertificateRequest, so this must be ServerHelloDone
-            for result in self._getMsg(ContentType.handshake,
-                    HandshakeType.server_hello_done):
-                if result in (0,1): yield result
-                else: break
-            serverHelloDone = result
-        elif isinstance(msg, ServerHelloDone):
-            serverHelloDone = msg
-
-        # Get server's public key from the Certificate message
-        # Also validate the chain against the ServerHello's TACKext (if any)
-        # If none, and a TACK cert is present, return its TACKext  
-        for result in self._clientGetKeyFromChain(serverCertificate,
-                                           settings, tackExt):
-            if result in (0,1): yield result
-            else: break
-        publicKey, serverCertChain, tackExt = result
-
-        #Calculate premaster secret
-        premasterSecret = getRandomBytes(48)
-        premasterSecret[0] = settings.maxVersion[0]
-        premasterSecret[1] = settings.maxVersion[1]
-
-        if self.fault == Fault.badPremasterPadding:
-            premasterSecret[0] = 5
-        if self.fault == Fault.shortPremasterSecret:
-            premasterSecret = premasterSecret[:-1]
-
-        #Encrypt premaster secret to server's public key
-        encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
-
-        #If client authentication was requested, send Certificate
-        #message, either with certificates or empty
-        if certificateRequest:
-            clientCertificate = Certificate(certificateType)
-
-            if clientCertChain:
-                #Check to make sure we have the same type of
-                #certificates the server requested
-                wrongType = False
-                if certificateType == CertificateType.x509:
-                    if not isinstance(clientCertChain, X509CertChain):
-                        wrongType = True
-                if wrongType:
-                    for result in self._sendError(\
-                            AlertDescription.handshake_failure,
-                            "Client certificate is of wrong type"):
-                        yield result
-
-                clientCertificate.create(clientCertChain)
-            for result in self._sendMsg(clientCertificate):
-                yield result
-        else:
-            #The server didn't request client auth, so we
-            #zeroize these so the clientCertChain won't be
-            #stored in the session.
-            privateKey = None
-            clientCertChain = None
-
-        #Send ClientKeyExchange
-        clientKeyExchange = ClientKeyExchange(cipherSuite,
-                                              self.version)
-        clientKeyExchange.createRSA(encryptedPreMasterSecret)
-        for result in self._sendMsg(clientKeyExchange):
-            yield result
-
-        #If client authentication was requested and we have a
-        #private key, send CertificateVerify
-        if certificateRequest and privateKey:
-            signatureAlgorithm = None
-            if self.version == (3,0):
-                masterSecret = calcMasterSecret(self.version,
-                                         premasterSecret,
-                                         clientRandom,
-                                         serverRandom,
-                                         b"", False)
-                verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
-            elif self.version in ((3,1), (3,2)):
-                verifyBytes = self._handshake_md5.digest() + \
-                                self._handshake_sha.digest()
-            elif self.version == (3,3):
-                # TODO: Signature algorithm negotiation not supported.
-                signatureAlgorithm = (HashAlgorithm.sha1, SignatureAlgorithm.rsa)
-                verifyBytes = self._handshake_sha.digest()
-                verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes)
-            if self.fault == Fault.badVerifyMessage:
-                verifyBytes[0] = ((verifyBytes[0]+1) % 256)
-            signedBytes = privateKey.sign(verifyBytes)
-            certificateVerify = CertificateVerify(self.version)
-            certificateVerify.create(signatureAlgorithm, signedBytes)
-            for result in self._sendMsg(certificateVerify):
-                yield result
-        yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
-
-    def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom, 
-                               serverRandom):
-        for result in self._getMsg(ContentType.handshake,
-                HandshakeType.server_key_exchange, cipherSuite):
-            if result in (0,1): yield result
-            else: break
-        serverKeyExchange = result
-
-        for result in self._getMsg(ContentType.handshake,
-                HandshakeType.server_hello_done):
-            if result in (0,1): yield result
-            else: break
-        serverHelloDone = result
-            
-        #calculate Yc
-        dh_p = serverKeyExchange.dh_p
-        dh_g = serverKeyExchange.dh_g
-        dh_Xc = bytesToNumber(getRandomBytes(32))
-        dh_Ys = serverKeyExchange.dh_Ys
-        dh_Yc = powMod(dh_g, dh_Xc, dh_p)
-        
-        #Send ClientKeyExchange
-        for result in self._sendMsg(\
-                ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
-            yield result
-            
-        #Calculate premaster secret
-        S = powMod(dh_Ys, dh_Xc, dh_p)
-        premasterSecret = numberToByteArray(S)
-                     
-        yield (premasterSecret, None, None)
-        
-    def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
-                        cipherSuite, cipherImplementations, nextProto):
-
-        masterSecret = calcMasterSecret(self.version, premasterSecret,
-                            clientRandom, serverRandom, b"", False)
-        self._calcPendingStates(cipherSuite, masterSecret, 
-                                clientRandom, serverRandom, 
-                                cipherImplementations)
-
-        #Exchange ChangeCipherSpec and Finished messages
-        for result in self._sendFinished(masterSecret, nextProto):
-            yield result
-        for result in self._getFinished(masterSecret, nextProto=nextProto):
-            yield result
-        yield masterSecret
-
-    def _clientGetKeyFromChain(self, certificate, settings, tackExt=None):
-        #Get and check cert chain from the Certificate message
-        certChain = certificate.certChain
-        if not certChain or certChain.getNumCerts() == 0:
-            for result in self._sendError(AlertDescription.illegal_parameter,
-                    "Other party sent a Certificate message without "\
-                    "certificates"):
-                yield result
-
-        #Get and check public key from the cert chain
-        publicKey = certChain.getEndEntityPublicKey()
-        if len(publicKey) < settings.minKeySize:
-            for result in self._sendError(AlertDescription.handshake_failure,
-                    "Other party's public key too small: %d" % len(publicKey)):
-                yield result
-        if len(publicKey) > settings.maxKeySize:
-            for result in self._sendError(AlertDescription.handshake_failure,
-                    "Other party's public key too large: %d" % len(publicKey)):
-                yield result
-        
-        # If there's no TLS Extension, look for a TACK cert
-        if tackpyLoaded:
-            if not tackExt:
-                tackExt = certChain.getTackExt()
-         
-            # If there's a TACK (whether via TLS or TACK Cert), check that it
-            # matches the cert chain   
-            if tackExt and tackExt.tacks:
-                for tack in tackExt.tacks: 
-                    if not certChain.checkTack(tack):
-                        for result in self._sendError(  
-                                AlertDescription.illegal_parameter,
-                                "Other party's TACK doesn't match their public key"):
-                                yield result
-
-        yield publicKey, certChain, tackExt
-
-
-    #*********************************************************
-    # Server Handshake Functions
-    #*********************************************************
-
-
-    def handshakeServer(self, verifierDB=None,
-                        certChain=None, privateKey=None, reqCert=False,
-                        sessionCache=None, settings=None, checker=None,
-                        reqCAs = None, reqCertTypes = None,
-                        tacks=None, activationFlags=0,
-                        nextProtos=None, anon=False,
-                        signedCertTimestamps=None,
-                        fallbackSCSV=False, ocspResponse=None):
-        """Perform a handshake in the role of server.
-
-        This function performs an SSL or TLS handshake.  Depending on
-        the arguments and the behavior of the client, this function can
-        perform an SRP, or certificate-based handshake.  It
-        can also perform a combined SRP and server-certificate
-        handshake.
-
-        Like any handshake function, this can be called on a closed
-        TLS connection, or on a TLS connection that is already open.
-        If called on an open connection it performs a re-handshake.
-        This function does not send a Hello Request message before
-        performing the handshake, so if re-handshaking is required,
-        the server must signal the client to begin the re-handshake
-        through some other means.
-
-        If the function completes without raising an exception, the
-        TLS connection will be open and available for data transfer.
-
-        If an exception is raised, the connection will have been
-        automatically closed (if it was ever open).
-
-        @type verifierDB: L{tlslite.verifierdb.VerifierDB}
-        @param verifierDB: A database of SRP password verifiers
-        associated with usernames.  If the client performs an SRP
-        handshake, the session's srpUsername attribute will be set.
-
-        @type certChain: L{tlslite.x509certchain.X509CertChain}
-        @param certChain: The certificate chain to be used if the
-        client requests server certificate authentication.
-
-        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
-        @param privateKey: The private key to be used if the client
-        requests server certificate authentication.
-
-        @type reqCert: bool
-        @param reqCert: Whether to request client certificate
-        authentication.  This only applies if the client chooses server
-        certificate authentication; if the client chooses SRP
-        authentication, this will be ignored.  If the client
-        performs a client certificate authentication, the sessions's
-        clientCertChain attribute will be set.
-
-        @type sessionCache: L{tlslite.sessioncache.SessionCache}
-        @param sessionCache: An in-memory cache of resumable sessions.
-        The client can resume sessions from this cache.  Alternatively,
-        if the client performs a full handshake, a new session will be
-        added to the cache.
-
-        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
-        @param settings: Various settings which can be used to control
-        the ciphersuites and SSL/TLS version chosen by the server.
-
-        @type checker: L{tlslite.checker.Checker}
-        @param checker: A Checker instance.  This instance will be
-        invoked to examine the other party's authentication
-        credentials, if the handshake completes succesfully.
-        
-        @type reqCAs: list of L{bytearray} of unsigned bytes
-        @param reqCAs: A collection of DER-encoded DistinguishedNames that
-        will be sent along with a certificate request. This does not affect
-        verification.        
-
-        @type reqCertTypes: list of int
-        @param reqCertTypes: A list of certificate_type values to be sent
-        along with a certificate request. This does not affect verification.
-
-        @type nextProtos: list of strings.
-        @param nextProtos: A list of upper layer protocols to expose to the
-        clients through the Next-Protocol Negotiation Extension, 
-        if they support it.
-
-        @type signedCertTimestamps: str
-        @param signedCertTimestamps: A SignedCertificateTimestampList (as a
-        binary 8-bit string) that will be sent as a TLS extension whenever
-        the client announces support for the extension.
-
-        @type fallbackSCSV: bool
-        @param fallbackSCSV: if true, the server will implement
-        TLS_FALLBACK_SCSV and thus reject connections using less than the
-        server's maximum TLS version that include this cipher suite.
-
-        @type ocspResponse: str
-        @param ocspResponse: An OCSP response (as a binary 8-bit string) that
-        will be sent stapled in the handshake whenever the client announces
-        support for the status_request extension.
-        Note that the response is sent independent of the ClientHello
-        status_request extension contents, and is thus only meant for testing
-        environments. Real OCSP stapling is more complicated as it requires
-        choosing a suitable response based on the ClientHello status_request
-        extension contents.
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        @raise tlslite.errors.TLSAuthenticationError: If the checker
-        doesn't like the other party's authentication credentials.
-        """
-        for result in self.handshakeServerAsync(verifierDB,
-                certChain, privateKey, reqCert, sessionCache, settings,
-                checker, reqCAs, reqCertTypes,
-                tacks=tacks, activationFlags=activationFlags, 
-                nextProtos=nextProtos, anon=anon,
-                signedCertTimestamps=signedCertTimestamps,
-                fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
-            pass
-
-
-    def handshakeServerAsync(self, verifierDB=None,
-                             certChain=None, privateKey=None, reqCert=False,
-                             sessionCache=None, settings=None, checker=None,
-                             reqCAs=None, reqCertTypes=None,
-                             tacks=None, activationFlags=0,
-                             nextProtos=None, anon=False,
-                             signedCertTimestamps=None,
-                             fallbackSCSV=False,
-                             ocspResponse=None
-                             ):
-        """Start a server handshake operation on the TLS connection.
-
-        This function returns a generator which behaves similarly to
-        handshakeServer().  Successive invocations of the generator
-        will return 0 if it is waiting to read from the socket, 1 if it is
-        waiting to write to the socket, or it will raise StopIteration
-        if the handshake operation is complete.
-
-        @rtype: iterable
-        @return: A generator; see above for details.
-        """
-        handshaker = self._handshakeServerAsyncHelper(\
-            verifierDB=verifierDB, certChain=certChain,
-            privateKey=privateKey, reqCert=reqCert,
-            sessionCache=sessionCache, settings=settings, 
-            reqCAs=reqCAs, reqCertTypes=reqCertTypes,
-            tacks=tacks, activationFlags=activationFlags, 
-            nextProtos=nextProtos, anon=anon,
-            signedCertTimestamps=signedCertTimestamps,
-            fallbackSCSV=fallbackSCSV,
-            ocspResponse=ocspResponse)
-        for result in self._handshakeWrapperAsync(handshaker, checker):
-            yield result
-        if settings and settings.alertAfterHandshake:
-            for result in self._sendError(AlertDescription.internal_error,
-                                          "Spurious alert"):
-                yield result
-
-
-    def _handshakeServerAsyncHelper(self, verifierDB,
-                             certChain, privateKey, reqCert, sessionCache,
-                             settings, reqCAs, reqCertTypes,
-                             tacks, activationFlags, 
-                             nextProtos, anon,
-                             signedCertTimestamps, fallbackSCSV,
-                             ocspResponse):
-
-        self._handshakeStart(client=False)
-
-        if (not verifierDB) and (not certChain) and not anon:
-            raise ValueError("Caller passed no authentication credentials")
-        if certChain and not privateKey:
-            raise ValueError("Caller passed a certChain but no privateKey")
-        if privateKey and not certChain:
-            raise ValueError("Caller passed a privateKey but no certChain")
-        if reqCAs and not reqCert:
-            raise ValueError("Caller passed reqCAs but not reqCert")            
-        if reqCertTypes and not reqCert:
-            raise ValueError("Caller passed reqCertTypes but not reqCert")
-        if certChain and not isinstance(certChain, X509CertChain):
-            raise ValueError("Unrecognized certificate type")
-        if activationFlags and not tacks:
-            raise ValueError("Nonzero activationFlags requires tacks")
-        if tacks:
-            if not tackpyLoaded:
-                raise ValueError("tackpy is not loaded")
-            if not settings or not settings.useExperimentalTackExtension:
-                raise ValueError("useExperimentalTackExtension not enabled")
-        if signedCertTimestamps and not certChain:
-            raise ValueError("Caller passed signedCertTimestamps but no "
-                             "certChain")
-
-        if not settings:
-            settings = HandshakeSettings()
-        settings = settings._filter()
-        
-        # OK Start exchanging messages
-        # ******************************
-        
-        # Handle ClientHello and resumption
-        for result in self._serverGetClientHello(settings, certChain,\
-                                            verifierDB, sessionCache,
-                                            anon, fallbackSCSV):
-            if result in (0,1): yield result
-            elif result == None:
-                self._handshakeDone(resumed=True)                
-                return # Handshake was resumed, we're done 
-            else: break
-        (clientHello, cipherSuite) = result
-
-        # Save the ClientHello for external code to query.
-        self.clientHello = clientHello
-        
-        #If not a resumption...
-
-        # Create the ServerHello message
-        if sessionCache:
-            sessionID = getRandomBytes(32)
-        else:
-            sessionID = bytearray(0)
-        
-        alpn_proto_selected = None
-        if (clientHello.alpn_protos_advertised is not None
-                and settings.alpnProtos is not None):
-            for proto in settings.alpnProtos:
-                if proto in clientHello.alpn_protos_advertised:
-                    alpn_proto_selected = proto
-                    nextProtos = None
-                    break;
-
-        if not clientHello.supports_npn:
-            nextProtos = None
-
-        # If not doing a certificate-based suite, discard the TACK
-        if not cipherSuite in CipherSuite.certAllSuites:
-            tacks = None
-
-        # Prepare a TACK Extension if requested
-        if clientHello.tack:
-            tackExt = TackExtension.create(tacks, activationFlags)
-        else:
-            tackExt = None
-        serverRandom = getRandomBytes(32)
-        # See https://tools.ietf.org/html/rfc8446#section-4.1.3
-        if settings.simulateTLS13Downgrade:
-            serverRandom = serverRandom[:24] + \
-                bytearray(b"\x44\x4f\x57\x4e\x47\x52\x44\x01")
-        elif settings.simulateTLS12Downgrade:
-            serverRandom = serverRandom[:24] + \
-                bytearray(b"\x44\x4f\x57\x4e\x47\x52\x44\x00")
-        serverHello = ServerHello()
-        serverHello.create(self.version, serverRandom, sessionID, \
-                            cipherSuite, CertificateType.x509, tackExt,
-                            alpn_proto_selected,
-                            nextProtos)
-        serverHello.channel_id = \
-            clientHello.channel_id and settings.enableChannelID
-        serverHello.extended_master_secret = \
-            clientHello.extended_master_secret and \
-            settings.enableExtendedMasterSecret
-        for param in clientHello.tb_client_params:
-            if param in settings.supportedTokenBindingParams:
-                serverHello.tb_params = param
-                break
-        if clientHello.support_signed_cert_timestamps:
-            serverHello.signed_cert_timestamps = signedCertTimestamps
-        if clientHello.status_request:
-            serverHello.status_request = ocspResponse
-        if clientHello.ri:
-            serverHello.send_ri = True
-
-        # Perform the SRP key exchange
-        clientCertChain = None
-        if cipherSuite in CipherSuite.srpAllSuites:
-            for result in self._serverSRPKeyExchange(clientHello, serverHello, 
-                                    verifierDB, cipherSuite, 
-                                    privateKey, certChain):
-                if result in (0,1): yield result
-                else: break
-            premasterSecret = result
-
-        # Perform a certificate-based key exchange
-        elif cipherSuite in CipherSuite.certAllSuites:
-            if cipherSuite in CipherSuite.certSuites:
-                keyExchange = RSAKeyExchange(cipherSuite,
-                                             clientHello,
-                                             serverHello,
-                                             privateKey)
-            elif cipherSuite in CipherSuite.dheCertSuites:
-                keyExchange = DHE_RSAKeyExchange(cipherSuite,
-                                                 clientHello,
-                                                 serverHello,
-                                                 privateKey)
-            elif cipherSuite in CipherSuite.ecdheCertSuites:
-                keyExchange = ECDHE_RSAKeyExchange(cipherSuite,
-                                                   clientHello,
-                                                   serverHello,
-                                                   privateKey)
-            else:
-                assert(False)
-            for result in self._serverCertKeyExchange(clientHello, serverHello, 
-                                        certChain, keyExchange,
-                                        reqCert, reqCAs, reqCertTypes, cipherSuite,
-                                        settings, ocspResponse):
-                if result in (0,1): yield result
-                else: break
-            (premasterSecret, clientCertChain) = result
-
-        # Perform anonymous Diffie Hellman key exchange
-        elif cipherSuite in CipherSuite.anonSuites:
-            for result in self._serverAnonKeyExchange(clientHello, serverHello, 
-                                        cipherSuite, settings):
-                if result in (0,1): yield result
-                else: break
-            premasterSecret = result
-        
-        else:
-            assert(False)
-                        
-        # Exchange Finished messages      
-        for result in self._serverFinished(premasterSecret, 
-                                clientHello.random, serverHello.random,
-                                cipherSuite, settings.cipherImplementations,
-                                nextProtos, serverHello.channel_id,
-                                serverHello.extended_master_secret):
-                if result in (0,1): yield result
-                else: break
-        masterSecret = result
-
-        self.clientRandom = clientHello.random
-        self.serverRandom = serverHello.random
-
-        #Create the session object
-        self.session = Session()
-        if cipherSuite in CipherSuite.certAllSuites:        
-            serverCertChain = certChain
-        else:
-            serverCertChain = None
-        srpUsername = None
-        serverName = None
-        if clientHello.srp_username:
-            srpUsername = clientHello.srp_username.decode("utf-8")
-        if clientHello.server_name:
-            serverName = clientHello.server_name.decode("utf-8")
-        self.session.create(masterSecret, serverHello.session_id, cipherSuite,
-            srpUsername, clientCertChain, serverCertChain,
-            tackExt, serverHello.tackExt!=None, serverName)
-            
-        #Add the session object to the session cache
-        if sessionCache and sessionID:
-            sessionCache[sessionID] = self.session
-
-        self._handshakeDone(resumed=False)
-
-
-    def _isIntolerant(self, settings, clientHello):
-        if settings.tlsIntolerant is None:
-            return False
-        clientVersion = clientHello.client_version
-        if clientHello.has_supported_versions:
-            clientVersion = (3, 4)
-        return clientVersion >= settings.tlsIntolerant
-
-
-    def _serverGetClientHello(self, settings, certChain, verifierDB,
-                                sessionCache, anon, fallbackSCSV):
-        #Tentatively set version to most-desirable version, so if an error
-        #occurs parsing the ClientHello, this is what we'll use for the
-        #error alert
-        self.version = settings.maxVersion
-
-        #Get ClientHello
-        for result in self._getMsg(ContentType.handshake,
-                                   HandshakeType.client_hello):
-            if result in (0,1): yield result
-            else: break
-        clientHello = result
-
-        #If client's version is too low, reject it
-        if clientHello.client_version < settings.minVersion:
-            self.version = settings.minVersion
-            for result in self._sendError(\
-                  AlertDescription.protocol_version,
-                  "Too old version: %s" % str(clientHello.client_version)):
-                yield result
-
-        #If simulating TLS intolerance, reject certain TLS versions.
-        elif self._isIntolerant(settings, clientHello):
-            if settings.tlsIntoleranceType == "alert":
-                for result in self._sendError(\
-                    AlertDescription.handshake_failure):
-                    yield result
-            elif settings.tlsIntoleranceType == "close":
-                self._abruptClose()
-                raise TLSUnsupportedError("Simulating version intolerance")
-            elif settings.tlsIntoleranceType == "reset":
-                self._abruptClose(reset=True)
-                raise TLSUnsupportedError("Simulating version intolerance")
-            else:
-                raise ValueError("Unknown intolerance type: '%s'" %
-                                 settings.tlsIntoleranceType)
-
-        #If client's version is too high, propose my highest version
-        elif clientHello.client_version > settings.maxVersion:
-            self.version = settings.maxVersion
-
-        #Detect if the client performed an inappropriate fallback.
-        elif fallbackSCSV and clientHello.client_version < settings.maxVersion:
-            self.version = clientHello.client_version
-            if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites:
-                for result in self._sendError(\
-                        AlertDescription.inappropriate_fallback):
-                    yield result
-
-        else:
-            #Set the version to the client's version
-            self.version = clientHello.client_version
-
-        #Initialize acceptable cipher suites
-        cipherSuites = []
-        if verifierDB:
-            if certChain:
-                cipherSuites += \
-                    CipherSuite.getSrpCertSuites(settings, self.version)
-            cipherSuites += CipherSuite.getSrpSuites(settings, self.version)
-        elif certChain:
-            cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.version)
-            cipherSuites += CipherSuite.getDheCertSuites(settings, self.version)
-            cipherSuites += CipherSuite.getCertSuites(settings, self.version)
-        elif anon:
-            cipherSuites += CipherSuite.getAnonSuites(settings, self.version)
-        else:
-            assert(False)
-
-        alpn_proto_selected = None
-        if (clientHello.alpn_protos_advertised is not None
-                and settings.alpnProtos is not None):
-            for proto in settings.alpnProtos:
-                if proto in clientHello.alpn_protos_advertised:
-                    alpn_proto_selected = proto
-                    break;
-
-        #If resumption was requested and we have a session cache...
-        if clientHello.session_id and sessionCache:
-            session = None
-
-            #Check in the session cache
-            if sessionCache and not session:
-                try:
-                    session = sessionCache[clientHello.session_id]
-                    if not session.resumable:
-                        raise AssertionError()
-                    #Check for consistency with ClientHello
-                    if session.cipherSuite not in cipherSuites:
-                        for result in self._sendError(\
-                                AlertDescription.handshake_failure):
-                            yield result
-                    if session.cipherSuite not in clientHello.cipher_suites:
-                        for result in self._sendError(\
-                                AlertDescription.handshake_failure):
-                            yield result
-                    if clientHello.srp_username:
-                        if not session.srpUsername or \
-                            clientHello.srp_username != bytearray(session.srpUsername, "utf-8"):
-                            for result in self._sendError(\
-                                    AlertDescription.handshake_failure):
-                                yield result
-                    if clientHello.server_name:
-                        if not session.serverName or \
-                            clientHello.server_name != bytearray(session.serverName, "utf-8"):
-                            for result in self._sendError(\
-                                    AlertDescription.handshake_failure):
-                                yield result                    
-                except KeyError:
-                    pass
-
-            #If a session is found..
-            if session:
-                #Send ServerHello
-                serverHello = ServerHello()
-                serverHello.create(self.version, getRandomBytes(32),
-                                   session.sessionID, session.cipherSuite,
-                                   CertificateType.x509, None,
-                                   alpn_proto_selected, None)
-                serverHello.extended_master_secret = \
-                    clientHello.extended_master_secret and \
-                    settings.enableExtendedMasterSecret
-                for param in clientHello.tb_client_params:
-                    if param in settings.supportedTokenBindingParams:
-                          serverHello.tb_params = param
-                          break
-                if clientHello.ri:
-                    serverHello.send_ri = True
-                for result in self._sendMsg(serverHello):
-                    yield result
-
-                #From here on, the client's messages must have right version
-                self._versionCheck = True
-
-                #Calculate pending connection states
-                self._calcPendingStates(session.cipherSuite, 
-                                        session.masterSecret,
-                                        clientHello.random, 
-                                        serverHello.random,
-                                        settings.cipherImplementations)
-
-                #Exchange ChangeCipherSpec and Finished messages
-                for result in self._sendFinished(session.masterSecret):
-                    yield result
-                for result in self._getFinished(session.masterSecret):
-                    yield result
-
-                #Set the session
-                self.session = session
-                    
-                self.clientRandom = clientHello.random
-                self.serverRandom = serverHello.random
-                yield None # Handshake done!
-
-        #Calculate the first cipher suite intersection.
-        #This is the 'privileged' ciphersuite.  We'll use it if we're
-        #doing a new negotiation.  In fact,
-        #the only time we won't use it is if we're resuming a
-        #session, in which case we use the ciphersuite from the session.
-        #
-        #Given the current ciphersuite ordering, this means we prefer SRP
-        #over non-SRP.
-        for cipherSuite in cipherSuites:
-            if cipherSuite in clientHello.cipher_suites:
-                break
-        else:
-            for result in self._sendError(\
-                    AlertDescription.handshake_failure,
-                    "No mutual ciphersuite"):
-                yield result
-        if cipherSuite in CipherSuite.srpAllSuites and \
-                            not clientHello.srp_username:
-            for result in self._sendError(\
-                    AlertDescription.unknown_psk_identity,
-                    "Client sent a hello, but without the SRP username"):
-                yield result
-           
-        #If an RSA suite is chosen, check for certificate type intersection
-        if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \
-                                not in clientHello.certificate_types:
-            for result in self._sendError(\
-                    AlertDescription.handshake_failure,
-                    "the client doesn't support my certificate type"):
-                yield result
-
-        # If resumption was not requested, or
-        # we have no session cache, or
-        # the client's session_id was not found in cache:
-        yield (clientHello, cipherSuite)
-
-    def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, 
-                                cipherSuite, privateKey, serverCertChain):
-
-        srpUsername = clientHello.srp_username.decode("utf-8")
-        self.allegedSrpUsername = srpUsername
-        #Get parameters from username
-        try:
-            entry = verifierDB[srpUsername]
-        except KeyError:
-            for result in self._sendError(\
-                    AlertDescription.unknown_psk_identity):
-                yield result
-        (N, g, s, v) = entry
-
-        #Calculate server's ephemeral DH values (b, B)
-        b = bytesToNumber(getRandomBytes(32))
-        k = makeK(N, g)
-        B = (powMod(g, b, N) + (k*v)) % N
-
-        #Create ServerKeyExchange, signing it if necessary
-        serverKeyExchange = ServerKeyExchange(cipherSuite, self.version)
-        serverKeyExchange.createSRP(N, g, s, B)
-        if cipherSuite in CipherSuite.srpCertSuites:
-            hashBytes = serverKeyExchange.hash(clientHello.random,
-                                               serverHello.random)
-            serverKeyExchange.signature = privateKey.sign(hashBytes)
-
-        #Send ServerHello[, Certificate], ServerKeyExchange,
-        #ServerHelloDone
-        msgs = []
-        msgs.append(serverHello)
-        if cipherSuite in CipherSuite.srpCertSuites:
-            certificateMsg = Certificate(CertificateType.x509)
-            certificateMsg.create(serverCertChain)
-            msgs.append(certificateMsg)
-        msgs.append(serverKeyExchange)
-        msgs.append(ServerHelloDone())
-        for result in self._sendMsgs(msgs):
-            yield result
-
-        #From here on, the client's messages must have the right version
-        self._versionCheck = True
-
-        #Get and check ClientKeyExchange
-        for result in self._getMsg(ContentType.handshake,
-                                  HandshakeType.client_key_exchange,
-                                  cipherSuite):
-            if result in (0,1): yield result
-            else: break
-        clientKeyExchange = result
-        A = clientKeyExchange.srp_A
-        if A % N == 0:
-            for result in self._sendError(AlertDescription.illegal_parameter,
-                    "Suspicious A value"):
-                yield result
-            assert(False) # Just to ensure we don't fall through somehow
-
-        #Calculate u
-        u = makeU(N, A, B)
-
-        #Calculate premaster secret
-        S = powMod((A * powMod(v,u,N)) % N, b, N)
-        premasterSecret = numberToByteArray(S)
-        
-        yield premasterSecret
-
-
-    def _serverCertKeyExchange(self, clientHello, serverHello, 
-                                serverCertChain, keyExchange,
-                                reqCert, reqCAs, reqCertTypes, cipherSuite,
-                                settings, ocspResponse):
-        #Send ServerHello, Certificate[, ServerKeyExchange]
-        #[, CertificateRequest], ServerHelloDone
-        msgs = []
-
-        # If we verify a client cert chain, return it
-        clientCertChain = None
-
-        msgs.append(serverHello)
-        msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
-        if serverHello.status_request:
-            msgs.append(CertificateStatus().create(ocspResponse))
-        serverKeyExchange = keyExchange.makeServerKeyExchange()
-        if serverKeyExchange is not None:
-            msgs.append(serverKeyExchange)
-        if reqCert:
-            reqCAs = reqCAs or []
-            #Apple's Secure Transport library rejects empty certificate_types,
-            #so default to rsa_sign.
-            reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
-            #Only SHA-1 + RSA is supported.
-            sigAlgs = [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)]
-            msgs.append(CertificateRequest(self.version).create(reqCertTypes,
-                                                                reqCAs,
-                                                                sigAlgs))
-        msgs.append(ServerHelloDone())
-        for result in self._sendMsgs(msgs):
-            yield result
-
-        #From here on, the client's messages must have the right version
-        self._versionCheck = True
-
-        #Get [Certificate,] (if was requested)
-        if reqCert:
-            if self.version == (3,0):
-                for result in self._getMsg((ContentType.handshake,
-                                           ContentType.alert),
-                                           HandshakeType.certificate,
-                                           CertificateType.x509):
-                    if result in (0,1): yield result
-                    else: break
-                msg = result
-
-                if isinstance(msg, Alert):
-                    #If it's not a no_certificate alert, re-raise
-                    alert = msg
-                    if alert.description != \
-                            AlertDescription.no_certificate:
-                        self._shutdown(False)
-                        raise TLSRemoteAlert(alert)
-                elif isinstance(msg, Certificate):
-                    clientCertificate = msg
-                    if clientCertificate.certChain and \
-                            clientCertificate.certChain.getNumCerts()!=0:
-                        clientCertChain = clientCertificate.certChain
-                else:
-                    raise AssertionError()
-            elif self.version in ((3,1), (3,2), (3,3)):
-                for result in self._getMsg(ContentType.handshake,
-                                          HandshakeType.certificate,
-                                          CertificateType.x509):
-                    if result in (0,1): yield result
-                    else: break
-                clientCertificate = result
-                if clientCertificate.certChain and \
-                        clientCertificate.certChain.getNumCerts()!=0:
-                    clientCertChain = clientCertificate.certChain
-            else:
-                raise AssertionError()
-
-        #Get ClientKeyExchange
-        for result in self._getMsg(ContentType.handshake,
-                                  HandshakeType.client_key_exchange,
-                                  cipherSuite):
-            if result in (0,1): yield result
-            else: break
-        clientKeyExchange = result
-
-        #Process ClientKeyExchange
-        try:
-            premasterSecret = \
-                keyExchange.processClientKeyExchange(clientKeyExchange)
-        except alert as TLSLocalAlert:
-            for result in self._sendError(alert.description, alert.message):
-                yield result
-
-        #Get and check CertificateVerify, if relevant
-        if clientCertChain:
-            if self.version == (3,0):
-                masterSecret = calcMasterSecret(self.version, premasterSecret,
-                                         clientHello.random, serverHello.random,
-                                         b"", False)
-                verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
-            elif self.version in ((3,1), (3,2)):
-                verifyBytes = self._handshake_md5.digest() + \
-                                self._handshake_sha.digest()
-            elif self.version == (3,3):
-                verifyBytes = self._handshake_sha.digest()
-                verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes)
-            for result in self._getMsg(ContentType.handshake,
-                                      HandshakeType.certificate_verify):
-                if result in (0,1): yield result
-                else: break
-            certificateVerify = result
-            publicKey = clientCertChain.getEndEntityPublicKey()
-            if len(publicKey) < settings.minKeySize:
-                for result in self._sendError(\
-                        AlertDescription.handshake_failure,
-                        "Client's public key too small: %d" % len(publicKey)):
-                    yield result
-
-            if len(publicKey) > settings.maxKeySize:
-                for result in self._sendError(\
-                        AlertDescription.handshake_failure,
-                        "Client's public key too large: %d" % len(publicKey)):
-                    yield result
-
-            if not publicKey.verify(certificateVerify.signature, verifyBytes):
-                for result in self._sendError(\
-                        AlertDescription.decrypt_error,
-                        "Signature failed to verify"):
-                    yield result
-        yield (premasterSecret, clientCertChain)
-
-
-    def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite, 
-                               settings):
-        # Calculate DH p, g, Xs, Ys
-        dh_p = getRandomSafePrime(32, False)
-        dh_g = getRandomNumber(2, dh_p)        
-        dh_Xs = bytesToNumber(getRandomBytes(32))        
-        dh_Ys = powMod(dh_g, dh_Xs, dh_p)
-
-        #Create ServerKeyExchange
-        serverKeyExchange = ServerKeyExchange(cipherSuite, self.version)
-        serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
-        
-        #Send ServerHello[, Certificate], ServerKeyExchange,
-        #ServerHelloDone  
-        msgs = []
-        msgs.append(serverHello)
-        msgs.append(serverKeyExchange)
-        msgs.append(ServerHelloDone())
-        for result in self._sendMsgs(msgs):
-            yield result
-        
-        #From here on, the client's messages must have the right version
-        self._versionCheck = True
-        
-        #Get and check ClientKeyExchange
-        for result in self._getMsg(ContentType.handshake,
-                                   HandshakeType.client_key_exchange,
-                                   cipherSuite):
-            if result in (0,1):
-                yield result 
-            else:
-                break
-        clientKeyExchange = result
-        dh_Yc = clientKeyExchange.dh_Yc
-        
-        if dh_Yc % dh_p == 0:
-            for result in self._sendError(AlertDescription.illegal_parameter,
-                    "Suspicious dh_Yc value"):
-                yield result
-            assert(False) # Just to ensure we don't fall through somehow            
-
-        #Calculate premaster secre
-        S = powMod(dh_Yc,dh_Xs,dh_p)
-        premasterSecret = numberToByteArray(S)
-        
-        yield premasterSecret
-
-
-    def _serverFinished(self,  premasterSecret, clientRandom, serverRandom,
-                        cipherSuite, cipherImplementations, nextProtos,
-                        doingChannelID, useExtendedMasterSecret):
-        masterSecret = calcMasterSecret(self.version, premasterSecret,
-                                      clientRandom, serverRandom,
-                                      self._ems_handshake_hash,
-                                      useExtendedMasterSecret)
-        
-        #Calculate pending connection states
-        self._calcPendingStates(cipherSuite, masterSecret, 
-                                clientRandom, serverRandom,
-                                cipherImplementations)
-
-        #Exchange ChangeCipherSpec and Finished messages
-        for result in self._getFinished(masterSecret, 
-                        expect_next_protocol=nextProtos is not None,
-                        expect_channel_id=doingChannelID):
-            yield result
-
-        for result in self._sendFinished(masterSecret):
-            yield result
-        
-        yield masterSecret        
-
-
-    #*********************************************************
-    # Shared Handshake Functions
-    #*********************************************************
-
-
-    def _sendFinished(self, masterSecret, nextProto=None):
-        #Send ChangeCipherSpec
-        for result in self._sendMsg(ChangeCipherSpec()):
-            yield result
-
-        #Switch to pending write state
-        self._changeWriteState()
-
-        if nextProto is not None:
-            nextProtoMsg = NextProtocol().create(nextProto)
-            for result in self._sendMsg(nextProtoMsg):
-                yield result
-
-        #Calculate verification data
-        verifyData = self._calcFinished(masterSecret, True)
-        if self.fault == Fault.badFinished:
-            verifyData[0] = (verifyData[0]+1)%256
-
-        #Send Finished message under new state
-        finished = Finished(self.version).create(verifyData)
-        for result in self._sendMsg(finished):
-            yield result
-
-    def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None,
-                     expect_channel_id=False):
-        #Get and check ChangeCipherSpec
-        for result in self._getMsg(ContentType.change_cipher_spec):
-            if result in (0,1):
-                yield result
-        changeCipherSpec = result
-
-        if changeCipherSpec.type != 1:
-            for result in self._sendError(AlertDescription.illegal_parameter,
-                                         "ChangeCipherSpec type incorrect"):
-                yield result
-
-        #Switch to pending read state
-        self._changeReadState()
-
-        #Server Finish - Are we waiting for a next protocol echo? 
-        if expect_next_protocol:
-            for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol):
-                if result in (0,1):
-                    yield result
-            if result is None:
-                for result in self._sendError(AlertDescription.unexpected_message,
-                                             "Didn't get NextProtocol message"):
-                    yield result
-
-            self.next_proto = result.next_proto
-        else:
-            self.next_proto = None
-
-        #Client Finish - Only set the next_protocol selected in the connection
-        if nextProto:
-            self.next_proto = nextProto
-
-        #Server Finish - Are we waiting for a EncryptedExtensions?
-        if expect_channel_id:
-            for result in self._getMsg(ContentType.handshake, HandshakeType.encrypted_extensions):
-                if result in (0,1):
-                    yield result
-            if result is None:
-                for result in self._sendError(AlertDescription.unexpected_message,
-                                             "Didn't get EncryptedExtensions message"):
-                    yield result
-            encrypted_extensions = result
-            self.channel_id = result.channel_id_key
-        else:
-            self.channel_id = None
-
-        #Calculate verification data
-        verifyData = self._calcFinished(masterSecret, False)
-
-        #Get and check Finished message under new state
-        for result in self._getMsg(ContentType.handshake,
-                                  HandshakeType.finished):
-            if result in (0,1):
-                yield result
-        finished = result
-        if finished.verify_data != verifyData:
-            for result in self._sendError(AlertDescription.decrypt_error,
-                                         "Finished message is incorrect"):
-                yield result
-
-    def _calcFinished(self, masterSecret, send=True):
-        if self.version == (3,0):
-            if (self._client and send) or (not self._client and not send):
-                senderStr = b"\x43\x4C\x4E\x54"
-            else:
-                senderStr = b"\x53\x52\x56\x52"
-
-            verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr)
-            return verifyData
-
-        elif self.version in ((3,1), (3,2)):
-            if (self._client and send) or (not self._client and not send):
-                label = b"client finished"
-            else:
-                label = b"server finished"
-
-            handshakeHashes = self._handshake_md5.digest() + \
-                                self._handshake_sha.digest()
-            verifyData = PRF(masterSecret, label, handshakeHashes, 12)
-            return verifyData
-        elif self.version == (3,3):
-            if (self._client and send) or (not self._client and not send):
-                label = b"client finished"
-            else:
-                label = b"server finished"
-
-            handshakeHashes = self._handshake_sha256.digest()
-            verifyData = PRF_1_2(masterSecret, label, handshakeHashes, 12)
-            return verifyData
-        else:
-            raise AssertionError()
-
-
-    def _handshakeWrapperAsync(self, handshaker, checker):
-        if not self.fault:
-            try:
-                for result in handshaker:
-                    yield result
-                if checker:
-                    try:
-                        checker(self)
-                    except TLSAuthenticationError:
-                        alert = Alert().create(AlertDescription.close_notify,
-                                               AlertLevel.fatal)
-                        for result in self._sendMsg(alert):
-                            yield result
-                        raise
-            except GeneratorExit:
-                raise
-            except TLSAlert as alert:
-                if not self.fault:
-                    raise
-                if alert.description not in Fault.faultAlerts[self.fault]:
-                    raise TLSFaultError(str(alert))
-                else:
-                    pass
-            except:
-                self._shutdown(False)
-                raise
-
-
-    def exportKeyingMaterial(self, label, context, use_context, length):
-        """Returns the exported keying material as defined in RFC 5705."""
-
-        seed = self.clientRandom + self.serverRandom
-        if use_context:
-            if len(context) > 65535:
-                raise ValueError("Context is too long")
-            seed += bytearray(2)
-            seed[len(seed) - 2] = len(context) >> 8
-            seed[len(seed) - 1] = len(context) & 0xFF
-            seed += context
-        if self.version in ((3,1), (3,2)):
-            return PRF(self.session.masterSecret, label, seed, length)
-        elif self.version == (3,3):
-            return PRF_1_2(self.session.masterSecret, label, seed, length)
-        else:
-            raise AssertionError()
diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
deleted file mode 100644
index d2320b8..0000000
--- a/third_party/tlslite/tlslite/tlsrecordlayer.py
+++ /dev/null
@@ -1,1268 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Google (adapted by Sam Rushing) - NPN support
-#   Martin von Loewis - python 3 port
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Helper class for TLSConnection."""
-from __future__ import generators
-
-from .utils.compat import *
-from .utils.cryptomath import *
-from .utils.cipherfactory import createAESGCM, createAES, createRC4, \
-     createTripleDES
-from .utils.codec import *
-from .errors import *
-from .messages import *
-from .mathtls import *
-from .constants import *
-from .utils.cryptomath import getRandomBytes
-
-import socket
-import struct
-import errno
-import traceback
-
-class _ConnectionState(object):
-    def __init__(self):
-        self.macContext = None
-        self.encContext = None
-        self.seqnum = 0
-
-    def getSeqNumBytes(self):
-        w = Writer()
-        w.add(self.seqnum, 8)
-        self.seqnum += 1
-        return w.bytes
-
-
-class TLSRecordLayer(object):
-    """
-    This class handles data transmission for a TLS connection.
-
-    Its only subclass is L{tlslite.TLSConnection.TLSConnection}.  We've
-    separated the code in this class from TLSConnection to make things
-    more readable.
-
-
-    @type sock: socket.socket
-    @ivar sock: The underlying socket object.
-
-    @type session: L{tlslite.Session.Session}
-    @ivar session: The session corresponding to this connection.
-
-    Due to TLS session resumption, multiple connections can correspond
-    to the same underlying session.
-
-    @type version: tuple
-    @ivar version: The TLS version being used for this connection.
-
-    (3,0) means SSL 3.0, and (3,1) means TLS 1.0.
-
-    @type closed: bool
-    @ivar closed: If this connection is closed.
-
-    @type resumed: bool
-    @ivar resumed: If this connection is based on a resumed session.
-
-    @type allegedSrpUsername: str or None
-    @ivar allegedSrpUsername:  This is set to the SRP username
-    asserted by the client, whether the handshake succeeded or not.
-    If the handshake fails, this can be inspected to determine
-    if a guessing attack is in progress against a particular user
-    account.
-
-    @type closeSocket: bool
-    @ivar closeSocket: If the socket should be closed when the
-    connection is closed, defaults to True (writable).
-
-    If you set this to True, TLS Lite will assume the responsibility of
-    closing the socket when the TLS Connection is shutdown (either
-    through an error or through the user calling close()).  The default
-    is False.
-
-    @type ignoreAbruptClose: bool
-    @ivar ignoreAbruptClose: If an abrupt close of the socket should
-    raise an error (writable).
-
-    If you set this to True, TLS Lite will not raise a
-    L{tlslite.errors.TLSAbruptCloseError} exception if the underlying
-    socket is unexpectedly closed.  Such an unexpected closure could be
-    caused by an attacker.  However, it also occurs with some incorrect
-    TLS implementations.
-
-    You should set this to True only if you're not worried about an
-    attacker truncating the connection, and only if necessary to avoid
-    spurious errors.  The default is False.
-
-    @sort: __init__, read, readAsync, write, writeAsync, close, closeAsync,
-    getCipherImplementation, getCipherName
-    """
-
-    def __init__(self, sock):
-        self.sock = sock
-
-        #My session object (Session instance; read-only)
-        self.session = None
-
-        #Am I a client or server?
-        self._client = None
-
-        #Buffers for processing messages
-        self._handshakeBuffer = []
-        self.clearReadBuffer()
-        self.clearWriteBuffer()
-
-        #Handshake digests
-        self._handshake_md5 = hashlib.md5()
-        self._handshake_sha = hashlib.sha1()
-        self._handshake_sha256 = hashlib.sha256()
-        self._ems_handshake_hash = b""
-
-        #TLS Protocol Version
-        self.version = (0,0) #read-only
-        self._versionCheck = False #Once we choose a version, this is True
-
-        #Current and Pending connection states
-        self._writeState = _ConnectionState()
-        self._readState = _ConnectionState()
-        self._pendingWriteState = _ConnectionState()
-        self._pendingReadState = _ConnectionState()
-
-        #Is the connection open?
-        self.closed = True #read-only
-        self._refCount = 0 #Used to trigger closure
-
-        #Is this a resumed session?
-        self.resumed = False #read-only
-
-        #What username did the client claim in his handshake?
-        self.allegedSrpUsername = None
-
-        #On a call to close(), do we close the socket? (writeable)
-        self.closeSocket = True
-
-        #If the socket is abruptly closed, do we ignore it
-        #and pretend the connection was shut down properly? (writeable)
-        self.ignoreAbruptClose = False
-
-        #Fault we will induce, for testing purposes
-        self.fault = None
-
-    def clearReadBuffer(self):
-        self._readBuffer = b''
-
-    def clearWriteBuffer(self):
-        self._send_writer = None
-
-
-    #*********************************************************
-    # Public Functions START
-    #*********************************************************
-
-    def read(self, max=None, min=1):
-        """Read some data from the TLS connection.
-
-        This function will block until at least 'min' bytes are
-        available (or the connection is closed).
-
-        If an exception is raised, the connection will have been
-        automatically closed.
-
-        @type max: int
-        @param max: The maximum number of bytes to return.
-
-        @type min: int
-        @param min: The minimum number of bytes to return
-
-        @rtype: str
-        @return: A string of no more than 'max' bytes, and no fewer
-        than 'min' (unless the connection has been closed, in which
-        case fewer than 'min' bytes may be returned).
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        """
-        for result in self.readAsync(max, min):
-            pass
-        return result
-
-    def readAsync(self, max=None, min=1):
-        """Start a read operation on the TLS connection.
-
-        This function returns a generator which behaves similarly to
-        read().  Successive invocations of the generator will return 0
-        if it is waiting to read from the socket, 1 if it is waiting
-        to write to the socket, or a string if the read operation has
-        completed.
-
-        @rtype: iterable
-        @return: A generator; see above for details.
-        """
-        try:
-            while len(self._readBuffer)<min and not self.closed:
-                try:
-                    for result in self._getMsg(ContentType.application_data):
-                        if result in (0,1):
-                            yield result
-                    applicationData = result
-                    self._readBuffer += applicationData.write()
-                except TLSRemoteAlert as alert:
-                    if alert.description != AlertDescription.close_notify:
-                        raise
-                except TLSAbruptCloseError:
-                    if not self.ignoreAbruptClose:
-                        raise
-                    else:
-                        self._shutdown(True)
-
-            if max == None:
-                max = len(self._readBuffer)
-
-            returnBytes = self._readBuffer[:max]
-            self._readBuffer = self._readBuffer[max:]
-            yield bytes(returnBytes)
-        except GeneratorExit:
-            raise
-        except:
-            self._shutdown(False)
-            raise
-
-    def unread(self, b):
-        """Add bytes to the front of the socket read buffer for future
-        reading. Be careful using this in the context of select(...): if you
-        unread the last data from a socket, that won't wake up selected waiters,
-        and those waiters may hang forever.
-        """
-        self._readBuffer = b + self._readBuffer
-
-    def write(self, s):
-        """Write some data to the TLS connection.
-
-        This function will block until all the data has been sent.
-
-        If an exception is raised, the connection will have been
-        automatically closed.
-
-        @type s: str
-        @param s: The data to transmit to the other party.
-
-        @raise socket.error: If a socket error occurs.
-        """
-        for result in self.writeAsync(s):
-            pass
-
-    def writeAsync(self, s):
-        """Start a write operation on the TLS connection.
-
-        This function returns a generator which behaves similarly to
-        write().  Successive invocations of the generator will return
-        1 if it is waiting to write to the socket, or will raise
-        StopIteration if the write operation has completed.
-
-        @rtype: iterable
-        @return: A generator; see above for details.
-        """
-        try:
-            if self.closed:
-                raise TLSClosedConnectionError("attempt to write to closed connection")
-
-            index = 0
-            blockSize = 16384
-            randomizeFirstBlock = True
-            while 1:
-                startIndex = index * blockSize
-                endIndex = startIndex + blockSize
-                if startIndex >= len(s):
-                    break
-                if endIndex > len(s):
-                    endIndex = len(s)
-                block = bytearray(s[startIndex : endIndex])
-                applicationData = ApplicationData().create(block)
-                for result in self._sendMsg(applicationData, \
-                                            randomizeFirstBlock):
-                    yield result
-                randomizeFirstBlock = False #only on 1st message
-                index += 1
-        except GeneratorExit:
-            raise
-        except Exception:
-            # Don't invalidate the session on write failure if abrupt closes are
-            # okay.
-            self._shutdown(self.ignoreAbruptClose)
-            raise
-
-    def close(self):
-        """Close the TLS connection.
-
-        This function will block until it has exchanged close_notify
-        alerts with the other party.  After doing so, it will shut down the
-        TLS connection.  Further attempts to read through this connection
-        will return "".  Further attempts to write through this connection
-        will raise ValueError.
-
-        If makefile() has been called on this connection, the connection
-        will be not be closed until the connection object and all file
-        objects have been closed.
-
-        Even if an exception is raised, the connection will have been
-        closed.
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        """
-        if not self.closed:
-            for result in self._decrefAsync():
-                pass
-
-    # Python 3 callback
-    _decref_socketios = close
-
-    def closeAsync(self):
-        """Start a close operation on the TLS connection.
-
-        This function returns a generator which behaves similarly to
-        close().  Successive invocations of the generator will return 0
-        if it is waiting to read from the socket, 1 if it is waiting
-        to write to the socket, or will raise StopIteration if the
-        close operation has completed.
-
-        @rtype: iterable
-        @return: A generator; see above for details.
-        """
-        if not self.closed:
-            for result in self._decrefAsync():
-                yield result
-
-    def _decrefAsync(self):
-        self._refCount -= 1
-        if self._refCount == 0 and not self.closed:
-            try:
-                for result in self._sendMsg(Alert().create(\
-                        AlertDescription.close_notify, AlertLevel.warning)):
-                    yield result
-                alert = None
-                # By default close the socket, since it's been observed
-                # that some other libraries will not respond to the 
-                # close_notify alert, thus leaving us hanging if we're
-                # expecting it
-                if self.closeSocket:
-                    self._shutdown(True)
-                else:
-                    while not alert:
-                        for result in self._getMsg((ContentType.alert, \
-                                                  ContentType.application_data)):
-                            if result in (0,1):
-                                yield result
-                        if result.contentType == ContentType.alert:
-                            alert = result
-                    if alert.description == AlertDescription.close_notify:
-                        self._shutdown(True)
-                    else:
-                        raise TLSRemoteAlert(alert)
-            except (socket.error, TLSAbruptCloseError):
-                #If the other side closes the socket, that's okay
-                self._shutdown(True)
-            except GeneratorExit:
-                raise
-            except:
-                self._shutdown(False)
-                raise
-
-    def getVersionName(self):
-        """Get the name of this TLS version.
-
-        @rtype: str
-        @return: The name of the TLS version used with this connection.
-        Either None, 'SSL 3.0', 'TLS 1.0', 'TLS 1.1', or 'TLS 1.2'.
-        """
-        if self.version == (3,0):
-            return "SSL 3.0"
-        elif self.version == (3,1):
-            return "TLS 1.0"
-        elif self.version == (3,2):
-            return "TLS 1.1"
-        elif self.version == (3,3):
-            return "TLS 1.2"
-        else:
-            return None
-        
-    def getCipherName(self):
-        """Get the name of the cipher used with this connection.
-
-        @rtype: str
-        @return: The name of the cipher used with this connection.
-        Either 'aes128', 'aes256', 'rc4', or '3des'.
-        """
-        if not self._writeState.encContext:
-            return None
-        return self._writeState.encContext.name
-
-    def getCipherImplementation(self):
-        """Get the name of the cipher implementation used with
-        this connection.
-
-        @rtype: str
-        @return: The name of the cipher implementation used with
-        this connection.  Either 'python', 'openssl', or 'pycrypto'.
-        """
-        if not self._writeState.encContext:
-            return None
-        return self._writeState.encContext.implementation
-
-
-
-    #Emulate a socket, somewhat -
-    def send(self, s):
-        """Send data to the TLS connection (socket emulation).
-
-        @raise socket.error: If a socket error occurs.
-        """
-        self.write(s)
-        return len(s)
-
-    def sendall(self, s):
-        """Send data to the TLS connection (socket emulation).
-
-        @raise socket.error: If a socket error occurs.
-        """
-        self.write(s)
-
-    def recv(self, bufsize):
-        """Get some data from the TLS connection (socket emulation).
-
-        @raise socket.error: If a socket error occurs.
-        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
-        without a preceding alert.
-        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
-        """
-        return self.read(bufsize)
-
-    def recv_into(self, b):
-        # XXX doc string
-        data = self.read(len(b))
-        if not data:
-            return None
-        b[:len(data)] = data
-        return len(data)
-
-    def makefile(self, mode='r', bufsize=-1):
-        """Create a file object for the TLS connection (socket emulation).
-
-        @rtype: L{socket._fileobject}
-        """
-        self._refCount += 1
-        # So, it is pretty fragile to be using Python internal objects
-        # like this, but it is probably the best/easiest way to provide
-        # matching behavior for socket emulation purposes.  The 'close'
-        # argument is nice, its apparently a recent addition to this
-        # class, so that when fileobject.close() gets called, it will
-        # close() us, causing the refcount to be decremented (decrefAsync).
-        #
-        # If this is the last close() on the outstanding fileobjects / 
-        # TLSConnection, then the "actual" close alerts will be sent,
-        # socket closed, etc.
-        if sys.version_info < (3,):
-            return socket._fileobject(self, mode, bufsize, close=True)
-        else:
-            # XXX need to wrap this further if buffering is requested
-            return socket.SocketIO(self, mode)
-
-    def getsockname(self):
-        """Return the socket's own address (socket emulation)."""
-        return self.sock.getsockname()
-
-    def getpeername(self):
-        """Return the remote address to which the socket is connected
-        (socket emulation)."""
-        return self.sock.getpeername()
-
-    def settimeout(self, value):
-        """Set a timeout on blocking socket operations (socket emulation)."""
-        return self.sock.settimeout(value)
-
-    def gettimeout(self):
-        """Return the timeout associated with socket operations (socket
-        emulation)."""
-        return self.sock.gettimeout()
-
-    def setsockopt(self, level, optname, value):
-        """Set the value of the given socket option (socket emulation)."""
-        return self.sock.setsockopt(level, optname, value)
-
-    def shutdown(self, how):
-        """Shutdown the underlying socket."""
-        return self.sock.shutdown(how)
-    	
-    def fileno(self):
-        """Not implement in TLS Lite."""
-        raise NotImplementedError()
-    	
-
-     #*********************************************************
-     # Public Functions END
-     #*********************************************************
-
-    def _shutdown(self, resumable):
-        self._writeState = _ConnectionState()
-        self._readState = _ConnectionState()
-        self.version = (0,0)
-        self._versionCheck = False
-        self.closed = True
-        if self.closeSocket:
-            self.sock.close()
-
-        #Even if resumable is False, we'll never toggle this on
-        if not resumable and self.session:
-            self.session.resumable = False
-
-
-    def _sendError(self, alertDescription, errorStr=None):
-        alert = Alert().create(alertDescription, AlertLevel.fatal)
-        for result in self._sendMsg(alert):
-            yield result
-        self._shutdown(False)
-        raise TLSLocalAlert(alert, errorStr)
-
-    def _abruptClose(self, reset=False):
-        if reset:
-            #Set an SO_LINGER timeout of 0 to send a TCP RST.
-            self.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
-                            struct.pack('ii', 1, 0))
-        self._shutdown(False)
-
-    def _sendMsgs(self, msgs):
-        randomizeFirstBlock = True
-        for msg in msgs:
-            for result in self._sendMsg(msg, randomizeFirstBlock):
-                yield result
-            randomizeFirstBlock = True
-
-    def _sendMsg(self, msg, randomizeFirstBlock = True):
-        #Whenever we're connected and asked to send an app data message,
-        #we first send the first byte of the message.  This prevents
-        #an attacker from launching a chosen-plaintext attack based on
-        #knowing the next IV (a la BEAST).
-        if not self.closed and randomizeFirstBlock and self.version <= (3,1) \
-                and self._writeState.encContext \
-                and self._writeState.encContext.isBlockCipher \
-                and isinstance(msg, ApplicationData):
-            msgFirstByte = msg.splitFirstByte()
-            for result in self._sendMsg(msgFirstByte,
-                                       randomizeFirstBlock = False):
-                yield result                                            
-
-        b = msg.write()
-        
-        # If a 1-byte message was passed in, and we "split" the 
-        # first(only) byte off above, we may have a 0-length msg:
-        if len(b) == 0:
-            return
-            
-        contentType = msg.contentType
-
-        #Update handshake hashes
-        if contentType == ContentType.handshake:
-            self._handshake_md5.update(compat26Str(b))
-            self._handshake_sha.update(compat26Str(b))
-            self._handshake_sha256.update(compat26Str(b))
-
-        #Calculate MAC
-        if self._writeState.macContext:
-            seqnumBytes = self._writeState.getSeqNumBytes()
-            mac = self._writeState.macContext.copy()
-            mac.update(compatHMAC(seqnumBytes))
-            mac.update(compatHMAC(bytearray([contentType])))
-            if self.version == (3,0):
-                mac.update( compatHMAC( bytearray([len(b)//256] )))
-                mac.update( compatHMAC( bytearray([len(b)%256] )))
-            elif self.version in ((3,1), (3,2), (3,3)):
-                mac.update(compatHMAC( bytearray([self.version[0]] )))
-                mac.update(compatHMAC( bytearray([self.version[1]] )))
-                mac.update( compatHMAC( bytearray([len(b)//256] )))
-                mac.update( compatHMAC( bytearray([len(b)%256] )))
-            else:
-                raise AssertionError()
-            mac.update(compatHMAC(b))
-            macBytes = bytearray(mac.digest())
-            if self.fault == Fault.badMAC:
-                macBytes[0] = (macBytes[0]+1) % 256
-
-        #Encrypt for non-NULL cipher.
-        if self._writeState.encContext:
-            #Seal (for AEAD)
-            if self._writeState.encContext.isAEAD:
-                #Assemble the authenticated data.
-                seqNumBytes = self._writeState.getSeqNumBytes()
-                authData = seqNumBytes + bytearray([contentType,
-                                                    self.version[0],
-                                                    self.version[1],
-                                                    len(b)//256,
-                                                    len(b)%256])
-
-                #The nonce is always the fixed nonce and the sequence number.
-                nonce = self._writeState.fixedNonce + seqNumBytes
-                assert len(nonce) == self._writeState.encContext.nonceLength
-
-                b = self._writeState.encContext.seal(nonce, b, authData)
-
-                #The only AEAD supported, AES-GCM, has an explicit variable
-                #nonce.
-                b = seqNumBytes + b
-
-            #Add padding and encrypt (for Block Cipher):
-            elif self._writeState.encContext.isBlockCipher:
-
-                #Add TLS 1.1 fixed block
-                if self.version >= (3,2):
-                    b = self.fixedIVBlock + b
-
-                #Add padding: b = b+ (macBytes + paddingBytes)
-                currentLength = len(b) + len(macBytes)
-                blockLength = self._writeState.encContext.block_size
-                paddingLength = blockLength - 1 - (currentLength % blockLength)
-
-                paddingBytes = bytearray([paddingLength] * (paddingLength+1))
-                if self.fault == Fault.badPadding:
-                    paddingBytes[0] = (paddingBytes[0]+1) % 256
-                endBytes = macBytes + paddingBytes
-                b += endBytes
-                #Encrypt
-                b = self._writeState.encContext.encrypt(b)
-
-            #Encrypt (for Stream Cipher)
-            else:
-                b += macBytes
-                b = self._writeState.encContext.encrypt(b)
-
-        #Add record header and send
-        r = RecordHeader3().create(self.version, contentType, len(b))
-        s = r.write() + b
-        while 1:
-            try:
-                bytesSent = self.sock.send(s) #Might raise socket.error
-            except socket.error as why:
-                if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
-                    yield 1
-                    continue
-                else:
-                    # The socket was unexpectedly closed.  The tricky part
-                    # is that there may be an alert sent by the other party
-                    # sitting in the read buffer.  So, if we get here after
-                    # handshaking, we will just raise the error and let the
-                    # caller read more data if it would like, thus stumbling
-                    # upon the error.
-                    #
-                    # However, if we get here DURING handshaking, we take
-                    # it upon ourselves to see if the next message is an 
-                    # Alert.
-                    if contentType == ContentType.handshake:
-                        
-                        # See if there's an alert record
-                        # Could raise socket.error or TLSAbruptCloseError
-                        for result in self._getNextRecord():
-                            if result in (0,1):
-                                yield result
-                                
-                        # Closes the socket
-                        self._shutdown(False)
-                        
-                        # If we got an alert, raise it        
-                        recordHeader, p = result                        
-                        if recordHeader.type == ContentType.alert:
-                            alert = Alert().parse(p)
-                            raise TLSRemoteAlert(alert)
-                    else:
-                        # If we got some other message who know what
-                        # the remote side is doing, just go ahead and
-                        # raise the socket.error
-                        raise
-            if bytesSent == len(s):
-                return
-            s = s[bytesSent:]
-            yield 1
-
-
-    def _getMsg(self, expectedType, secondaryType=None, constructorType=None):
-        try:
-            if not isinstance(expectedType, tuple):
-                expectedType = (expectedType,)
-
-            #Spin in a loop, until we've got a non-empty record of a type we
-            #expect.  The loop will be repeated if:
-            #  - we receive a renegotiation attempt; we send no_renegotiation,
-            #    then try again
-            #  - we receive an empty application-data fragment; we try again
-            while 1:
-                for result in self._getNextRecord():
-                    if result in (0,1):
-                        yield result
-                recordHeader, p = result
-
-                #If this is an empty application-data fragment, try again
-                if recordHeader.type == ContentType.application_data:
-                    if p.index == len(p.bytes):
-                        continue
-
-                #If we received an unexpected record type...
-                if recordHeader.type not in expectedType:
-
-                    #If we received an alert...
-                    if recordHeader.type == ContentType.alert:
-                        alert = Alert().parse(p)
-
-                        #We either received a fatal error, a warning, or a
-                        #close_notify.  In any case, we're going to close the
-                        #connection.  In the latter two cases we respond with
-                        #a close_notify, but ignore any socket errors, since
-                        #the other side might have already closed the socket.
-                        if alert.level == AlertLevel.warning or \
-                           alert.description == AlertDescription.close_notify:
-
-                            #If the sendMsg() call fails because the socket has
-                            #already been closed, we will be forgiving and not
-                            #report the error nor invalidate the "resumability"
-                            #of the session.
-                            try:
-                                alertMsg = Alert()
-                                alertMsg.create(AlertDescription.close_notify,
-                                                AlertLevel.warning)
-                                for result in self._sendMsg(alertMsg):
-                                    yield result
-                            except socket.error:
-                                pass
-
-                            if alert.description == \
-                                   AlertDescription.close_notify:
-                                self._shutdown(True)
-                            elif alert.level == AlertLevel.warning:
-                                self._shutdown(False)
-
-                        else: #Fatal alert:
-                            self._shutdown(False)
-
-                        #Raise the alert as an exception
-                        raise TLSRemoteAlert(alert)
-
-                    #If we received a renegotiation attempt...
-                    if recordHeader.type == ContentType.handshake:
-                        subType = p.get(1)
-                        reneg = False
-                        if self._client:
-                            if subType == HandshakeType.hello_request:
-                                reneg = True
-                        else:
-                            if subType == HandshakeType.client_hello:
-                                reneg = True
-                        #Send no_renegotiation, then try again
-                        if reneg:
-                            alertMsg = Alert()
-                            alertMsg.create(AlertDescription.no_renegotiation,
-                                            AlertLevel.warning)
-                            for result in self._sendMsg(alertMsg):
-                                yield result
-                            continue
-
-                    #Otherwise: this is an unexpected record, but neither an
-                    #alert nor renegotiation
-                    for result in self._sendError(\
-                            AlertDescription.unexpected_message,
-                            "received type=%d" % recordHeader.type):
-                        yield result
-
-                break
-
-            #Parse based on content_type
-            if recordHeader.type == ContentType.change_cipher_spec:
-                yield ChangeCipherSpec().parse(p)
-            elif recordHeader.type == ContentType.alert:
-                yield Alert().parse(p)
-            elif recordHeader.type == ContentType.application_data:
-                yield ApplicationData().parse(p)
-            elif recordHeader.type == ContentType.handshake:
-                #Convert secondaryType to tuple, if it isn't already
-                if not isinstance(secondaryType, tuple):
-                    secondaryType = (secondaryType,)
-
-                #If it's a handshake message, check handshake header
-                if recordHeader.ssl2:
-                    subType = p.get(1)
-                    if subType != HandshakeType.client_hello:
-                        for result in self._sendError(\
-                                AlertDescription.unexpected_message,
-                                "Can only handle SSLv2 ClientHello messages"):
-                            yield result
-                    if HandshakeType.client_hello not in secondaryType:
-                        for result in self._sendError(\
-                                AlertDescription.unexpected_message):
-                            yield result
-                    subType = HandshakeType.client_hello
-                else:
-                    subType = p.get(1)
-                    if subType not in secondaryType:
-                        for result in self._sendError(\
-                                AlertDescription.unexpected_message,
-                                "Expecting %s, got %s" % (str(secondaryType), subType)):
-                            yield result
-
-                #Update handshake hashes
-                self._handshake_md5.update(compat26Str(p.bytes))
-                self._handshake_sha.update(compat26Str(p.bytes))
-                self._handshake_sha256.update(compat26Str(p.bytes))
-                if subType == HandshakeType.client_key_exchange:
-                    self._ems_handshake_hash = self._getHandshakeHash()
-
-                #Parse based on handshake type
-                if subType == HandshakeType.client_hello:
-                    yield ClientHello(recordHeader.ssl2).parse(p)
-                elif subType == HandshakeType.server_hello:
-                    yield ServerHello().parse(p)
-                elif subType == HandshakeType.certificate:
-                    yield Certificate(constructorType).parse(p)
-                elif subType == HandshakeType.certificate_request:
-                    yield CertificateRequest(self.version).parse(p)
-                elif subType == HandshakeType.certificate_verify:
-                    yield CertificateVerify(self.version).parse(p)
-                elif subType == HandshakeType.server_key_exchange:
-                    yield ServerKeyExchange(constructorType,
-                                            self.version).parse(p)
-                elif subType == HandshakeType.server_hello_done:
-                    yield ServerHelloDone().parse(p)
-                elif subType == HandshakeType.client_key_exchange:
-                    yield ClientKeyExchange(constructorType, \
-                                            self.version).parse(p)
-                elif subType == HandshakeType.finished:
-                    yield Finished(self.version).parse(p)
-                elif subType == HandshakeType.next_protocol:
-                    yield NextProtocol().parse(p)
-                elif subType == HandshakeType.encrypted_extensions:
-                    yield EncryptedExtensions().parse(p)
-                else:
-                    raise AssertionError()
-
-        #If an exception was raised by a Parser or Message instance:
-        except SyntaxError as e:
-            for result in self._sendError(AlertDescription.decode_error,
-                                         formatExceptionTrace(e)):
-                yield result
-
-
-    #Returns next record or next handshake message
-    def _getNextRecord(self):
-
-        #If there's a handshake message waiting, return it
-        if self._handshakeBuffer:
-            recordHeader, b = self._handshakeBuffer[0]
-            self._handshakeBuffer = self._handshakeBuffer[1:]
-            yield (recordHeader, Parser(b))
-            return
-
-        #Otherwise...
-        #Read the next record header
-        b = bytearray(0)
-        recordHeaderLength = 1
-        ssl2 = False
-        while 1:
-            try:
-                s = self.sock.recv(recordHeaderLength-len(b))
-            except socket.error as why:
-                if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
-                    yield 0
-                    continue
-                else:
-                    raise
-
-            #If the connection was abruptly closed, raise an error
-            if len(s)==0:
-                raise TLSAbruptCloseError()
-
-            b += bytearray(s)
-            if len(b)==1:
-                if b[0] in ContentType.all:
-                    ssl2 = False
-                    recordHeaderLength = 5
-                elif b[0] == 128:
-                    ssl2 = True
-                    recordHeaderLength = 2
-                else:
-                    raise SyntaxError()
-            if len(b) == recordHeaderLength:
-                break
-
-        #Parse the record header
-        if ssl2:
-            r = RecordHeader2().parse(Parser(b))
-        else:
-            r = RecordHeader3().parse(Parser(b))
-
-        #Check the record header fields
-        if r.length > 18432:
-            for result in self._sendError(AlertDescription.record_overflow):
-                yield result
-
-        #Read the record contents
-        b = bytearray(0)
-        while 1:
-            try:
-                s = self.sock.recv(r.length - len(b))
-            except socket.error as why:
-                if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
-                    yield 0
-                    continue
-                else:
-                    raise
-
-            #If the connection is closed, raise a socket error
-            if len(s)==0:
-                    raise TLSAbruptCloseError()
-
-            b += bytearray(s)
-            if len(b) == r.length:
-                break
-
-        #Check the record header fields (2)
-        #We do this after reading the contents from the socket, so that
-        #if there's an error, we at least don't leave extra bytes in the
-        #socket..
-        #
-        # THIS CHECK HAS NO SECURITY RELEVANCE (?), BUT COULD HURT INTEROP.
-        # SO WE LEAVE IT OUT FOR NOW.
-        #
-        #if self._versionCheck and r.version != self.version:
-        #    for result in self._sendError(AlertDescription.protocol_version,
-        #            "Version in header field: %s, should be %s" % (str(r.version),
-        #                                                       str(self.version))):
-        #        yield result
-
-        #Decrypt the record
-        for result in self._decryptRecord(r.type, b):
-            if result in (0,1): yield result
-            else: break
-        b = result
-        p = Parser(b)
-
-        #If it doesn't contain handshake messages, we can just return it
-        if r.type != ContentType.handshake:
-            yield (r, p)
-        #If it's an SSLv2 ClientHello, we can return it as well
-        elif r.ssl2:
-            yield (r, p)
-        else:
-            #Otherwise, we loop through and add the handshake messages to the
-            #handshake buffer
-            while 1:
-                if p.index == len(b): #If we're at the end
-                    if not self._handshakeBuffer:
-                        for result in self._sendError(\
-                                AlertDescription.decode_error, \
-                                "Received empty handshake record"):
-                            yield result
-                    break
-                #There needs to be at least 4 bytes to get a header
-                if p.index+4 > len(b):
-                    for result in self._sendError(\
-                            AlertDescription.decode_error,
-                            "A record has a partial handshake message (1)"):
-                        yield result
-                p.get(1) # skip handshake type
-                msgLength = p.get(3)
-                if p.index+msgLength > len(b):
-                    for result in self._sendError(\
-                            AlertDescription.decode_error,
-                            "A record has a partial handshake message (2)"):
-                        yield result
-
-                handshakePair = (r, b[p.index-4 : p.index+msgLength])
-                self._handshakeBuffer.append(handshakePair)
-                p.index += msgLength
-
-            #We've moved at least one handshake message into the
-            #handshakeBuffer, return the first one
-            recordHeader, b = self._handshakeBuffer[0]
-            self._handshakeBuffer = self._handshakeBuffer[1:]
-            yield (recordHeader, Parser(b))
-
-
-    def _decryptRecord(self, recordType, b):
-        if self._readState.encContext:
-            #Open if it's an AEAD.
-            if self._readState.encContext.isAEAD:
-                #The only AEAD supported, AES-GCM, has an explicit variable
-                #nonce.
-                explicitNonceLength = 8
-                if explicitNonceLength > len(b):
-                    #Publicly invalid.
-                    for result in self._sendError(
-                            AlertDescription.bad_record_mac,
-                            "MAC failure (or padding failure)"):
-                        yield result
-                nonce = self._readState.fixedNonce + b[:explicitNonceLength]
-                b = b[8:]
-
-                if self._readState.encContext.tagLength > len(b):
-                    #Publicly invalid.
-                    for result in self._sendError(
-                            AlertDescription.bad_record_mac,
-                            "MAC failure (or padding failure)"):
-                        yield result
-
-                #Assemble the authenticated data.
-                seqnumBytes = self._readState.getSeqNumBytes()
-                plaintextLen = len(b) - self._readState.encContext.tagLength
-                authData = seqnumBytes + bytearray([recordType, self.version[0],
-                                                    self.version[1],
-                                                    plaintextLen//256,
-                                                    plaintextLen%256])
-
-                b = self._readState.encContext.open(nonce, b, authData)
-                if b is None:
-                    for result in self._sendError(
-                            AlertDescription.bad_record_mac,
-                            "MAC failure (or padding failure)"):
-                        yield result
-                yield b
-                return
-
-            #Decrypt if it's a block cipher
-            if self._readState.encContext.isBlockCipher:
-                blockLength = self._readState.encContext.block_size
-                if len(b) % blockLength != 0:
-                    for result in self._sendError(\
-                            AlertDescription.decryption_failed,
-                            "Encrypted data not a multiple of blocksize"):
-                        yield result
-                b = self._readState.encContext.decrypt(b)
-                if self.version >= (3,2): #For TLS 1.1, remove explicit IV
-                    b = b[self._readState.encContext.block_size : ]
-
-                #Check padding
-                paddingGood = True
-                paddingLength = b[-1]
-                if (paddingLength+1) > len(b):
-                    paddingGood=False
-                    totalPaddingLength = 0
-                else:
-                    if self.version == (3,0):
-                        totalPaddingLength = paddingLength+1
-                    elif self.version in ((3,1), (3,2), (3,3)):
-                        totalPaddingLength = paddingLength+1
-                        paddingBytes = b[-totalPaddingLength:-1]
-                        for byte in paddingBytes:
-                            if byte != paddingLength:
-                                paddingGood = False
-                                totalPaddingLength = 0
-                    else:
-                        raise AssertionError()
-
-            #Decrypt if it's a stream cipher
-            else:
-                paddingGood = True
-                b = self._readState.encContext.decrypt(b)
-                totalPaddingLength = 0
-
-            #Check MAC
-            macGood = True
-            macLength = self._readState.macContext.digest_size
-            endLength = macLength + totalPaddingLength
-            if endLength > len(b):
-                macGood = False
-            else:
-                #Read MAC
-                startIndex = len(b) - endLength
-                endIndex = startIndex + macLength
-                checkBytes = b[startIndex : endIndex]
-
-                #Calculate MAC
-                seqnumBytes = self._readState.getSeqNumBytes()
-                b = b[:-endLength]
-                mac = self._readState.macContext.copy()
-                mac.update(compatHMAC(seqnumBytes))
-                mac.update(compatHMAC(bytearray([recordType])))
-                if self.version == (3,0):
-                    mac.update( compatHMAC(bytearray( [len(b)//256] ) ))
-                    mac.update( compatHMAC(bytearray( [len(b)%256] ) ))
-                elif self.version in ((3,1), (3,2), (3,3)):
-                    mac.update(compatHMAC(bytearray( [self.version[0]] ) ))
-                    mac.update(compatHMAC(bytearray( [self.version[1]] ) ))
-                    mac.update(compatHMAC(bytearray( [len(b)//256] ) ))
-                    mac.update(compatHMAC(bytearray( [len(b)%256] ) ))
-                else:
-                    raise AssertionError()
-                mac.update(compatHMAC(b))
-                macBytes = bytearray(mac.digest())
-
-                #Compare MACs
-                if macBytes != checkBytes:
-                    macGood = False
-
-            if not (paddingGood and macGood):
-                for result in self._sendError(AlertDescription.bad_record_mac,
-                                          "MAC failure (or padding failure)"):
-                    yield result
-
-        yield b
-
-    def _handshakeStart(self, client):
-        if not self.closed:
-            raise ValueError("Renegotiation disallowed for security reasons")
-        self._client = client
-        self._handshake_md5 = hashlib.md5()
-        self._handshake_sha = hashlib.sha1()
-        self._handshake_sha256 = hashlib.sha256()
-        self._ems_handshake_hash = b""
-        self._handshakeBuffer = []
-        self.allegedSrpUsername = None
-        self._refCount = 1
-
-    def _handshakeDone(self, resumed):
-        self.resumed = resumed
-        self.closed = False
-
-    def _calcPendingStates(self, cipherSuite, masterSecret,
-            clientRandom, serverRandom, implementations):
-        if cipherSuite in CipherSuite.aes128GcmSuites:
-            keyLength = 16
-            ivLength = 4
-            createCipherFunc = createAESGCM
-        elif cipherSuite in CipherSuite.aes128Suites:
-            keyLength = 16
-            ivLength = 16
-            createCipherFunc = createAES
-        elif cipherSuite in CipherSuite.aes256Suites:
-            keyLength = 32
-            ivLength = 16
-            createCipherFunc = createAES
-        elif cipherSuite in CipherSuite.rc4Suites:
-            keyLength = 16
-            ivLength = 0
-            createCipherFunc = createRC4
-        elif cipherSuite in CipherSuite.tripleDESSuites:
-            keyLength = 24
-            ivLength = 8
-            createCipherFunc = createTripleDES
-        else:
-            raise AssertionError()
-            
-        if cipherSuite in CipherSuite.aeadSuites:
-            macLength = 0
-            digestmod = None
-        elif cipherSuite in CipherSuite.shaSuites:
-            macLength = 20
-            digestmod = hashlib.sha1        
-        elif cipherSuite in CipherSuite.sha256Suites:
-            macLength = 32
-            digestmod = hashlib.sha256
-        elif cipherSuite in CipherSuite.md5Suites:
-            macLength = 16
-            digestmod = hashlib.md5
-        else:
-            raise AssertionError()
-
-        if not digestmod:
-            createMACFunc = None
-        elif self.version == (3,0):
-            createMACFunc = createMAC_SSL
-        elif self.version in ((3,1), (3,2), (3,3)):
-            createMACFunc = createHMAC
-
-        outputLength = (macLength*2) + (keyLength*2) + (ivLength*2)
-
-        #Calculate Keying Material from Master Secret
-        if self.version == (3,0):
-            keyBlock = PRF_SSL(masterSecret,
-                               serverRandom + clientRandom,
-                               outputLength)
-        elif self.version in ((3,1), (3,2)):
-            keyBlock = PRF(masterSecret,
-                           b"key expansion",
-                           serverRandom + clientRandom,
-                           outputLength)
-        elif self.version == (3,3):
-            keyBlock = PRF_1_2(masterSecret,
-                           b"key expansion",
-                           serverRandom + clientRandom,
-                           outputLength)
-        else:
-            raise AssertionError()
-
-        #Slice up Keying Material
-        clientPendingState = _ConnectionState()
-        serverPendingState = _ConnectionState()
-        p = Parser(keyBlock)
-        clientMACBlock = p.getFixBytes(macLength)
-        serverMACBlock = p.getFixBytes(macLength)
-        clientKeyBlock = p.getFixBytes(keyLength)
-        serverKeyBlock = p.getFixBytes(keyLength)
-        clientIVBlock  = p.getFixBytes(ivLength)
-        serverIVBlock  = p.getFixBytes(ivLength)
-        if digestmod:
-            # Legacy cipher.
-            clientPendingState.macContext = createMACFunc(
-                compatHMAC(clientMACBlock), digestmod=digestmod)
-            serverPendingState.macContext = createMACFunc(
-                compatHMAC(serverMACBlock), digestmod=digestmod)
-            clientPendingState.encContext = createCipherFunc(clientKeyBlock,
-                                                             clientIVBlock,
-                                                             implementations)
-            serverPendingState.encContext = createCipherFunc(serverKeyBlock,
-                                                             serverIVBlock,
-                                                             implementations)
-        else:
-            # AEAD.
-            clientPendingState.macContext = None
-            serverPendingState.macContext = None
-            clientPendingState.encContext = createCipherFunc(clientKeyBlock,
-                                                             implementations)
-            serverPendingState.encContext = createCipherFunc(serverKeyBlock,
-                                                             implementations)
-            clientPendingState.fixedNonce = clientIVBlock
-            serverPendingState.fixedNonce = serverIVBlock
-
-        #Assign new connection states to pending states
-        if self._client:
-            self._pendingWriteState = clientPendingState
-            self._pendingReadState = serverPendingState
-        else:
-            self._pendingWriteState = serverPendingState
-            self._pendingReadState = clientPendingState
-
-        if self.version >= (3,2) and ivLength:
-            #Choose fixedIVBlock for TLS 1.1 (this is encrypted with the CBC
-            #residue to create the IV for each sent block)
-            self.fixedIVBlock = getRandomBytes(ivLength)
-
-    def _changeWriteState(self):
-        self._writeState = self._pendingWriteState
-        self._pendingWriteState = _ConnectionState()
-
-    def _changeReadState(self):
-        self._readState = self._pendingReadState
-        self._pendingReadState = _ConnectionState()
-
-    #Used for Finished messages and CertificateVerify messages in SSL v3
-    def _calcSSLHandshakeHash(self, masterSecret, label):
-        imac_md5 = self._handshake_md5.copy()
-        imac_sha = self._handshake_sha.copy()
-
-        imac_md5.update(compatHMAC(label + masterSecret + bytearray([0x36]*48)))
-        imac_sha.update(compatHMAC(label + masterSecret + bytearray([0x36]*40)))
-
-        md5Bytes = MD5(masterSecret + bytearray([0x5c]*48) + \
-                         bytearray(imac_md5.digest()))
-        shaBytes = SHA1(masterSecret + bytearray([0x5c]*40) + \
-                         bytearray(imac_sha.digest()))
-
-        return md5Bytes + shaBytes
-
-    def _getHandshakeHash(self):
-        if self.version in ((3,1), (3,2)):
-            return self._handshake_md5.digest() + \
-                self._handshake_sha.digest()
-        elif self.version == (3,3):
-            return self._handshake_sha256.digest()
diff --git a/third_party/tlslite/tlslite/utils/__init__.py b/third_party/tlslite/tlslite/utils/__init__.py
deleted file mode 100644
index 4d49df6..0000000
--- a/third_party/tlslite/tlslite/utils/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Toolkit for crypto and other stuff."""
-
-__all__ = ["aes",
-           "asn1parser",
-           "cipherfactory",
-           "codec",
-           "cryptomath",
-           "datefuncs",
-           "compat",
-           "keyfactory",
-           "openssl_aes",
-           "openssl_rc4",
-           "openssl_rsakey",
-           "openssl_tripledes",
-           "pycrypto_aes",
-           "pycrypto_rc4",
-           "pycrypto_rsakey",
-           "pycrypto_tripledes",
-           "python_aes",
-           "python_rc4",
-           "python_rsakey",
-           "rc4",
-           "rijndael",
-           "rsakey",
-           "tackpywrapper",
-           "tripledes"]
diff --git a/third_party/tlslite/tlslite/utils/aes.py b/third_party/tlslite/tlslite/utils/aes.py
deleted file mode 100644
index 5a038fb..0000000
--- a/third_party/tlslite/tlslite/utils/aes.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Abstract class for AES."""
-
-class AES(object):
-    def __init__(self, key, mode, IV, implementation):
-        if len(key) not in (16, 24, 32):
-            raise AssertionError()
-        if mode != 2:
-            raise AssertionError()
-        if len(IV) != 16:
-            raise AssertionError()
-        self.isBlockCipher = True
-        self.isAEAD = False
-        self.block_size = 16
-        self.implementation = implementation
-        if len(key)==16:
-            self.name = "aes128"
-        elif len(key)==24:
-            self.name = "aes192"
-        elif len(key)==32:
-            self.name = "aes256"
-        else:
-            raise AssertionError()
-
-    #CBC-Mode encryption, returns ciphertext
-    #WARNING: *MAY* modify the input as well
-    def encrypt(self, plaintext):
-        assert(len(plaintext) % 16 == 0)
-
-    #CBC-Mode decryption, returns plaintext
-    #WARNING: *MAY* modify the input as well
-    def decrypt(self, ciphertext):
-        assert(len(ciphertext) % 16 == 0)
diff --git a/third_party/tlslite/tlslite/utils/aesgcm.py b/third_party/tlslite/tlslite/utils/aesgcm.py
deleted file mode 100644
index c887f2f..0000000
--- a/third_party/tlslite/tlslite/utils/aesgcm.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# Author: Google
-# See the LICENSE file for legal information regarding use of this file.
-
-# GCM derived from Go's implementation in crypto/cipher.
-#
-# https://golang.org/src/crypto/cipher/gcm.go
-
-# GCM works over elements of the field GF(2^128), each of which is a 128-bit
-# polynomial. Throughout this implementation, polynomials are represented as
-# Python integers with the low-order terms at the most significant bits. So a
-# 128-bit polynomial is an integer from 0 to 2^128-1 with the most significant
-# bit representing the x^0 term and the least significant bit representing the
-# x^127 term. This bit reversal also applies to polynomials used as indices in a
-# look-up table.
-
-from __future__ import division
-
-from .cryptomath import bytesToNumber, numberToByteArray
-
-class AESGCM(object):
-    """
-    AES-GCM implementation. Note: this implementation does not attempt
-    to be side-channel resistant. It's also rather slow.
-    """
-
-    def __init__(self, key, implementation, rawAesEncrypt):
-        self.isBlockCipher = False
-        self.isAEAD = True
-        self.nonceLength = 12
-        self.tagLength = 16
-        self.implementation = implementation
-        if len(key) == 16:
-            self.name = "aes128gcm"
-        elif len(key) == 32:
-            self.name = "aes256gcm"
-        else:
-            raise AssertionError()
-
-        self._rawAesEncrypt = rawAesEncrypt
-
-        # The GCM key is AES(0).
-        h = bytesToNumber(self._rawAesEncrypt(bytearray(16)))
-
-        # Pre-compute all 4-bit multiples of h. Note that bits are reversed
-        # because our polynomial representation places low-order terms at the
-        # most significant bit. Thus x^0 * h = h is at index 0b1000 = 8 and
-        # x^1 * h is at index 0b0100 = 4.
-        self._productTable = [0] * 16
-        self._productTable[_reverseBits(1)] = h
-        for i in range(2, 16, 2):
-            self._productTable[_reverseBits(i)] = \
-                _gcmShift(self._productTable[_reverseBits(i//2)])
-            self._productTable[_reverseBits(i+1)] = \
-                _gcmAdd(self._productTable[_reverseBits(i)], h)
-
-    def _rawAesCtrEncrypt(self, counter, inp):
-        """
-        Encrypts (or decrypts) plaintext with AES-CTR. counter is modified.
-        """
-        out = bytearray(len(inp))
-        for i in range(0, len(out), 16):
-            mask = self._rawAesEncrypt(counter)
-            for j in range(i, min(len(out), i + 16)):
-                out[j] = inp[j] ^ mask[j-i]
-            _inc32(counter)
-        return out
-
-    def _auth(self, ciphertext, ad, tagMask):
-        y = 0
-        y = self._update(y, ad)
-        y = self._update(y, ciphertext)
-        y ^= (len(ad) << (3 + 64)) | (len(ciphertext) << 3)
-        y = self._mul(y)
-        y ^= bytesToNumber(tagMask)
-        return numberToByteArray(y, 16)
-
-    def _update(self, y, data):
-        for i in range(0, len(data) // 16):
-            y ^= bytesToNumber(data[16*i:16*i+16])
-            y = self._mul(y)
-        extra = len(data) % 16
-        if extra != 0:
-            block = bytearray(16)
-            block[:extra] = data[-extra:]
-            y ^= bytesToNumber(block)
-            y = self._mul(y)
-        return y
-
-    def _mul(self, y):
-        """ Returns y*H, where H is the GCM key. """
-        ret = 0
-        # Multiply H by y 4 bits at a time, starting with the highest power
-        # terms.
-        for i in range(0, 128, 4):
-            # Multiply by x^4. The reduction for the top four terms is
-            # precomputed.
-            retHigh = ret & 0xf
-            ret >>= 4
-            ret ^= (_gcmReductionTable[retHigh] << (128-16))
-
-            # Add in y' * H where y' are the next four terms of y, shifted down
-            # to the x^0..x^4. This is one of the pre-computed multiples of
-            # H. The multiplication by x^4 shifts them back into place.
-            ret ^= self._productTable[y & 0xf]
-            y >>= 4
-        assert y == 0
-        return ret
-
-    def seal(self, nonce, plaintext, data):
-        """
-        Encrypts and authenticates plaintext using nonce and data. Returns the
-        ciphertext, consisting of the encrypted plaintext and tag concatenated.
-        """
-
-        if len(nonce) != 12:
-            raise ValueError("Bad nonce length")
-
-        # The initial counter value is the nonce, followed by a 32-bit counter
-        # that starts at 1. It's used to compute the tag mask.
-        counter = bytearray(16)
-        counter[:12] = nonce
-        counter[-1] = 1
-        tagMask = self._rawAesEncrypt(counter)
-
-        # The counter starts at 2 for the actual encryption.
-        counter[-1] = 2
-        ciphertext = self._rawAesCtrEncrypt(counter, plaintext)
-
-        tag = self._auth(ciphertext, data, tagMask)
-
-        return ciphertext + tag
-
-    def open(self, nonce, ciphertext, data):
-        """
-        Decrypts and authenticates ciphertext using nonce and data. If the
-        tag is valid, the plaintext is returned. If the tag is invalid,
-        returns None.
-        """
-
-        if len(nonce) != 12:
-            raise ValueError("Bad nonce length")
-        if len(ciphertext) < 16:
-            return None
-
-        tag = ciphertext[-16:]
-        ciphertext = ciphertext[:-16]
-
-        # The initial counter value is the nonce, followed by a 32-bit counter
-        # that starts at 1. It's used to compute the tag mask.
-        counter = bytearray(16)
-        counter[:12] = nonce
-        counter[-1] = 1
-        tagMask = self._rawAesEncrypt(counter)
-
-        if tag != self._auth(ciphertext, data, tagMask):
-            return None
-
-        # The counter starts at 2 for the actual decryption.
-        counter[-1] = 2
-        return self._rawAesCtrEncrypt(counter, ciphertext)
-
-def _reverseBits(i):
-    assert i < 16
-    i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
-    i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
-    return i
-
-def _gcmAdd(x, y):
-    return x ^ y
-
-def _gcmShift(x):
-    # Multiplying by x is a right shift, due to bit order.
-    highTermSet = x & 1
-    x >>= 1
-    if highTermSet:
-        # The x^127 term was shifted up to x^128, so subtract a 1+x+x^2+x^7
-        # term. This is 0b11100001 or 0xe1 when represented as an 8-bit
-        # polynomial.
-        x ^= 0xe1 << (128-8)
-    return x
-
-def _inc32(counter):
-    for i in range(len(counter)-1, len(counter)-5, -1):
-        counter[i] = (counter[i] + 1) % 256
-        if counter[i] != 0:
-            break
-    return counter
-
-# _gcmReductionTable[i] is i * (1+x+x^2+x^7) for all 4-bit polynomials i. The
-# result is stored as a 16-bit polynomial. This is used in the reduction step to
-# multiply elements of GF(2^128) by x^4.
-_gcmReductionTable = [
-    0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
-    0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
-]
diff --git a/third_party/tlslite/tlslite/utils/asn1parser.py b/third_party/tlslite/tlslite/utils/asn1parser.py
deleted file mode 100644
index 618e855..0000000
--- a/third_party/tlslite/tlslite/utils/asn1parser.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Author: Trevor Perrin
-# Patch from Google adding getChildBytes()
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class for parsing ASN.1"""
-from .compat import *
-from .codec import *
-
-#Takes a byte array which has a DER TLV field at its head
-class ASN1Parser(object):
-    def __init__(self, bytes):
-        p = Parser(bytes)
-        p.get(1) #skip Type
-
-        #Get Length
-        self.length = self._getASN1Length(p)
-
-        #Get Value
-        self.value = p.getFixBytes(self.length)
-
-    #Assuming this is a sequence...
-    def getChild(self, which):
-        return ASN1Parser(self.getChildBytes(which))
-
-    def getChildBytes(self, which):
-        p = Parser(self.value)
-        for x in range(which+1):
-            markIndex = p.index
-            p.get(1) #skip Type
-            length = self._getASN1Length(p)
-            p.getFixBytes(length)
-        return p.bytes[markIndex : p.index]
-
-    #Decode the ASN.1 DER length field
-    def _getASN1Length(self, p):
-        firstLength = p.get(1)
-        if firstLength<=127:
-            return firstLength
-        else:
-            lengthLength = firstLength & 0x7F
-            return p.get(lengthLength)
diff --git a/third_party/tlslite/tlslite/utils/cipherfactory.py b/third_party/tlslite/tlslite/utils/cipherfactory.py
deleted file mode 100644
index d525644..0000000
--- a/third_party/tlslite/tlslite/utils/cipherfactory.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Factory functions for symmetric cryptography."""
-
-import os
-
-from tlslite.utils import python_aes
-from tlslite.utils import python_aesgcm
-from tlslite.utils import python_rc4
-
-from tlslite.utils import cryptomath
-
-tripleDESPresent = False
-
-if cryptomath.m2cryptoLoaded:
-    from tlslite.utils import openssl_aes
-    from tlslite.utils import openssl_rc4
-    from tlslite.utils import openssl_tripledes
-    tripleDESPresent = True
-
-if cryptomath.pycryptoLoaded:
-    from tlslite.utils import pycrypto_aes
-    from tlslite.utils import pycrypto_aesgcm
-    from tlslite.utils import pycrypto_rc4
-    from tlslite.utils import pycrypto_tripledes
-    tripleDESPresent = True
-
-# **************************************************************************
-# Factory Functions for AES
-# **************************************************************************
-
-def createAES(key, IV, implList=None):
-    """Create a new AES object.
-
-    @type key: str
-    @param key: A 16, 24, or 32 byte string.
-
-    @type IV: str
-    @param IV: A 16 byte string
-
-    @rtype: L{tlslite.utils.AES}
-    @return: An AES object.
-    """
-    if implList == None:
-        implList = ["openssl", "pycrypto", "python"]
-
-    for impl in implList:
-        if impl == "openssl" and cryptomath.m2cryptoLoaded:
-            return openssl_aes.new(key, 2, IV)
-        elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
-            return pycrypto_aes.new(key, 2, IV)
-        elif impl == "python":
-            return python_aes.new(key, 2, IV)
-    raise NotImplementedError()
-
-def createAESGCM(key, implList=None):
-    """Create a new AESGCM object.
-
-    @type key: bytearray
-    @param key: A 16 or 32 byte byte array.
-
-    @rtype: L{tlslite.utils.AESGCM}
-    @return: An AESGCM object.
-    """
-    if implList == None:
-        implList = ["pycrypto", "python"]
-
-    for impl in implList:
-        if impl == "pycrypto" and cryptomath.pycryptoLoaded:
-            return pycrypto_aesgcm.new(key)
-        if impl == "python":
-            return python_aesgcm.new(key)
-    raise NotImplementedError()
-
-def createRC4(key, IV, implList=None):
-    """Create a new RC4 object.
-
-    @type key: str
-    @param key: A 16 to 32 byte string.
-
-    @type IV: object
-    @param IV: Ignored, whatever it is.
-
-    @rtype: L{tlslite.utils.RC4}
-    @return: An RC4 object.
-    """
-    if implList == None:
-        implList = ["openssl", "pycrypto", "python"]
-
-    if len(IV) != 0:
-        raise AssertionError()
-    for impl in implList:
-        if impl == "openssl" and cryptomath.m2cryptoLoaded:
-            return openssl_rc4.new(key)
-        elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
-            return pycrypto_rc4.new(key)
-        elif impl == "python":
-            return python_rc4.new(key)
-    raise NotImplementedError()
-
-#Create a new TripleDES instance
-def createTripleDES(key, IV, implList=None):
-    """Create a new 3DES object.
-
-    @type key: str
-    @param key: A 24 byte string.
-
-    @type IV: str
-    @param IV: An 8 byte string
-
-    @rtype: L{tlslite.utils.TripleDES}
-    @return: A 3DES object.
-    """
-    if implList == None:
-        implList = ["openssl", "pycrypto"]
-
-    for impl in implList:
-        if impl == "openssl" and cryptomath.m2cryptoLoaded:
-            return openssl_tripledes.new(key, 2, IV)
-        elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
-            return pycrypto_tripledes.new(key, 2, IV)
-    raise NotImplementedError()
diff --git a/third_party/tlslite/tlslite/utils/codec.py b/third_party/tlslite/tlslite/utils/codec.py
deleted file mode 100644
index f1e21c9..0000000
--- a/third_party/tlslite/tlslite/utils/codec.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Classes for reading/writing binary data (such as TLS records)."""
-
-from .compat import *
-
-class Writer(object):
-    def __init__(self):
-        self.bytes = bytearray(0)
-
-    def add(self, x, length):
-        self.bytes += bytearray(length)
-        newIndex = len(self.bytes) - 1
-        for count in range(length):
-            self.bytes[newIndex] = x & 0xFF
-            x >>= 8
-            newIndex -= 1
-
-    def addFixSeq(self, seq, length):
-        for e in seq:
-            self.add(e, length)
-
-    def addVarSeq(self, seq, length, lengthLength):
-        self.add(len(seq)*length, lengthLength)
-        for e in seq:
-            self.add(e, length)
-
-class Parser(object):
-    def __init__(self, bytes):
-        self.bytes = bytes
-        self.index = 0
-
-    def get(self, length):
-        if self.index + length > len(self.bytes):
-            raise SyntaxError()
-        x = 0
-        for count in range(length):
-            x <<= 8
-            x |= self.bytes[self.index]
-            self.index += 1
-        return x
-
-    def getFixBytes(self, lengthBytes):
-        bytes = self.bytes[self.index : self.index+lengthBytes]
-        self.index += lengthBytes
-        return bytes
-
-    def getVarBytes(self, lengthLength):
-        lengthBytes = self.get(lengthLength)
-        return self.getFixBytes(lengthBytes)
-
-    def getFixList(self, length, lengthList):
-        l = [0] * lengthList
-        for x in range(lengthList):
-            l[x] = self.get(length)
-        return l
-
-    def getVarList(self, length, lengthLength):
-        lengthList = self.get(lengthLength)
-        if lengthList % length != 0:
-            raise SyntaxError()
-        lengthList = lengthList // length
-        l = [0] * lengthList
-        for x in range(lengthList):
-            l[x] = self.get(length)
-        return l
-
-    def startLengthCheck(self, lengthLength):
-        self.lengthCheck = self.get(lengthLength)
-        self.indexCheck = self.index
-
-    def setLengthCheck(self, length):
-        self.lengthCheck = length
-        self.indexCheck = self.index
-
-    def stopLengthCheck(self):
-        if (self.index - self.indexCheck) != self.lengthCheck:
-            raise SyntaxError()
-
-    def atLengthCheck(self):
-        if (self.index - self.indexCheck) < self.lengthCheck:
-            return False
-        elif (self.index - self.indexCheck) == self.lengthCheck:
-            return True
-        else:
-            raise SyntaxError()
diff --git a/third_party/tlslite/tlslite/utils/compat.py b/third_party/tlslite/tlslite/utils/compat.py
deleted file mode 100644
index 124f630..0000000
--- a/third_party/tlslite/tlslite/utils/compat.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Miscellaneous functions to mask Python version differences."""
-
-import sys
-import os
-import math
-import binascii
-
-if sys.version_info >= (3,0):
-
-    def compat26Str(x): return x
-    
-    # Python 3 requires bytes instead of bytearrays for HMAC   
-    
-    # So, python 2.6 requires strings, python 3 requires 'bytes',
-    # and python 2.7 can handle bytearrays...     
-    def compatHMAC(x): return bytes(x)
-    
-    def raw_input(s):
-        return input(s)
-    
-    # So, the python3 binascii module deals with bytearrays, and python2
-    # deals with strings...  I would rather deal with the "a" part as
-    # strings, and the "b" part as bytearrays, regardless of python version,
-    # so...
-    def a2b_hex(s):
-        try:
-            b = bytearray(binascii.a2b_hex(bytearray(s, "ascii")))
-        except Exception as e:
-            raise SyntaxError("base16 error: %s" % e) 
-        return b  
-
-    def a2b_base64(s):
-        try:
-            b = bytearray(binascii.a2b_base64(bytearray(s, "ascii")))
-        except Exception as e:
-            raise SyntaxError("base64 error: %s" % e)
-        return b
-
-    def b2a_hex(b):
-        return binascii.b2a_hex(b).decode("ascii")    
-            
-    def b2a_base64(b):
-        return binascii.b2a_base64(b).decode("ascii") 
-
-    def readStdinBinary():
-        return sys.stdin.buffer.read()        
-
-else:
-    # Python 2.6 requires strings instead of bytearrays in a couple places,
-    # so we define this function so it does the conversion if needed.
-    if sys.version_info < (2,7):
-        def compat26Str(x): return str(x)
-    else:
-        def compat26Str(x): return x
-
-    # So, python 2.6 requires strings, python 3 requires 'bytes',
-    # and python 2.7 can handle bytearrays...     
-    def compatHMAC(x): return compat26Str(x)
-
-    def a2b_hex(s):
-        try:
-            b = bytearray(binascii.a2b_hex(s))
-        except Exception as e:
-            raise SyntaxError("base16 error: %s" % e)
-        return b
-
-    def a2b_base64(s):
-        try:
-            b = bytearray(binascii.a2b_base64(s))
-        except Exception as e:
-            raise SyntaxError("base64 error: %s" % e)
-        return b
-        
-    def b2a_hex(b):
-        return binascii.b2a_hex(compat26Str(b))
-        
-    def b2a_base64(b):
-        return binascii.b2a_base64(compat26Str(b))
-        
-import traceback
-def formatExceptionTrace(e):
-    newStr = "".join(traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
-    return newStr
-
diff --git a/third_party/tlslite/tlslite/utils/cryptomath.py b/third_party/tlslite/tlslite/utils/cryptomath.py
deleted file mode 100644
index f7142c0..0000000
--- a/third_party/tlslite/tlslite/utils/cryptomath.py
+++ /dev/null
@@ -1,312 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Martin von Loewis - python 3 port
-#   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""cryptomath module
-
-This module has basic math/crypto code."""
-from __future__ import print_function
-import os
-import math
-import base64
-import binascii
-
-from .compat import *
-
-
-# **************************************************************************
-# Load Optional Modules
-# **************************************************************************
-
-# Try to load M2Crypto/OpenSSL
-try:
-    from M2Crypto import m2
-    m2cryptoLoaded = True
-
-except ImportError:
-    m2cryptoLoaded = False
-
-#Try to load GMPY
-try:
-    import gmpy
-    gmpyLoaded = True
-except ImportError:
-    gmpyLoaded = False
-
-#Try to load pycrypto
-try:
-    import Crypto.Cipher.AES
-    pycryptoLoaded = True
-except ImportError:
-    pycryptoLoaded = False
-
-
-# **************************************************************************
-# PRNG Functions
-# **************************************************************************
-
-# Check that os.urandom works
-import zlib
-length = len(zlib.compress(os.urandom(1000)))
-assert(length > 900)
-
-def getRandomBytes(howMany):
-    b = bytearray(os.urandom(howMany))
-    assert(len(b) == howMany)
-    return b
-
-prngName = "os.urandom"
-
-# **************************************************************************
-# Simple hash functions
-# **************************************************************************
-
-import hmac
-import hashlib
-
-def MD5(b):
-    return bytearray(hashlib.md5(compat26Str(b)).digest())
-
-def SHA1(b):
-    return bytearray(hashlib.sha1(compat26Str(b)).digest())
-
-def SHA256(b):
-    return bytearray(hashlib.sha256(compat26Str(b)).digest())
-
-def HMAC_MD5(k, b):
-    k = compatHMAC(k)
-    b = compatHMAC(b)
-    return bytearray(hmac.new(k, b, hashlib.md5).digest())
-
-def HMAC_SHA1(k, b):
-    k = compatHMAC(k)
-    b = compatHMAC(b)
-    return bytearray(hmac.new(k, b, hashlib.sha1).digest())
-
-def HMAC_SHA256(k, b):
-    k = compatHMAC(k)
-    b = compatHMAC(b)
-    return bytearray(hmac.new(k, b, hashlib.sha256).digest())
-
-# **************************************************************************
-# Converter Functions
-# **************************************************************************
-
-def bytesToNumber(b):
-    total = 0
-    multiplier = 1
-    for count in range(len(b)-1, -1, -1):
-        byte = b[count]
-        total += multiplier * byte
-        multiplier *= 256
-    return total
-
-def numberToByteArray(n, howManyBytes=None):
-    """Convert an integer into a bytearray, zero-pad to howManyBytes.
-
-    The returned bytearray may be smaller than howManyBytes, but will
-    not be larger.  The returned bytearray will contain a big-endian
-    encoding of the input integer (n).
-    """    
-    if howManyBytes == None:
-        howManyBytes = numBytes(n)
-    b = bytearray(howManyBytes)
-    for count in range(howManyBytes-1, -1, -1):
-        b[count] = int(n % 256)
-        n >>= 8
-    return b
-
-def mpiToNumber(mpi): #mpi is an openssl-format bignum string
-    if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number
-        raise AssertionError()
-    b = bytearray(mpi[4:])
-    return bytesToNumber(b)
-
-def numberToMPI(n):
-    b = numberToByteArray(n)
-    ext = 0
-    #If the high-order bit is going to be set,
-    #add an extra byte of zeros
-    if (numBits(n) & 0x7)==0:
-        ext = 1
-    length = numBytes(n) + ext
-    b = bytearray(4+ext) + b
-    b[0] = (length >> 24) & 0xFF
-    b[1] = (length >> 16) & 0xFF
-    b[2] = (length >> 8) & 0xFF
-    b[3] = length & 0xFF
-    return bytes(b)
-
-
-# **************************************************************************
-# Misc. Utility Functions
-# **************************************************************************
-
-def numBits(n):
-    if n==0:
-        return 0
-    s = "%x" % n
-    return ((len(s)-1)*4) + \
-    {'0':0, '1':1, '2':2, '3':2,
-     '4':3, '5':3, '6':3, '7':3,
-     '8':4, '9':4, 'a':4, 'b':4,
-     'c':4, 'd':4, 'e':4, 'f':4,
-     }[s[0]]
-    return int(math.floor(math.log(n, 2))+1)
-
-def numBytes(n):
-    if n==0:
-        return 0
-    bits = numBits(n)
-    return int(math.ceil(bits / 8.0))
-
-# **************************************************************************
-# Big Number Math
-# **************************************************************************
-
-def getRandomNumber(low, high):
-    if low >= high:
-        raise AssertionError()
-    howManyBits = numBits(high)
-    howManyBytes = numBytes(high)
-    lastBits = howManyBits % 8
-    while 1:
-        bytes = getRandomBytes(howManyBytes)
-        if lastBits:
-            bytes[0] = bytes[0] % (1 << lastBits)
-        n = bytesToNumber(bytes)
-        if n >= low and n < high:
-            return n
-
-def gcd(a,b):
-    a, b = max(a,b), min(a,b)
-    while b:
-        a, b = b, a % b
-    return a
-
-def lcm(a, b):
-    return (a * b) // gcd(a, b)
-
-#Returns inverse of a mod b, zero if none
-#Uses Extended Euclidean Algorithm
-def invMod(a, b):
-    c, d = a, b
-    uc, ud = 1, 0
-    while c != 0:
-        q = d // c
-        c, d = d-(q*c), c
-        uc, ud = ud - (q * uc), uc
-    if d == 1:
-        return ud % b
-    return 0
-
-
-if gmpyLoaded:
-    def powMod(base, power, modulus):
-        base = gmpy.mpz(base)
-        power = gmpy.mpz(power)
-        modulus = gmpy.mpz(modulus)
-        result = pow(base, power, modulus)
-        return long(result)
-
-else:
-    def powMod(base, power, modulus):
-        if power < 0:
-            result = pow(base, power*-1, modulus)
-            result = invMod(result, modulus)
-            return result
-        else:
-            return pow(base, power, modulus)
-
-#Pre-calculate a sieve of the ~100 primes < 1000:
-def makeSieve(n):
-    sieve = list(range(n))
-    for count in range(2, int(math.sqrt(n))+1):
-        if sieve[count] == 0:
-            continue
-        x = sieve[count] * 2
-        while x < len(sieve):
-            sieve[x] = 0
-            x += sieve[count]
-    sieve = [x for x in sieve[2:] if x]
-    return sieve
-
-sieve = makeSieve(1000)
-
-def isPrime(n, iterations=5, display=False):
-    #Trial division with sieve
-    for x in sieve:
-        if x >= n: return True
-        if n % x == 0: return False
-    #Passed trial division, proceed to Rabin-Miller
-    #Rabin-Miller implemented per Ferguson & Schneier
-    #Compute s, t for Rabin-Miller
-    if display: print("*", end=' ')
-    s, t = n-1, 0
-    while s % 2 == 0:
-        s, t = s//2, t+1
-    #Repeat Rabin-Miller x times
-    a = 2 #Use 2 as a base for first iteration speedup, per HAC
-    for count in range(iterations):
-        v = powMod(a, s, n)
-        if v==1:
-            continue
-        i = 0
-        while v != n-1:
-            if i == t-1:
-                return False
-            else:
-                v, i = powMod(v, 2, n), i+1
-        a = getRandomNumber(2, n)
-    return True
-
-def getRandomPrime(bits, display=False):
-    if bits < 10:
-        raise AssertionError()
-    #The 1.5 ensures the 2 MSBs are set
-    #Thus, when used for p,q in RSA, n will have its MSB set
-    #
-    #Since 30 is lcm(2,3,5), we'll set our test numbers to
-    #29 % 30 and keep them there
-    low = ((2 ** (bits-1)) * 3) // 2
-    high = 2 ** bits - 30
-    p = getRandomNumber(low, high)
-    p += 29 - (p % 30)
-    while 1:
-        if display: print(".", end=' ')
-        p += 30
-        if p >= high:
-            p = getRandomNumber(low, high)
-            p += 29 - (p % 30)
-        if isPrime(p, display=display):
-            return p
-
-#Unused at the moment...
-def getRandomSafePrime(bits, display=False):
-    if bits < 10:
-        raise AssertionError()
-    #The 1.5 ensures the 2 MSBs are set
-    #Thus, when used for p,q in RSA, n will have its MSB set
-    #
-    #Since 30 is lcm(2,3,5), we'll set our test numbers to
-    #29 % 30 and keep them there
-    low = (2 ** (bits-2)) * 3//2
-    high = (2 ** (bits-1)) - 30
-    q = getRandomNumber(low, high)
-    q += 29 - (q % 30)
-    while 1:
-        if display: print(".", end=' ')
-        q += 30
-        if (q >= high):
-            q = getRandomNumber(low, high)
-            q += 29 - (q % 30)
-        #Ideas from Tom Wu's SRP code
-        #Do trial division on p and q before Rabin-Miller
-        if isPrime(q, 0, display=display):
-            p = (2 * q) + 1
-            if isPrime(p, display=display):
-                if isPrime(q, display=display):
-                    return p
diff --git a/third_party/tlslite/tlslite/utils/datefuncs.py b/third_party/tlslite/tlslite/utils/datefuncs.py
deleted file mode 100644
index d8f0d240..0000000
--- a/third_party/tlslite/tlslite/utils/datefuncs.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-import os
-
-#Functions for manipulating datetime objects
-#CCYY-MM-DDThh:mm:ssZ
-def parseDateClass(s):
-    year, month, day = s.split("-")
-    day, tail = day[:2], day[2:]
-    hour, minute, second = tail[1:].split(":")
-    second = second[:2]
-    year, month, day = int(year), int(month), int(day)
-    hour, minute, second = int(hour), int(minute), int(second)
-    return createDateClass(year, month, day, hour, minute, second)
-
-
-if os.name != "java":
-    from datetime import datetime, timedelta
-
-    #Helper functions for working with a date/time class
-    def createDateClass(year, month, day, hour, minute, second):
-        return datetime(year, month, day, hour, minute, second)
-
-    def printDateClass(d):
-        #Split off fractional seconds, append 'Z'
-        return d.isoformat().split(".")[0]+"Z"
-
-    def getNow():
-        return datetime.utcnow()
-
-    def getHoursFromNow(hours):
-        return datetime.utcnow() + timedelta(hours=hours)
-
-    def getMinutesFromNow(minutes):
-        return datetime.utcnow() + timedelta(minutes=minutes)
-
-    def isDateClassExpired(d):
-        return d < datetime.utcnow()
-
-    def isDateClassBefore(d1, d2):
-        return d1 < d2
-
-else:
-    #Jython 2.1 is missing lots of python 2.3 stuff,
-    #which we have to emulate here:
-    import java
-    import jarray
-
-    def createDateClass(year, month, day, hour, minute, second):
-        c = java.util.Calendar.getInstance()
-        c.setTimeZone(java.util.TimeZone.getTimeZone("UTC"))
-        c.set(year, month-1, day, hour, minute, second)
-        return c
-
-    def printDateClass(d):
-        return "%04d-%02d-%02dT%02d:%02d:%02dZ" % \
-        (d.get(d.YEAR), d.get(d.MONTH)+1, d.get(d.DATE), \
-        d.get(d.HOUR_OF_DAY), d.get(d.MINUTE), d.get(d.SECOND))
-
-    def getNow():
-        c = java.util.Calendar.getInstance()
-        c.setTimeZone(java.util.TimeZone.getTimeZone("UTC"))
-        c.get(c.HOUR) #force refresh?
-        return c
-
-    def getHoursFromNow(hours):
-        d = getNow()
-        d.add(d.HOUR, hours)
-        return d
-
-    def isDateClassExpired(d):
-        n = getNow()
-        return d.before(n)
-
-    def isDateClassBefore(d1, d2):
-        return d1.before(d2)
diff --git a/third_party/tlslite/tlslite/utils/keyfactory.py b/third_party/tlslite/tlslite/utils/keyfactory.py
deleted file mode 100644
index 1ee338f3..0000000
--- a/third_party/tlslite/tlslite/utils/keyfactory.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Factory functions for asymmetric cryptography.
-@sort: generateRSAKey, parsePEMKey, parseAsPublicKey
-"""
-
-from .compat import *
-
-from .rsakey import RSAKey
-from .python_rsakey import Python_RSAKey
-from tlslite.utils import cryptomath
-
-if cryptomath.m2cryptoLoaded:
-    from .openssl_rsakey import OpenSSL_RSAKey
-
-if cryptomath.pycryptoLoaded:
-    from .pycrypto_rsakey import PyCrypto_RSAKey
-
-# **************************************************************************
-# Factory Functions for RSA Keys
-# **************************************************************************
-
-def generateRSAKey(bits, implementations=["openssl", "python"]):
-    """Generate an RSA key with the specified bit length.
-
-    @type bits: int
-    @param bits: Desired bit length of the new key's modulus.
-
-    @rtype: L{tlslite.utils.rsakey.RSAKey}
-    @return: A new RSA private key.
-    """
-    for implementation in implementations:
-        if implementation == "openssl" and cryptomath.m2cryptoLoaded:
-            return OpenSSL_RSAKey.generate(bits)
-        elif implementation == "python":
-            return Python_RSAKey.generate(bits)
-    raise ValueError("No acceptable implementations")
-
-#Parse as an OpenSSL or Python key
-def parsePEMKey(s, private=False, public=False, passwordCallback=None,
-                implementations=["openssl", "python"]):
-    """Parse a PEM-format key.
-
-    The PEM format is used by OpenSSL and other tools.  The
-    format is typically used to store both the public and private
-    components of a key.  For example::
-
-       -----BEGIN RSA PRIVATE KEY-----
-        MIICXQIBAAKBgQDYscuoMzsGmW0pAYsmyHltxB2TdwHS0dImfjCMfaSDkfLdZY5+
-        dOWORVns9etWnr194mSGA1F0Pls/VJW8+cX9+3vtJV8zSdANPYUoQf0TP7VlJxkH
-        dSRkUbEoz5bAAs/+970uos7n7iXQIni+3erUTdYEk2iWnMBjTljfgbK/dQIDAQAB
-        AoGAJHoJZk75aKr7DSQNYIHuruOMdv5ZeDuJvKERWxTrVJqE32/xBKh42/IgqRrc
-        esBN9ZregRCd7YtxoL+EVUNWaJNVx2mNmezEznrc9zhcYUrgeaVdFO2yBF1889zO
-        gCOVwrO8uDgeyj6IKa25H6c1N13ih/o7ZzEgWbGG+ylU1yECQQDv4ZSJ4EjSh/Fl
-        aHdz3wbBa/HKGTjC8iRy476Cyg2Fm8MZUe9Yy3udOrb5ZnS2MTpIXt5AF3h2TfYV
-        VoFXIorjAkEA50FcJmzT8sNMrPaV8vn+9W2Lu4U7C+K/O2g1iXMaZms5PC5zV5aV
-        CKXZWUX1fq2RaOzlbQrpgiolhXpeh8FjxwJBAOFHzSQfSsTNfttp3KUpU0LbiVvv
-        i+spVSnA0O4rq79KpVNmK44Mq67hsW1P11QzrzTAQ6GVaUBRv0YS061td1kCQHnP
-        wtN2tboFR6lABkJDjxoGRvlSt4SOPr7zKGgrWjeiuTZLHXSAnCY+/hr5L9Q3ZwXG
-        6x6iBdgLjVIe4BZQNtcCQQDXGv/gWinCNTN3MPWfTW/RGzuMYVmyBFais0/VrgdH
-        h1dLpztmpQqfyH/zrBXQ9qL/zR4ojS6XYneO/U18WpEe
-        -----END RSA PRIVATE KEY-----
-
-    To generate a key like this with OpenSSL, run::
-
-        openssl genrsa 2048 > key.pem
-
-    This format also supports password-encrypted private keys.  TLS
-    Lite can only handle password-encrypted private keys when OpenSSL
-    and M2Crypto are installed.  In this case, passwordCallback will be
-    invoked to query the user for the password.
-
-    @type s: str
-    @param s: A string containing a PEM-encoded public or private key.
-
-    @type private: bool
-    @param private: If True, a L{SyntaxError} will be raised if the
-    private key component is not present.
-
-    @type public: bool
-    @param public: If True, the private key component (if present) will
-    be discarded, so this function will always return a public key.
-
-    @type passwordCallback: callable
-    @param passwordCallback: This function will be called, with no
-    arguments, if the PEM-encoded private key is password-encrypted.
-    The callback should return the password string.  If the password is
-    incorrect, SyntaxError will be raised.  If no callback is passed
-    and the key is password-encrypted, a prompt will be displayed at
-    the console.
-
-    @rtype: L{tlslite.utils.RSAKey.RSAKey}
-    @return: An RSA key.
-
-    @raise SyntaxError: If the key is not properly formatted.
-    """
-    for implementation in implementations:
-        if implementation == "openssl" and cryptomath.m2cryptoLoaded:
-            key = OpenSSL_RSAKey.parse(s, passwordCallback)
-            break
-        elif implementation == "python":
-            key = Python_RSAKey.parsePEM(s)
-            break
-    else:
-        raise ValueError("No acceptable implementations")
-
-    return _parseKeyHelper(key, private, public)
-
-
-def _parseKeyHelper(key, private, public):
-    if private:
-        if not key.hasPrivateKey():
-            raise SyntaxError("Not a private key!")
-
-    if public:
-        return _createPublicKey(key)
-
-    if private:
-        if hasattr(key, "d"):
-            return _createPrivateKey(key)
-        else:
-            return key
-
-    return key
-
-def parseAsPublicKey(s):
-    """Parse a PEM-formatted public key.
-
-    @type s: str
-    @param s: A string containing a PEM-encoded public or private key.
-
-    @rtype: L{tlslite.utils.rsakey.RSAKey}
-    @return: An RSA public key.
-
-    @raise SyntaxError: If the key is not properly formatted.
-    """
-    return parsePEMKey(s, public=True)
-
-def parsePrivateKey(s):
-    """Parse a PEM-formatted private key.
-
-    @type s: str
-    @param s: A string containing a PEM-encoded private key.
-
-    @rtype: L{tlslite.utils.rsakey.RSAKey}
-    @return: An RSA private key.
-
-    @raise SyntaxError: If the key is not properly formatted.
-    """
-    return parsePEMKey(s, private=True)
-
-def _createPublicKey(key):
-    """
-    Create a new public key.  Discard any private component,
-    and return the most efficient key possible.
-    """
-    if not isinstance(key, RSAKey):
-        raise AssertionError()
-    return _createPublicRSAKey(key.n, key.e)
-
-def _createPrivateKey(key):
-    """
-    Create a new private key.  Return the most efficient key possible.
-    """
-    if not isinstance(key, RSAKey):
-        raise AssertionError()
-    if not key.hasPrivateKey():
-        raise AssertionError()
-    return _createPrivateRSAKey(key.n, key.e, key.d, key.p, key.q, key.dP,
-                                key.dQ, key.qInv)
-
-def _createPublicRSAKey(n, e, implementations = ["openssl", "pycrypto",
-                                                "python"]):
-    for implementation in implementations:
-        if implementation == "openssl" and cryptomath.m2cryptoLoaded:
-            return OpenSSL_RSAKey(n, e)
-        elif implementation == "pycrypto" and cryptomath.pycryptoLoaded:
-            return PyCrypto_RSAKey(n, e)
-        elif implementation == "python":
-            return Python_RSAKey(n, e)
-    raise ValueError("No acceptable implementations")
-
-def _createPrivateRSAKey(n, e, d, p, q, dP, dQ, qInv,
-                        implementations = ["pycrypto", "python"]):
-    for implementation in implementations:
-        if implementation == "pycrypto" and cryptomath.pycryptoLoaded:
-            return PyCrypto_RSAKey(n, e, d, p, q, dP, dQ, qInv)
-        elif implementation == "python":
-            return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
-    raise ValueError("No acceptable implementations")
diff --git a/third_party/tlslite/tlslite/utils/openssl_aes.py b/third_party/tlslite/tlslite/utils/openssl_aes.py
deleted file mode 100644
index 658cf83..0000000
--- a/third_party/tlslite/tlslite/utils/openssl_aes.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""OpenSSL/M2Crypto AES implementation."""
-
-from .cryptomath import *
-from .aes import *
-
-if m2cryptoLoaded:
-
-    def new(key, mode, IV):
-        return OpenSSL_AES(key, mode, IV)
-
-    class OpenSSL_AES(AES):
-
-        def __init__(self, key, mode, IV):
-            AES.__init__(self, key, mode, IV, "openssl")
-            self.key = key
-            self.IV = IV
-
-        def _createContext(self, encrypt):
-            context = m2.cipher_ctx_new()
-            if len(self.key)==16:
-                cipherType = m2.aes_128_cbc()
-            if len(self.key)==24:
-                cipherType = m2.aes_192_cbc()
-            if len(self.key)==32:
-                cipherType = m2.aes_256_cbc()
-            m2.cipher_init(context, cipherType, self.key, self.IV, encrypt)
-            return context
-
-        def encrypt(self, plaintext):
-            AES.encrypt(self, plaintext)
-            context = self._createContext(1)
-            ciphertext = m2.cipher_update(context, plaintext)
-            m2.cipher_ctx_free(context)
-            self.IV = ciphertext[-self.block_size:]
-            return bytearray(ciphertext)
-
-        def decrypt(self, ciphertext):
-            AES.decrypt(self, ciphertext)
-            context = self._createContext(0)
-            #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in.
-            #To work around this, we append sixteen zeros to the string, below:
-            plaintext = m2.cipher_update(context, ciphertext+('\0'*16))
-
-            #If this bug is ever fixed, then plaintext will end up having a garbage
-            #plaintext block on the end.  That's okay - the below code will discard it.
-            plaintext = plaintext[:len(ciphertext)]
-            m2.cipher_ctx_free(context)
-            self.IV = ciphertext[-self.block_size:]
-            return bytearray(plaintext)
diff --git a/third_party/tlslite/tlslite/utils/openssl_rc4.py b/third_party/tlslite/tlslite/utils/openssl_rc4.py
deleted file mode 100644
index 2fbfa07e..0000000
--- a/third_party/tlslite/tlslite/utils/openssl_rc4.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""OpenSSL/M2Crypto RC4 implementation."""
-
-from .cryptomath import *
-from .rc4 import RC4
-
-if m2cryptoLoaded:
-
-    def new(key):
-        return OpenSSL_RC4(key)
-
-    class OpenSSL_RC4(RC4):
-
-        def __init__(self, key):
-            RC4.__init__(self, key, "openssl")
-            self.rc4 = m2.rc4_new()
-            m2.rc4_set_key(self.rc4, key)
-
-        def __del__(self):
-            m2.rc4_free(self.rc4)
-
-        def encrypt(self, plaintext):
-            return bytearray(m2.rc4_update(self.rc4, plaintext))
-
-        def decrypt(self, ciphertext):
-            return bytearray(self.encrypt(ciphertext))
diff --git a/third_party/tlslite/tlslite/utils/openssl_rsakey.py b/third_party/tlslite/tlslite/utils/openssl_rsakey.py
deleted file mode 100644
index f6ec85958..0000000
--- a/third_party/tlslite/tlslite/utils/openssl_rsakey.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""OpenSSL/M2Crypto RSA implementation."""
-
-from .cryptomath import *
-
-from .rsakey import *
-from .python_rsakey import Python_RSAKey
-
-#copied from M2Crypto.util.py, so when we load the local copy of m2
-#we can still use it
-def password_callback(v, prompt1='Enter private key passphrase:',
-                           prompt2='Verify passphrase:'):
-    from getpass import getpass
-    while 1:
-        try:
-            p1=getpass(prompt1)
-            if v:
-                p2=getpass(prompt2)
-                if p1==p2:
-                    break
-            else:
-                break
-        except KeyboardInterrupt:
-            return None
-    return p1
-
-
-if m2cryptoLoaded:
-    class OpenSSL_RSAKey(RSAKey):
-        def __init__(self, n=0, e=0):
-            self.rsa = None
-            self._hasPrivateKey = False
-            if (n and not e) or (e and not n):
-                raise AssertionError()
-            if n and e:
-                self.rsa = m2.rsa_new()
-                m2.rsa_set_n(self.rsa, numberToMPI(n))
-                m2.rsa_set_e(self.rsa, numberToMPI(e))
-
-        def __del__(self):
-            if self.rsa:
-                m2.rsa_free(self.rsa)
-
-        def __getattr__(self, name):
-            if name == 'e':
-                if not self.rsa:
-                    return 0
-                return mpiToNumber(m2.rsa_get_e(self.rsa))
-            elif name == 'n':
-                if not self.rsa:
-                    return 0
-                return mpiToNumber(m2.rsa_get_n(self.rsa))
-            else:
-                raise AttributeError
-
-        def hasPrivateKey(self):
-            return self._hasPrivateKey
-
-        def _rawPrivateKeyOp(self, m):
-            b = numberToByteArray(m, numBytes(self.n))
-            s = m2.rsa_private_encrypt(self.rsa, bytes(b), m2.no_padding)
-            c = bytesToNumber(bytearray(s))
-            return c
-
-        def _rawPublicKeyOp(self, c):
-            b = numberToByteArray(c, numBytes(self.n))
-            s = m2.rsa_public_decrypt(self.rsa, bytes(b), m2.no_padding)
-            m = bytesToNumber(bytearray(s))
-            return m
-
-        def acceptsPassword(self): return True
-
-        def write(self, password=None):
-            bio = m2.bio_new(m2.bio_s_mem())
-            if self._hasPrivateKey:
-                if password:
-                    def f(v): return password
-                    m2.rsa_write_key(self.rsa, bio, m2.des_ede_cbc(), f)
-                else:
-                    def f(): pass
-                    m2.rsa_write_key_no_cipher(self.rsa, bio, f)
-            else:
-                if password:
-                    raise AssertionError()
-                m2.rsa_write_pub_key(self.rsa, bio)
-            s = m2.bio_read(bio, m2.bio_ctrl_pending(bio))
-            m2.bio_free(bio)
-            return s
-
-        def generate(bits):
-            key = OpenSSL_RSAKey()
-            def f():pass
-            key.rsa = m2.rsa_generate_key(bits, 3, f)
-            key._hasPrivateKey = True
-            return key
-        generate = staticmethod(generate)
-
-        def parse(s, passwordCallback=None):
-            # Skip forward to the first PEM header
-            start = s.find("-----BEGIN ")
-            if start == -1:
-                raise SyntaxError()
-            s = s[start:]            
-            if s.startswith("-----BEGIN "):
-                if passwordCallback==None:
-                    callback = password_callback
-                else:
-                    def f(v, prompt1=None, prompt2=None):
-                        return passwordCallback()
-                    callback = f
-                bio = m2.bio_new(m2.bio_s_mem())
-                try:
-                    m2.bio_write(bio, s)
-                    key = OpenSSL_RSAKey()
-                    if s.startswith("-----BEGIN RSA PRIVATE KEY-----"):
-                        def f():pass
-                        key.rsa = m2.rsa_read_key(bio, callback)
-                        if key.rsa == None:
-                            raise SyntaxError()
-                        key._hasPrivateKey = True
-                    elif s.startswith("-----BEGIN PUBLIC KEY-----"):
-                        key.rsa = m2.rsa_read_pub_key(bio)
-                        if key.rsa == None:
-                            raise SyntaxError()
-                        key._hasPrivateKey = False
-                    else:
-                        raise SyntaxError()
-                    return key
-                finally:
-                    m2.bio_free(bio)
-            else:
-                raise SyntaxError()
-
-        parse = staticmethod(parse)
diff --git a/third_party/tlslite/tlslite/utils/openssl_tripledes.py b/third_party/tlslite/tlslite/utils/openssl_tripledes.py
deleted file mode 100644
index 15a68bb4..0000000
--- a/third_party/tlslite/tlslite/utils/openssl_tripledes.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""OpenSSL/M2Crypto 3DES implementation."""
-
-from .cryptomath import *
-from .tripledes import *
-
-if m2cryptoLoaded:
-
-    def new(key, mode, IV):
-        return OpenSSL_TripleDES(key, mode, IV)
-
-    class OpenSSL_TripleDES(TripleDES):
-
-        def __init__(self, key, mode, IV):
-            TripleDES.__init__(self, key, mode, IV, "openssl")
-            self.key = key
-            self.IV = IV
-
-        def _createContext(self, encrypt):
-            context = m2.cipher_ctx_new()
-            cipherType = m2.des_ede3_cbc()
-            m2.cipher_init(context, cipherType, self.key, self.IV, encrypt)
-            return context
-
-        def encrypt(self, plaintext):
-            TripleDES.encrypt(self, plaintext)
-            context = self._createContext(1)
-            ciphertext = m2.cipher_update(context, plaintext)
-            m2.cipher_ctx_free(context)
-            self.IV = ciphertext[-self.block_size:]
-            return bytearray(ciphertext)
-
-        def decrypt(self, ciphertext):
-            TripleDES.decrypt(self, ciphertext)
-            context = self._createContext(0)
-            #I think M2Crypto has a bug - it fails to decrypt and return the last block passed in.
-            #To work around this, we append sixteen zeros to the string, below:
-            plaintext = m2.cipher_update(context, ciphertext+('\0'*16))
-
-            #If this bug is ever fixed, then plaintext will end up having a garbage
-            #plaintext block on the end.  That's okay - the below code will ignore it.
-            plaintext = plaintext[:len(ciphertext)]
-            m2.cipher_ctx_free(context)
-            self.IV = ciphertext[-self.block_size:]
-            return bytearray(plaintext)
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/utils/p256.py b/third_party/tlslite/tlslite/utils/p256.py
deleted file mode 100644
index 45159000..0000000
--- a/third_party/tlslite/tlslite/utils/p256.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# Author: Google
-# See the LICENSE file for legal information regarding use of this file.
-
-import os
-import six
-
-p = (
-    115792089210356248762697446949407573530086143415290314195533631308867097853951)
-order = (
-    115792089210356248762697446949407573529996955224135760342422259061068512044369)
-p256B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
-
-baseX = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
-baseY = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
-basePoint = (baseX, baseY)
-
-
-def _pointAdd(a, b):
-    Z1Z1 = (a[2] * a[2]) % p
-    Z2Z2 = (b[2] * b[2]) % p
-    U1 = (a[0] * Z2Z2) % p
-    U2 = (b[0] * Z1Z1) % p
-    S1 = (a[1] * b[2] * Z2Z2) % p
-    S2 = (b[1] * a[2] * Z1Z1) % p
-    if U1 == U2 and S1 == S2:
-        return pointDouble(a)
-    H = (U2 - U1) % p
-    I = (4 * H * H) % p
-    J = (H * I) % p
-    r = (2 * (S2 - S1)) % p
-    V = (U1 * I) % p
-    X3 = (r * r - J - 2 * V) % p
-    Y3 = (r * (V - X3) - 2 * S1 * J) % p
-    Z3 = (((a[2] + b[2]) * (a[2] + b[2]) - Z1Z1 - Z2Z2) * H) % p
-
-    return (X3, Y3, Z3)
-
-
-def _pointDouble(a):
-    delta = (a[2] * a[2]) % p
-    gamma = (a[1] * a[1]) % p
-    beta = (a[0] * gamma) % p
-    alpha = (3 * (a[0] - delta) * (a[0] + delta)) % p
-    X3 = (alpha * alpha - 8 * beta) % p
-    Z3 = ((a[1] + a[2]) * (a[1] + a[2]) - gamma - delta) % p
-    Y3 = (alpha * (4 * beta - X3) - 8 * gamma * gamma) % p
-
-    return (X3, Y3, Z3)
-
-
-def _square(n):
-    return (n * n)
-
-
-def _modpow(a, n, p):
-    if n == 0:
-        return 1
-    if n == 1:
-        return a
-    r = _square(_modpow(a, n >> 1, p)) % p
-    if n & 1 == 1:
-        r = (r * a) % p
-    return r
-
-
-def _scalarMult(k, point):
-    accum = (0, 0, 0)
-    accumIsInfinity = True
-    jacobianPoint = (point[0], point[1], 1)
-
-    for bit in range(255, -1, -1):
-        if not accumIsInfinity:
-            accum = _pointDouble(accum)
-
-        if (k >> bit) & 1 == 1:
-            if accumIsInfinity:
-                accum = jacobianPoint
-                accumIsInfinity = False
-            else:
-                accum = _pointAdd(accum, jacobianPoint)
-
-    if accumIsInfinity:
-        return (0, 0)
-
-    zInv = _modpow(accum[2], p - 2, p)
-    return ((accum[0] * zInv * zInv) % p, (accum[1] * zInv * zInv * zInv) % p)
-
-
-def _scalarBaseMult(k):
-    return _scalarMult(k, basePoint)
-
-
-def _decodeBigEndian(b):
-    # TODO(davidben): Replace with int.from_bytes when removing Python 2.
-    return sum([six.indexbytes(b, len(b) - i - 1) << 8 * i
-                for i in range(len(b))])
-
-
-def _encodeBigEndian(n):
-    b = bytearray()
-    while n != 0:
-        b.append(n & 0xff)
-        n >>= 8
-
-    if len(b) == 0:
-        b.append(0)
-    b.reverse()
-
-    return bytes(b)
-
-
-def _zeroPad(b, length):
-    if len(b) < length:
-        return (b"\x00" * (length - len(b))) + b
-    return b
-
-
-def _encodePoint(point):
-    x = point[0]
-    y = point[1]
-    if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
-        raise "point not on curve"
-    return b"\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad(
-        _encodeBigEndian(point[1]), 32)
-
-
-def _decodePoint(b):
-    if len(b) != 1 + 32 + 32 or six.indexbytes(b, 0) != 4:
-        raise "invalid encoded ec point"
-    x = _decodeBigEndian(b[1:33])
-    y = _decodeBigEndian(b[33:65])
-    if (y * y) % p != (x * x * x - 3 * x + p256B) % p:
-        raise "point not on curve"
-    return (x, y)
-
-
-def generatePublicPrivate():
-    """generatePublicPrivate returns a tuple of (X9.62 encoded public point,
-    private value), where the private value is generated from os.urandom."""
-    private = _decodeBigEndian(os.urandom(40)) % order
-    return _encodePoint(_scalarBaseMult(private)), private
-
-
-def generateSharedValue(theirPublic, private):
-    """generateSharedValue returns the encoded x-coordinate of the
-    multiplication of a peer's X9.62 encoded point and a private value."""
-    return _zeroPad(
-        _encodeBigEndian(_scalarMult(private, _decodePoint(theirPublic))[0]),
-        32)
-
-if __name__ == "__main__":
-    alice, alicePrivate = generatePublicPrivate()
-    bob, bobPrivate = generatePublicPrivate()
-
-    if generateSharedValue(alice, bobPrivate) != generateSharedValue(
-        bob, alicePrivate):
-        raise "simple DH test failed"
-
-    (x, _) = _scalarBaseMult(1)
-
-    for i in range(1000):
-        (x, _) = _scalarBaseMult(x)
-
-    if x != 2428281965257598569040586318034812501729437946720808289049534492833635302706:
-        raise "loop test failed"
diff --git a/third_party/tlslite/tlslite/utils/pem.py b/third_party/tlslite/tlslite/utils/pem.py
deleted file mode 100644
index 04b5d0b..0000000
--- a/third_party/tlslite/tlslite/utils/pem.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-from .compat import *
-import binascii
-
-#This code is shared with tackpy (somewhat), so I'd rather make minimal
-#changes, and preserve the use of a2b_base64 throughout.
-
-def dePem(s, name):
-    """Decode a PEM string into a bytearray of its payload.
-    
-    The input must contain an appropriate PEM prefix and postfix
-    based on the input name string, e.g. for name="CERTIFICATE":
-
-    -----BEGIN CERTIFICATE-----
-    MIIBXDCCAUSgAwIBAgIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDEwRUQUNL
-...
-    KoZIhvcNAQEFBQADAwA5kw==
-    -----END CERTIFICATE-----    
-
-    The first such PEM block in the input will be found, and its
-    payload will be base64 decoded and returned.
-    """
-    prefix  = "-----BEGIN %s-----" % name
-    postfix = "-----END %s-----" % name    
-    start = s.find(prefix)
-    if start == -1:
-        raise SyntaxError("Missing PEM prefix")
-    end = s.find(postfix, start+len(prefix))
-    if end == -1:
-        raise SyntaxError("Missing PEM postfix")
-    s = s[start+len("-----BEGIN %s-----" % name) : end]
-    retBytes = a2b_base64(s) # May raise SyntaxError
-    return retBytes
-    
-def dePemList(s, name):
-    """Decode a sequence of PEM blocks into a list of bytearrays.
-
-    The input must contain any number of PEM blocks, each with the appropriate
-    PEM prefix and postfix based on the input name string, e.g. for
-    name="TACK BREAK SIG".  Arbitrary text can appear between and before and
-    after the PEM blocks.  For example:
-
-    " Created by TACK.py 0.9.3 Created at 2012-02-01T00:30:10Z -----BEGIN TACK
-    BREAK SIG-----
-    ATKhrz5C6JHJW8BF5fLVrnQss6JnWVyEaC0p89LNhKPswvcC9/s6+vWLd9snYTUv
-    YMEBdw69PUP8JB4AdqA3K6Ap0Fgd9SSTOECeAKOUAym8zcYaXUwpk0+WuPYa7Zmm
-    SkbOlK4ywqt+amhWbg9txSGUwFO5tWUHT3QrnRlE/e3PeNFXLx5Bckg= -----END TACK
-    BREAK SIG----- Created by TACK.py 0.9.3 Created at 2012-02-01T00:30:11Z
-    -----BEGIN TACK BREAK SIG-----
-    ATKhrz5C6JHJW8BF5fLVrnQss6JnWVyEaC0p89LNhKPswvcC9/s6+vWLd9snYTUv
-    YMEBdw69PUP8JB4AdqA3K6BVCWfcjN36lx6JwxmZQncS6sww7DecFO/qjSePCxwM
-    +kdDqX/9/183nmjx6bf0ewhPXkA0nVXsDYZaydN8rJU1GaMlnjcIYxY= -----END TACK
-    BREAK SIG----- "
-    
-    All such PEM blocks will be found, decoded, and return in an ordered list
-    of bytearrays, which may have zero elements if not PEM blocks are found.
-     """
-    bList = []
-    prefix  = "-----BEGIN %s-----" % name
-    postfix = "-----END %s-----" % name
-    while 1:
-        start = s.find(prefix)
-        if start == -1:
-            return bList
-        end = s.find(postfix, start+len(prefix))
-        if end == -1:
-            raise SyntaxError("Missing PEM postfix")
-        s2 = s[start+len(prefix) : end]
-        retBytes = a2b_base64(s2) # May raise SyntaxError
-        bList.append(retBytes)
-        s = s[end+len(postfix) : ]
-
-def pem(b, name):
-    """Encode a payload bytearray into a PEM string.
-    
-    The input will be base64 encoded, then wrapped in a PEM prefix/postfix
-    based on the name string, e.g. for name="CERTIFICATE":
-    
-    -----BEGIN CERTIFICATE-----
-    MIIBXDCCAUSgAwIBAgIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDEwRUQUNL
-...
-    KoZIhvcNAQEFBQADAwA5kw==
-    -----END CERTIFICATE-----    
-    """
-    s1 = b2a_base64(b)[:-1] # remove terminating \n
-    s2 = ""
-    while s1:
-        s2 += s1[:64] + "\n"
-        s1 = s1[64:]
-    s = ("-----BEGIN %s-----\n" % name) + s2 + \
-        ("-----END %s-----\n" % name)     
-    return s
-
-def pemSniff(inStr, name):
-    searchStr = "-----BEGIN %s-----" % name
-    return searchStr in inStr
diff --git a/third_party/tlslite/tlslite/utils/pycrypto_aes.py b/third_party/tlslite/tlslite/utils/pycrypto_aes.py
deleted file mode 100644
index b3425c0..0000000
--- a/third_party/tlslite/tlslite/utils/pycrypto_aes.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""PyCrypto AES implementation."""
-
-from .cryptomath import *
-from .aes import *
-
-if pycryptoLoaded:
-    import Crypto.Cipher.AES
-
-    def new(key, mode, IV):
-        return PyCrypto_AES(key, mode, IV)
-
-    class PyCrypto_AES(AES):
-
-        def __init__(self, key, mode, IV):
-            AES.__init__(self, key, mode, IV, "pycrypto")
-            key = bytes(key)
-            IV = bytes(IV)
-            self.context = Crypto.Cipher.AES.new(key, mode, IV)
-
-        def encrypt(self, plaintext):
-            plaintext = bytes(plaintext)
-            return bytearray(self.context.encrypt(plaintext))
-
-        def decrypt(self, ciphertext):
-            ciphertext = bytes(ciphertext)
-            return bytearray(self.context.decrypt(ciphertext))
diff --git a/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py b/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
deleted file mode 100644
index ee187eea..0000000
--- a/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Author: Google
-# See the LICENSE file for legal information regarding use of this file.
-
-"""PyCrypto AES-GCM implementation."""
-
-from .cryptomath import *
-from .aesgcm import AESGCM
-
-if pycryptoLoaded:
-    import Crypto.Cipher.AES
-
-    def new(key):
-        cipher = Crypto.Cipher.AES.new(bytes(key))
-        def encrypt(plaintext):
-            return bytearray(cipher.encrypt(bytes(plaintext)))
-        return AESGCM(key, "pycrypto", encrypt)
diff --git a/third_party/tlslite/tlslite/utils/pycrypto_rc4.py b/third_party/tlslite/tlslite/utils/pycrypto_rc4.py
deleted file mode 100644
index fc98d7c..0000000
--- a/third_party/tlslite/tlslite/utils/pycrypto_rc4.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""PyCrypto RC4 implementation."""
-
-from .cryptomath import *
-from .rc4 import *
-
-if pycryptoLoaded:
-    import Crypto.Cipher.ARC4
-
-    def new(key):
-        return PyCrypto_RC4(key)
-
-    class PyCrypto_RC4(RC4):
-
-        def __init__(self, key):
-            RC4.__init__(self, key, "pycrypto")
-            key = bytes(key)
-            self.context = Crypto.Cipher.ARC4.new(key)
-
-        def encrypt(self, plaintext):
-            plaintext = bytes(plaintext)
-            return bytearray(self.context.encrypt(plaintext))
-
-        def decrypt(self, ciphertext):
-            ciphertext = bytes(ciphertext)
-            return bytearray(self.context.decrypt(ciphertext))
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py b/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py
deleted file mode 100644
index 4537856..0000000
--- a/third_party/tlslite/tlslite/utils/pycrypto_rsakey.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""PyCrypto RSA implementation."""
-
-from .cryptomath import *
-
-from .rsakey import *
-from .python_rsakey import Python_RSAKey
-
-if pycryptoLoaded:
-
-    from Crypto.PublicKey import RSA
-
-    class PyCrypto_RSAKey(RSAKey):
-        def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
-            if not d:
-                self.rsa = RSA.construct( (n, e) )
-            else:
-                self.rsa = RSA.construct( (n, e, d, p, q) )
-
-        def __getattr__(self, name):
-            return getattr(self.rsa, name)
-
-        def hasPrivateKey(self):
-            return self.rsa.has_private()
-
-        def _rawPrivateKeyOp(self, m):
-            c = self.rsa.decrypt((m,))
-            return c
-
-        def _rawPublicKeyOp(self, c):
-            m = self.rsa.encrypt(c, None)[0]
-            return m
-
-        def generate(bits):
-            key = PyCrypto_RSAKey()
-            def f(numBytes):
-                return bytes(getRandomBytes(numBytes))
-            key.rsa = RSA.generate(bits, f)
-            return key
-        generate = staticmethod(generate)
diff --git a/third_party/tlslite/tlslite/utils/pycrypto_tripledes.py b/third_party/tlslite/tlslite/utils/pycrypto_tripledes.py
deleted file mode 100644
index 8117f34..0000000
--- a/third_party/tlslite/tlslite/utils/pycrypto_tripledes.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""PyCrypto 3DES implementation."""
-
-from .cryptomath import *
-from .tripledes import *
-
-if pycryptoLoaded:
-    import Crypto.Cipher.DES3
-
-    def new(key, mode, IV):
-        return PyCrypto_TripleDES(key, mode, IV)
-
-    class PyCrypto_TripleDES(TripleDES):
-
-        def __init__(self, key, mode, IV):
-            TripleDES.__init__(self, key, mode, IV, "pycrypto")
-            key = bytes(key)
-            IV = bytes(IV)
-            self.context = Crypto.Cipher.DES3.new(key, mode, IV)
-
-        def encrypt(self, plaintext):
-            plaintext = bytes(plaintext)
-            return bytearray(self.context.encrypt(plaintext))
-
-        def decrypt(self, ciphertext):
-            ciphertext = bytes(ciphertext)
-            return bytearray(self.context.decrypt(ciphertext))
\ No newline at end of file
diff --git a/third_party/tlslite/tlslite/utils/python_aes.py b/third_party/tlslite/tlslite/utils/python_aes.py
deleted file mode 100644
index cb8f87e..0000000
--- a/third_party/tlslite/tlslite/utils/python_aes.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Pure-Python AES implementation."""
-
-from .cryptomath import *
-
-from .aes import *
-from .rijndael import rijndael
-
-def new(key, mode, IV):
-    return Python_AES(key, mode, IV)
-
-class Python_AES(AES):
-    def __init__(self, key, mode, IV):
-        AES.__init__(self, key, mode, IV, "python")
-        self.rijndael = rijndael(key, 16)
-        self.IV = IV
-
-    def encrypt(self, plaintext):
-        AES.encrypt(self, plaintext)
-
-        plaintextBytes = plaintext[:]
-        chainBytes = self.IV[:]
-
-        #CBC Mode: For each block...
-        for x in range(len(plaintextBytes)//16):
-
-            #XOR with the chaining block
-            blockBytes = plaintextBytes[x*16 : (x*16)+16]
-            for y in range(16):
-                blockBytes[y] ^= chainBytes[y]
-
-            #Encrypt it
-            encryptedBytes = self.rijndael.encrypt(blockBytes)
-
-            #Overwrite the input with the output
-            for y in range(16):
-                plaintextBytes[(x*16)+y] = encryptedBytes[y]
-
-            #Set the next chaining block
-            chainBytes = encryptedBytes
-
-        self.IV = chainBytes[:]
-        return plaintextBytes
-
-    def decrypt(self, ciphertext):
-        AES.decrypt(self, ciphertext)
-
-        ciphertextBytes = ciphertext[:]
-        chainBytes = self.IV[:]
-
-        #CBC Mode: For each block...
-        for x in range(len(ciphertextBytes)//16):
-
-            #Decrypt it
-            blockBytes = ciphertextBytes[x*16 : (x*16)+16]
-            decryptedBytes = self.rijndael.decrypt(blockBytes)
-
-            #XOR with the chaining block and overwrite the input with output
-            for y in range(16):
-                decryptedBytes[y] ^= chainBytes[y]
-                ciphertextBytes[(x*16)+y] = decryptedBytes[y]
-
-            #Set the next chaining block
-            chainBytes = blockBytes
-
-        self.IV = chainBytes[:]
-        return ciphertextBytes
diff --git a/third_party/tlslite/tlslite/utils/python_aesgcm.py b/third_party/tlslite/tlslite/utils/python_aesgcm.py
deleted file mode 100644
index 80a5fd5..0000000
--- a/third_party/tlslite/tlslite/utils/python_aesgcm.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Author: Google
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Pure-Python AES-GCM implementation."""
-
-from .aesgcm import AESGCM
-from .rijndael import rijndael
-
-def new(key):
-    return AESGCM(key, "python", rijndael(key, 16).encrypt)
diff --git a/third_party/tlslite/tlslite/utils/python_rc4.py b/third_party/tlslite/tlslite/utils/python_rc4.py
deleted file mode 100644
index 15d9fd491..0000000
--- a/third_party/tlslite/tlslite/utils/python_rc4.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Pure-Python RC4 implementation."""
-
-from .rc4 import RC4
-from .cryptomath import *
-
-def new(key):
-    return Python_RC4(key)
-
-class Python_RC4(RC4):
-    def __init__(self, keyBytes):
-        RC4.__init__(self, keyBytes, "python")
-        S = [i for i in range(256)]
-        j = 0
-        for i in range(256):
-            j = (j + S[i] + keyBytes[i % len(keyBytes)]) % 256
-            S[i], S[j] = S[j], S[i]
-
-        self.S = S
-        self.i = 0
-        self.j = 0
-
-    def encrypt(self, plaintextBytes):
-        ciphertextBytes = plaintextBytes[:]
-        S = self.S
-        i = self.i
-        j = self.j
-        for x in range(len(ciphertextBytes)):
-            i = (i + 1) % 256
-            j = (j + S[i]) % 256
-            S[i], S[j] = S[j], S[i]
-            t = (S[i] + S[j]) % 256
-            ciphertextBytes[x] ^= S[t]
-        self.i = i
-        self.j = j
-        return ciphertextBytes
-
-    def decrypt(self, ciphertext):
-        return self.encrypt(ciphertext)
diff --git a/third_party/tlslite/tlslite/utils/python_rsakey.py b/third_party/tlslite/tlslite/utils/python_rsakey.py
deleted file mode 100644
index a62fc68..0000000
--- a/third_party/tlslite/tlslite/utils/python_rsakey.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Pure-Python RSA implementation."""
-import threading
-from .cryptomath import *
-from .asn1parser import ASN1Parser
-from .rsakey import *
-from .pem import *
-
-class Python_RSAKey(RSAKey):
-    def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
-        if (n and not e) or (e and not n):
-            raise AssertionError()
-        self.n = n
-        self.e = e
-        self.d = d
-        self.p = p
-        self.q = q
-        self.dP = dP
-        self.dQ = dQ
-        self.qInv = qInv
-        self.blinder = 0
-        self.unblinder = 0
-        self._lock = threading.Lock()
-
-    def hasPrivateKey(self):
-        return self.d != 0
-
-    def _rawPrivateKeyOp(self, message):
-        with self._lock:
-            # Create blinding values, on the first pass:
-            if not self.blinder:
-                self.unblinder = getRandomNumber(2, self.n)
-                self.blinder = powMod(invMod(self.unblinder, self.n), self.e,
-                                      self.n)
-            unblinder = self.unblinder
-            blinder = self.blinder
-
-            # Update blinding values
-            self.blinder = (self.blinder * self.blinder) % self.n
-            self.unblinder = (self.unblinder * self.unblinder) % self.n
-
-        # Blind the input
-        message = (message * blinder) % self.n
-
-        # Perform the RSA operation
-        cipher = self._rawPrivateKeyOpHelper(message)
-
-        # Unblind the output
-        cipher = (cipher * unblinder) % self.n
-
-        # Return the output
-        return cipher
-
-    def _rawPrivateKeyOpHelper(self, m):
-        #Non-CRT version
-        #c = powMod(m, self.d, self.n)
-
-        #CRT version  (~3x faster)
-        s1 = powMod(m, self.dP, self.p)
-        s2 = powMod(m, self.dQ, self.q)
-        h = ((s1 - s2) * self.qInv) % self.p
-        c = s2 + self.q * h
-        return c
-
-    def _rawPublicKeyOp(self, c):
-        m = powMod(c, self.e, self.n)
-        return m
-
-    def acceptsPassword(self): return False
-
-    def generate(bits):
-        key = Python_RSAKey()
-        p = getRandomPrime(bits//2, False)
-        q = getRandomPrime(bits//2, False)
-        t = lcm(p-1, q-1)
-        key.n = p * q
-        key.e = 65537
-        key.d = invMod(key.e, t)
-        key.p = p
-        key.q = q
-        key.dP = key.d % (p-1)
-        key.dQ = key.d % (q-1)
-        key.qInv = invMod(q, p)
-        return key
-    generate = staticmethod(generate)
-
-    def parsePEM(s, passwordCallback=None):
-        """Parse a string containing a PEM-encoded <privateKey>."""
-
-        if pemSniff(s, "PRIVATE KEY"):
-            bytes = dePem(s, "PRIVATE KEY")
-            return Python_RSAKey._parsePKCS8(bytes)
-        elif pemSniff(s, "RSA PRIVATE KEY"):
-            bytes = dePem(s, "RSA PRIVATE KEY")
-            return Python_RSAKey._parseSSLeay(bytes)
-        else:
-            raise SyntaxError("Not a PEM private key file")
-    parsePEM = staticmethod(parsePEM)
-
-    def _parsePKCS8(bytes):
-        p = ASN1Parser(bytes)
-
-        version = p.getChild(0).value[0]
-        if version != 0:
-            raise SyntaxError("Unrecognized PKCS8 version")
-
-        rsaOID = p.getChild(1).value
-        if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
-            raise SyntaxError("Unrecognized AlgorithmIdentifier")
-
-        #Get the privateKey
-        privateKeyP = p.getChild(2)
-
-        #Adjust for OCTET STRING encapsulation
-        privateKeyP = ASN1Parser(privateKeyP.value)
-
-        return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
-    _parsePKCS8 = staticmethod(_parsePKCS8)
-
-    def _parseSSLeay(bytes):
-        privateKeyP = ASN1Parser(bytes)
-        return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
-    _parseSSLeay = staticmethod(_parseSSLeay)
-
-    def _parseASN1PrivateKey(privateKeyP):
-        version = privateKeyP.getChild(0).value[0]
-        if version != 0:
-            raise SyntaxError("Unrecognized RSAPrivateKey version")
-        n = bytesToNumber(privateKeyP.getChild(1).value)
-        e = bytesToNumber(privateKeyP.getChild(2).value)
-        d = bytesToNumber(privateKeyP.getChild(3).value)
-        p = bytesToNumber(privateKeyP.getChild(4).value)
-        q = bytesToNumber(privateKeyP.getChild(5).value)
-        dP = bytesToNumber(privateKeyP.getChild(6).value)
-        dQ = bytesToNumber(privateKeyP.getChild(7).value)
-        qInv = bytesToNumber(privateKeyP.getChild(8).value)
-        return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
-    _parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey)
diff --git a/third_party/tlslite/tlslite/utils/rc4.py b/third_party/tlslite/tlslite/utils/rc4.py
deleted file mode 100644
index 3853f5b..0000000
--- a/third_party/tlslite/tlslite/utils/rc4.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Abstract class for RC4."""
-
-
-class RC4(object):
-    def __init__(self, keyBytes, implementation):
-        if len(keyBytes) < 16 or len(keyBytes) > 256:
-            raise ValueError()
-        self.isBlockCipher = False
-        self.isAEAD = False
-        self.name = "rc4"
-        self.implementation = implementation
-
-    def encrypt(self, plaintext):
-        raise NotImplementedError()
-
-    def decrypt(self, ciphertext):
-        raise NotImplementedError()
diff --git a/third_party/tlslite/tlslite/utils/rijndael.py b/third_party/tlslite/tlslite/utils/rijndael.py
deleted file mode 100644
index a1d720a2..0000000
--- a/third_party/tlslite/tlslite/utils/rijndael.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# Authors:
-#   Bram Cohen
-#   Trevor Perrin - various changes
-#
-# See the LICENSE file for legal information regarding use of this file.
-# Also see Bram Cohen's statement below
-
-"""
-A pure python (slow) implementation of rijndael with a decent interface
-
-To include -
-
-from rijndael import rijndael
-
-To do a key setup -
-
-r = rijndael(key, block_size = 16)
-
-key must be a string of length 16, 24, or 32
-blocksize must be 16, 24, or 32. Default is 16
-
-To use -
-
-ciphertext = r.encrypt(plaintext)
-plaintext = r.decrypt(ciphertext)
-
-If any strings are of the wrong length a ValueError is thrown
-"""
-
-# ported from the Java reference code by Bram Cohen, bram@gawth.com, April 2001
-# this code is public domain, unless someone makes
-# an intellectual property claim against the reference
-# code, in which case it can be made public domain by
-# deleting all the comments and renaming all the variables
-
-import copy
-import string
-
-shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
-          [[0, 0], [1, 5], [2, 4], [3, 3]],
-          [[0, 0], [1, 7], [3, 5], [4, 4]]]
-
-# [keysize][block_size]
-num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
-
-A = [[1, 1, 1, 1, 1, 0, 0, 0],
-     [0, 1, 1, 1, 1, 1, 0, 0],
-     [0, 0, 1, 1, 1, 1, 1, 0],
-     [0, 0, 0, 1, 1, 1, 1, 1],
-     [1, 0, 0, 0, 1, 1, 1, 1],
-     [1, 1, 0, 0, 0, 1, 1, 1],
-     [1, 1, 1, 0, 0, 0, 1, 1],
-     [1, 1, 1, 1, 0, 0, 0, 1]]
-
-# produce log and alog tables, needed for multiplying in the
-# field GF(2^m) (generator = 3)
-alog = [1]
-for i in range(255):
-    j = (alog[-1] << 1) ^ alog[-1]
-    if j & 0x100 != 0:
-        j ^= 0x11B
-    alog.append(j)
-
-log = [0] * 256
-for i in range(1, 255):
-    log[alog[i]] = i
-
-# multiply two elements of GF(2^m)
-def mul(a, b):
-    if a == 0 or b == 0:
-        return 0
-    return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
-
-# substitution box based on F^{-1}(x)
-box = [[0] * 8 for i in range(256)]
-box[1][7] = 1
-for i in range(2, 256):
-    j = alog[255 - log[i]]
-    for t in range(8):
-        box[i][t] = (j >> (7 - t)) & 0x01
-
-B = [0, 1, 1, 0, 0, 0, 1, 1]
-
-# affine transform:  box[i] <- B + A*box[i]
-cox = [[0] * 8 for i in range(256)]
-for i in range(256):
-    for t in range(8):
-        cox[i][t] = B[t]
-        for j in range(8):
-            cox[i][t] ^= A[t][j] * box[i][j]
-
-# S-boxes and inverse S-boxes
-S =  [0] * 256
-Si = [0] * 256
-for i in range(256):
-    S[i] = cox[i][0] << 7
-    for t in range(1, 8):
-        S[i] ^= cox[i][t] << (7-t)
-    Si[S[i] & 0xFF] = i
-
-# T-boxes
-G = [[2, 1, 1, 3],
-    [3, 2, 1, 1],
-    [1, 3, 2, 1],
-    [1, 1, 3, 2]]
-
-AA = [[0] * 8 for i in range(4)]
-
-for i in range(4):
-    for j in range(4):
-        AA[i][j] = G[i][j]
-        AA[i][i+4] = 1
-
-for i in range(4):
-    pivot = AA[i][i]
-    if pivot == 0:
-        t = i + 1
-        while AA[t][i] == 0 and t < 4:
-            t += 1
-            assert t != 4, 'G matrix must be invertible'
-            for j in range(8):
-                AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
-            pivot = AA[i][i]
-    for j in range(8):
-        if AA[i][j] != 0:
-            AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
-    for t in range(4):
-        if i != t:
-            for j in range(i+1, 8):
-                AA[t][j] ^= mul(AA[i][j], AA[t][i])
-            AA[t][i] = 0
-
-iG = [[0] * 4 for i in range(4)]
-
-for i in range(4):
-    for j in range(4):
-        iG[i][j] = AA[i][j + 4]
-
-def mul4(a, bs):
-    if a == 0:
-        return 0
-    r = 0
-    for b in bs:
-        r <<= 8
-        if b != 0:
-            r = r | mul(a, b)
-    return r
-
-T1 = []
-T2 = []
-T3 = []
-T4 = []
-T5 = []
-T6 = []
-T7 = []
-T8 = []
-U1 = []
-U2 = []
-U3 = []
-U4 = []
-
-for t in range(256):
-    s = S[t]
-    T1.append(mul4(s, G[0]))
-    T2.append(mul4(s, G[1]))
-    T3.append(mul4(s, G[2]))
-    T4.append(mul4(s, G[3]))
-
-    s = Si[t]
-    T5.append(mul4(s, iG[0]))
-    T6.append(mul4(s, iG[1]))
-    T7.append(mul4(s, iG[2]))
-    T8.append(mul4(s, iG[3]))
-
-    U1.append(mul4(t, iG[0]))
-    U2.append(mul4(t, iG[1]))
-    U3.append(mul4(t, iG[2]))
-    U4.append(mul4(t, iG[3]))
-
-# round constants
-rcon = [1]
-r = 1
-for t in range(1, 30):
-    r = mul(2, r)
-    rcon.append(r)
-
-del A
-del AA
-del pivot
-del B
-del G
-del box
-del log
-del alog
-del i
-del j
-del r
-del s
-del t
-del mul
-del mul4
-del cox
-del iG
-
-class rijndael:
-    def __init__(self, key, block_size = 16):
-        if block_size != 16 and block_size != 24 and block_size != 32:
-            raise ValueError('Invalid block size: ' + str(block_size))
-        if len(key) != 16 and len(key) != 24 and len(key) != 32:
-            raise ValueError('Invalid key size: ' + str(len(key)))
-        self.block_size = block_size
-
-        ROUNDS = num_rounds[len(key)][block_size]
-        BC = block_size // 4
-        # encryption round keys
-        Ke = [[0] * BC for i in range(ROUNDS + 1)]
-        # decryption round keys
-        Kd = [[0] * BC for i in range(ROUNDS + 1)]
-        ROUND_KEY_COUNT = (ROUNDS + 1) * BC
-        KC = len(key) // 4
-
-        # copy user material bytes into temporary ints
-        tk = []
-        for i in range(0, KC):
-            tk.append((key[i * 4] << 24) | (key[i * 4 + 1] << 16) |
-                (key[i * 4 + 2] << 8) | key[i * 4 + 3])
-
-        # copy values into round key arrays
-        t = 0
-        j = 0
-        while j < KC and t < ROUND_KEY_COUNT:
-            Ke[t // BC][t % BC] = tk[j]
-            Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
-            j += 1
-            t += 1
-        tt = 0
-        rconpointer = 0
-        while t < ROUND_KEY_COUNT:
-            # extrapolate using phi (the round key evolution function)
-            tt = tk[KC - 1]
-            tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^  \
-                     (S[(tt >>  8) & 0xFF] & 0xFF) << 16 ^  \
-                     (S[ tt        & 0xFF] & 0xFF) <<  8 ^  \
-                     (S[(tt >> 24) & 0xFF] & 0xFF)       ^  \
-                     (rcon[rconpointer]    & 0xFF) << 24
-            rconpointer += 1
-            if KC != 8:
-                for i in range(1, KC):
-                    tk[i] ^= tk[i-1]
-            else:
-                for i in range(1, KC // 2):
-                    tk[i] ^= tk[i-1]
-                tt = tk[KC // 2 - 1]
-                tk[KC // 2] ^= (S[ tt        & 0xFF] & 0xFF)       ^ \
-                              (S[(tt >>  8) & 0xFF] & 0xFF) <<  8 ^ \
-                              (S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
-                              (S[(tt >> 24) & 0xFF] & 0xFF) << 24
-                for i in range(KC // 2 + 1, KC):
-                    tk[i] ^= tk[i-1]
-            # copy values into round key arrays
-            j = 0
-            while j < KC and t < ROUND_KEY_COUNT:
-                Ke[t // BC][t % BC] = tk[j]
-                Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
-                j += 1
-                t += 1
-        # inverse MixColumn where needed
-        for r in range(1, ROUNDS):
-            for j in range(BC):
-                tt = Kd[r][j]
-                Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \
-                           U2[(tt >> 16) & 0xFF] ^ \
-                           U3[(tt >>  8) & 0xFF] ^ \
-                           U4[ tt        & 0xFF]
-        self.Ke = Ke
-        self.Kd = Kd
-
-    def encrypt(self, plaintext):
-        if len(plaintext) != self.block_size:
-            raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
-        Ke = self.Ke
-
-        BC = self.block_size // 4
-        ROUNDS = len(Ke) - 1
-        if BC == 4:
-            SC = 0
-        elif BC == 6:
-            SC = 1
-        else:
-            SC = 2
-        s1 = shifts[SC][1][0]
-        s2 = shifts[SC][2][0]
-        s3 = shifts[SC][3][0]
-        a = [0] * BC
-        # temporary work array
-        t = []
-        # plaintext to ints + key
-        for i in range(BC):
-            t.append((plaintext[i * 4    ] << 24 |
-                      plaintext[i * 4 + 1] << 16 |
-                      plaintext[i * 4 + 2] <<  8 |
-                      plaintext[i * 4 + 3]        ) ^ Ke[0][i])
-        # apply round transforms
-        for r in range(1, ROUNDS):
-            for i in range(BC):
-                a[i] = (T1[(t[ i           ] >> 24) & 0xFF] ^
-                        T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
-                        T3[(t[(i + s2) % BC] >>  8) & 0xFF] ^
-                        T4[ t[(i + s3) % BC]        & 0xFF]  ) ^ Ke[r][i]
-            t = copy.copy(a)
-        # last round is special
-        result = []
-        for i in range(BC):
-            tt = Ke[ROUNDS][i]
-            result.append((S[(t[ i           ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
-            result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
-            result.append((S[(t[(i + s2) % BC] >>  8) & 0xFF] ^ (tt >>  8)) & 0xFF)
-            result.append((S[ t[(i + s3) % BC]        & 0xFF] ^  tt       ) & 0xFF)
-        return bytearray(result)
-
-    def decrypt(self, ciphertext):
-        if len(ciphertext) != self.block_size:
-            raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
-        Kd = self.Kd
-
-        BC = self.block_size // 4
-        ROUNDS = len(Kd) - 1
-        if BC == 4:
-            SC = 0
-        elif BC == 6:
-            SC = 1
-        else:
-            SC = 2
-        s1 = shifts[SC][1][1]
-        s2 = shifts[SC][2][1]
-        s3 = shifts[SC][3][1]
-        a = [0] * BC
-        # temporary work array
-        t = [0] * BC
-        # ciphertext to ints + key
-        for i in range(BC):
-            t[i] = (ciphertext[i * 4    ] << 24 |
-                    ciphertext[i * 4 + 1] << 16 |
-                    ciphertext[i * 4 + 2] <<  8 |
-                    ciphertext[i * 4 + 3]        ) ^ Kd[0][i]
-        # apply round transforms
-        for r in range(1, ROUNDS):
-            for i in range(BC):
-                a[i] = (T5[(t[ i           ] >> 24) & 0xFF] ^
-                        T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
-                        T7[(t[(i + s2) % BC] >>  8) & 0xFF] ^
-                        T8[ t[(i + s3) % BC]        & 0xFF]  ) ^ Kd[r][i]
-            t = copy.copy(a)
-        # last round is special
-        result = []
-        for i in range(BC):
-            tt = Kd[ROUNDS][i]
-            result.append((Si[(t[ i           ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
-            result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
-            result.append((Si[(t[(i + s2) % BC] >>  8) & 0xFF] ^ (tt >>  8)) & 0xFF)
-            result.append((Si[ t[(i + s3) % BC]        & 0xFF] ^  tt       ) & 0xFF)
-        return bytearray(result)
-
-def encrypt(key, block):
-    return rijndael(key, len(block)).encrypt(block)
-
-def decrypt(key, block):
-    return rijndael(key, len(block)).decrypt(block)
-
-def test():
-    def t(kl, bl):
-        b = 'b' * bl
-        r = rijndael('a' * kl, bl)
-        assert r.decrypt(r.encrypt(b)) == b
-    t(16, 16)
-    t(16, 24)
-    t(16, 32)
-    t(24, 16)
-    t(24, 24)
-    t(24, 32)
-    t(32, 16)
-    t(32, 24)
-    t(32, 32)
-
diff --git a/third_party/tlslite/tlslite/utils/rsakey.py b/third_party/tlslite/tlslite/utils/rsakey.py
deleted file mode 100644
index 7e3f9788..0000000
--- a/third_party/tlslite/tlslite/utils/rsakey.py
+++ /dev/null
@@ -1,265 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Abstract class for RSA."""
-
-from .cryptomath import *
-
-
-class RSAKey(object):
-    """This is an abstract base class for RSA keys.
-
-    Particular implementations of RSA keys, such as
-    L{openssl_rsakey.OpenSSL_RSAKey},
-    L{python_rsakey.Python_RSAKey}, and
-    L{pycrypto_rsakey.PyCrypto_RSAKey},
-    inherit from this.
-
-    To create or parse an RSA key, don't use one of these classes
-    directly.  Instead, use the factory functions in
-    L{tlslite.utils.keyfactory}.
-    """
-
-    def __init__(self, n=0, e=0):
-        """Create a new RSA key.
-
-        If n and e are passed in, the new key will be initialized.
-
-        @type n: int
-        @param n: RSA modulus.
-
-        @type e: int
-        @param e: RSA public exponent.
-        """
-        raise NotImplementedError()
-
-    def __len__(self):
-        """Return the length of this key in bits.
-
-        @rtype: int
-        """
-        return numBits(self.n)
-
-    def hasPrivateKey(self):
-        """Return whether or not this key has a private component.
-
-        @rtype: bool
-        """
-        raise NotImplementedError()
-
-    def hashAndSign(self, bytes):
-        """Hash and sign the passed-in bytes.
-
-        This requires the key to have a private component.  It performs
-        a PKCS1-SHA1 signature on the passed-in data.
-
-        @type bytes: str or L{bytearray} of unsigned bytes
-        @param bytes: The value which will be hashed and signed.
-
-        @rtype: L{bytearray} of unsigned bytes.
-        @return: A PKCS1-SHA1 signature on the passed-in data.
-        """
-        hashBytes = SHA1(bytearray(bytes))
-        prefixedHashBytes = self.addPKCS1SHA1Prefix(hashBytes)
-        sigBytes = self.sign(prefixedHashBytes)
-        return sigBytes
-
-    def hashAndVerify(self, sigBytes, bytes):
-        """Hash and verify the passed-in bytes with the signature.
-
-        This verifies a PKCS1-SHA1 signature on the passed-in data.
-
-        @type sigBytes: L{bytearray} of unsigned bytes
-        @param sigBytes: A PKCS1-SHA1 signature.
-
-        @type bytes: str or L{bytearray} of unsigned bytes
-        @param bytes: The value which will be hashed and verified.
-
-        @rtype: bool
-        @return: Whether the signature matches the passed-in data.
-        """
-        hashBytes = SHA1(bytearray(bytes))
-        
-        # Try it with/without the embedded NULL
-        prefixedHashBytes1 = self.addPKCS1SHA1Prefix(hashBytes, False)
-        prefixedHashBytes2 = self.addPKCS1SHA1Prefix(hashBytes, True)
-        result1 = self.verify(sigBytes, prefixedHashBytes1)
-        result2 = self.verify(sigBytes, prefixedHashBytes2)
-        return (result1 or result2)
-
-    def sign(self, bytes):
-        """Sign the passed-in bytes.
-
-        This requires the key to have a private component.  It performs
-        a PKCS1 signature on the passed-in data.
-
-        @type bytes: L{bytearray} of unsigned bytes
-        @param bytes: The value which will be signed.
-
-        @rtype: L{bytearray} of unsigned bytes.
-        @return: A PKCS1 signature on the passed-in data.
-        """
-        if not self.hasPrivateKey():
-            raise AssertionError()
-        paddedBytes = self._addPKCS1Padding(bytes, 1)
-        m = bytesToNumber(paddedBytes)
-        if m >= self.n:
-            raise ValueError()
-        c = self._rawPrivateKeyOp(m)
-        sigBytes = numberToByteArray(c, numBytes(self.n))
-        return sigBytes
-
-    def verify(self, sigBytes, bytes):
-        """Verify the passed-in bytes with the signature.
-
-        This verifies a PKCS1 signature on the passed-in data.
-
-        @type sigBytes: L{bytearray} of unsigned bytes
-        @param sigBytes: A PKCS1 signature.
-
-        @type bytes: L{bytearray} of unsigned bytes
-        @param bytes: The value which will be verified.
-
-        @rtype: bool
-        @return: Whether the signature matches the passed-in data.
-        """
-        if len(sigBytes) != numBytes(self.n):
-            return False
-        paddedBytes = self._addPKCS1Padding(bytes, 1)
-        c = bytesToNumber(sigBytes)
-        if c >= self.n:
-            return False
-        m = self._rawPublicKeyOp(c)
-        checkBytes = numberToByteArray(m, numBytes(self.n))
-        return checkBytes == paddedBytes
-
-    def encrypt(self, bytes):
-        """Encrypt the passed-in bytes.
-
-        This performs PKCS1 encryption of the passed-in data.
-
-        @type bytes: L{bytearray} of unsigned bytes
-        @param bytes: The value which will be encrypted.
-
-        @rtype: L{bytearray} of unsigned bytes.
-        @return: A PKCS1 encryption of the passed-in data.
-        """
-        paddedBytes = self._addPKCS1Padding(bytes, 2)
-        m = bytesToNumber(paddedBytes)
-        if m >= self.n:
-            raise ValueError()
-        c = self._rawPublicKeyOp(m)
-        encBytes = numberToByteArray(c, numBytes(self.n))
-        return encBytes
-
-    def decrypt(self, encBytes):
-        """Decrypt the passed-in bytes.
-
-        This requires the key to have a private component.  It performs
-        PKCS1 decryption of the passed-in data.
-
-        @type encBytes: L{bytearray} of unsigned bytes
-        @param encBytes: The value which will be decrypted.
-
-        @rtype: L{bytearray} of unsigned bytes or None.
-        @return: A PKCS1 decryption of the passed-in data or None if
-        the data is not properly formatted.
-        """
-        if not self.hasPrivateKey():
-            raise AssertionError()
-        if len(encBytes) != numBytes(self.n):
-            return None
-        c = bytesToNumber(encBytes)
-        if c >= self.n:
-            return None
-        m = self._rawPrivateKeyOp(c)
-        decBytes = numberToByteArray(m, numBytes(self.n))
-        #Check first two bytes
-        if decBytes[0] != 0 or decBytes[1] != 2:
-            return None
-        #Scan through for zero separator
-        for x in range(1, len(decBytes)-1):
-            if decBytes[x]== 0:
-                break
-        else:
-            return None
-        return decBytes[x+1:] #Return everything after the separator
-
-    def _rawPrivateKeyOp(self, m):
-        raise NotImplementedError()
-
-    def _rawPublicKeyOp(self, c):
-        raise NotImplementedError()
-
-    def acceptsPassword(self):
-        """Return True if the write() method accepts a password for use
-        in encrypting the private key.
-
-        @rtype: bool
-        """
-        raise NotImplementedError()
-
-    def write(self, password=None):
-        """Return a string containing the key.
-
-        @rtype: str
-        @return: A string describing the key, in whichever format (PEM)
-        is native to the implementation.
-        """
-        raise NotImplementedError()
-
-    def generate(bits):
-        """Generate a new key with the specified bit length.
-
-        @rtype: L{tlslite.utils.RSAKey.RSAKey}
-        """
-        raise NotImplementedError()
-    generate = staticmethod(generate)
-
-
-    # **************************************************************************
-    # Helper Functions for RSA Keys
-    # **************************************************************************
-
-    @staticmethod
-    def addPKCS1SHA1Prefix(bytes, withNULL=True):
-        # There is a long history of confusion over whether the SHA1 
-        # algorithmIdentifier should be encoded with a NULL parameter or 
-        # with the parameter omitted.  While the original intention was 
-        # apparently to omit it, many toolkits went the other way.  TLS 1.2
-        # specifies the NULL should be included, and this behavior is also
-        # mandated in recent versions of PKCS #1, and is what tlslite has
-        # always implemented.  Anyways, verification code should probably 
-        # accept both.
-        if not withNULL:
-            prefixBytes = bytearray(\
-            [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])            
-        else:
-            prefixBytes = bytearray(\
-            [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14])            
-        prefixedBytes = prefixBytes + bytes
-        return prefixedBytes
-
-    @staticmethod
-    def addPKCS1SHA256Prefix(bytes):
-        prefixBytes = bytearray([
-            0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
-            0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20])
-        return prefixBytes + bytes
-
-    def _addPKCS1Padding(self, bytes, blockType):
-        padLength = (numBytes(self.n) - (len(bytes)+3))
-        if blockType == 1: #Signature padding
-            pad = [0xFF] * padLength
-        elif blockType == 2: #Encryption padding
-            pad = bytearray(0)
-            while len(pad) < padLength:
-                padBytes = getRandomBytes(padLength * 2)
-                pad = [b for b in padBytes if b != 0]
-                pad = pad[:padLength]
-        else:
-            raise AssertionError()
-
-        padding = bytearray([0,blockType] + pad + [0])
-        paddedBytes = padding + bytes
-        return paddedBytes
diff --git a/third_party/tlslite/tlslite/utils/tackwrapper.py b/third_party/tlslite/tlslite/utils/tackwrapper.py
deleted file mode 100644
index 4eb39ef..0000000
--- a/third_party/tlslite/tlslite/utils/tackwrapper.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-try:
-    from tack.structures.Tack import Tack
-    from tack.structures.TackExtension import TackExtension
-    from tack.tls.TlsCertificate import TlsCertificate
-    
-    tackpyLoaded = True
-except ImportError:
-    tackpyLoaded = False
diff --git a/third_party/tlslite/tlslite/utils/tripledes.py b/third_party/tlslite/tlslite/utils/tripledes.py
deleted file mode 100644
index ddcdcad3..0000000
--- a/third_party/tlslite/tlslite/utils/tripledes.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Abstract class for 3DES."""
-
-class TripleDES(object):
-    def __init__(self, key, mode, IV, implementation):
-        if len(key) != 24:
-            raise ValueError()
-        if mode != 2:
-            raise ValueError()
-        if len(IV) != 8:
-            raise ValueError()
-        self.isBlockCipher = True
-        self.isAEAD = False
-        self.block_size = 8
-        self.implementation = implementation
-        self.name = "3des"
-
-    #CBC-Mode encryption, returns ciphertext
-    #WARNING: *MAY* modify the input as well
-    def encrypt(self, plaintext):
-        assert(len(plaintext) % 8 == 0)
-
-    #CBC-Mode decryption, returns plaintext
-    #WARNING: *MAY* modify the input as well
-    def decrypt(self, ciphertext):
-        assert(len(ciphertext) % 8 == 0)
diff --git a/third_party/tlslite/tlslite/verifierdb.py b/third_party/tlslite/tlslite/verifierdb.py
deleted file mode 100644
index 4384541..0000000
--- a/third_party/tlslite/tlslite/verifierdb.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class for storing SRP password verifiers."""
-
-from .utils.cryptomath import *
-from .utils.compat import *
-from tlslite import mathtls
-from .basedb import BaseDB
-
-class VerifierDB(BaseDB):
-    """This class represent an in-memory or on-disk database of SRP
-    password verifiers.
-
-    A VerifierDB can be passed to a server handshake to authenticate
-    a client based on one of the verifiers.
-
-    This class is thread-safe.
-    """
-    def __init__(self, filename=None):
-        """Create a new VerifierDB instance.
-
-        @type filename: str
-        @param filename: Filename for an on-disk database, or None for
-        an in-memory database.  If the filename already exists, follow
-        this with a call to open().  To create a new on-disk database,
-        follow this with a call to create().
-        """
-        BaseDB.__init__(self, filename, "verifier")
-
-    def _getItem(self, username, valueStr):
-        (N, g, salt, verifier) = valueStr.split(" ")
-        N = bytesToNumber(a2b_base64(N))
-        g = bytesToNumber(a2b_base64(g))
-        salt = a2b_base64(salt)
-        verifier = bytesToNumber(a2b_base64(verifier))
-        return (N, g, salt, verifier)
-
-    def __setitem__(self, username, verifierEntry):
-        """Add a verifier entry to the database.
-
-        @type username: str
-        @param username: The username to associate the verifier with.
-        Must be less than 256 characters in length.  Must not already
-        be in the database.
-
-        @type verifierEntry: tuple
-        @param verifierEntry: The verifier entry to add.  Use
-        L{tlslite.verifierdb.VerifierDB.makeVerifier} to create a
-        verifier entry.
-        """
-        BaseDB.__setitem__(self, username, verifierEntry)
-
-
-    def _setItem(self, username, value):
-        if len(username)>=256:
-            raise ValueError("username too long")
-        N, g, salt, verifier = value
-        N = b2a_base64(numberToByteArray(N))
-        g = b2a_base64(numberToByteArray(g))
-        salt = b2a_base64(salt)
-        verifier = b2a_base64(numberToByteArray(verifier))
-        valueStr = " ".join( (N, g, salt, verifier)  )
-        return valueStr
-
-    def _checkItem(self, value, username, param):
-        (N, g, salt, verifier) = value
-        x = mathtls.makeX(salt, username, param)
-        v = powMod(g, x, N)
-        return (verifier == v)
-
-
-    def makeVerifier(username, password, bits):
-        """Create a verifier entry which can be stored in a VerifierDB.
-
-        @type username: str
-        @param username: The username for this verifier.  Must be less
-        than 256 characters in length.
-
-        @type password: str
-        @param password: The password for this verifier.
-
-        @type bits: int
-        @param bits: This values specifies which SRP group parameters
-        to use.  It must be one of (1024, 1536, 2048, 3072, 4096, 6144,
-        8192).  Larger values are more secure but slower.  2048 is a
-        good compromise between safety and speed.
-
-        @rtype: tuple
-        @return: A tuple which may be stored in a VerifierDB.
-        """
-        usernameBytes = bytearray(username, "utf-8")
-        passwordBytes = bytearray(password, "utf-8")
-        return mathtls.makeVerifier(usernameBytes, passwordBytes, bits)
-    makeVerifier = staticmethod(makeVerifier)
diff --git a/third_party/tlslite/tlslite/x509.py b/third_party/tlslite/tlslite/x509.py
deleted file mode 100644
index 94dd00d..0000000
--- a/third_party/tlslite/tlslite/x509.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Authors: 
-#   Trevor Perrin
-#   Google - parsing subject field
-#
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class representing an X.509 certificate."""
-
-from .utils.asn1parser import ASN1Parser
-from .utils.cryptomath import *
-from .utils.keyfactory import _createPublicRSAKey
-from .utils.pem import *
-
-
-class X509(object):
-    """This class represents an X.509 certificate.
-
-    @type bytes: L{bytearray} of unsigned bytes
-    @ivar bytes: The DER-encoded ASN.1 certificate
-
-    @type publicKey: L{tlslite.utils.rsakey.RSAKey}
-    @ivar publicKey: The subject public key from the certificate.
-
-    @type subject: L{bytearray} of unsigned bytes
-    @ivar subject: The DER-encoded ASN.1 subject distinguished name.
-    """
-
-    def __init__(self):
-        self.bytes = bytearray(0)
-        self.publicKey = None
-        self.subject = None
-
-    def parse(self, s):
-        """Parse a PEM-encoded X.509 certificate.
-
-        @type s: str
-        @param s: A PEM-encoded X.509 certificate (i.e. a base64-encoded
-        certificate wrapped with "-----BEGIN CERTIFICATE-----" and
-        "-----END CERTIFICATE-----" tags).
-        """
-
-        bytes = dePem(s, "CERTIFICATE")
-        self.parseBinary(bytes)
-        return self
-
-    def parseBinary(self, bytes):
-        """Parse a DER-encoded X.509 certificate.
-
-        @type bytes: str or L{bytearray} of unsigned bytes
-        @param bytes: A DER-encoded X.509 certificate.
-        """
-
-        self.bytes = bytearray(bytes)
-        p = ASN1Parser(bytes)
-
-        #Get the tbsCertificate
-        tbsCertificateP = p.getChild(0)
-
-        #Is the optional version field present?
-        #This determines which index the key is at.
-        if tbsCertificateP.value[0]==0xA0:
-            subjectPublicKeyInfoIndex = 6
-        else:
-            subjectPublicKeyInfoIndex = 5
-
-        #Get the subject
-        self.subject = tbsCertificateP.getChildBytes(\
-                           subjectPublicKeyInfoIndex - 1)
-
-        #Get the subjectPublicKeyInfo
-        subjectPublicKeyInfoP = tbsCertificateP.getChild(\
-                                    subjectPublicKeyInfoIndex)
-
-        #Get the algorithm
-        algorithmP = subjectPublicKeyInfoP.getChild(0)
-        rsaOID = algorithmP.value
-        if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
-            raise SyntaxError("Unrecognized AlgorithmIdentifier")
-
-        #Get the subjectPublicKey
-        subjectPublicKeyP = subjectPublicKeyInfoP.getChild(1)
-
-        #Adjust for BIT STRING encapsulation
-        if (subjectPublicKeyP.value[0] !=0):
-            raise SyntaxError()
-        subjectPublicKeyP = ASN1Parser(subjectPublicKeyP.value[1:])
-
-        #Get the modulus and exponent
-        modulusP = subjectPublicKeyP.getChild(0)
-        publicExponentP = subjectPublicKeyP.getChild(1)
-
-        #Decode them into numbers
-        n = bytesToNumber(modulusP.value)
-        e = bytesToNumber(publicExponentP.value)
-
-        #Create a public key instance
-        self.publicKey = _createPublicRSAKey(n, e)
-
-    def getFingerprint(self):
-        """Get the hex-encoded fingerprint of this certificate.
-
-        @rtype: str
-        @return: A hex-encoded fingerprint.
-        """
-        return b2a_hex(SHA1(self.bytes))
-
-    def writeBytes(self):
-        return self.bytes
-
-
diff --git a/third_party/tlslite/tlslite/x509certchain.py b/third_party/tlslite/tlslite/x509certchain.py
deleted file mode 100644
index 2a592b6..0000000
--- a/third_party/tlslite/tlslite/x509certchain.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Author: Trevor Perrin
-# See the LICENSE file for legal information regarding use of this file.
-
-"""Class representing an X.509 certificate chain."""
-
-from .utils import cryptomath
-from .utils.tackwrapper import *
-from .utils.pem import *
-from .x509 import X509
-
-class X509CertChain(object):
-    """This class represents a chain of X.509 certificates.
-
-    @type x509List: list
-    @ivar x509List: A list of L{tlslite.x509.X509} instances,
-    starting with the end-entity certificate and with every
-    subsequent certificate certifying the previous.
-    """
-
-    def __init__(self, x509List=None):
-        """Create a new X509CertChain.
-
-        @type x509List: list
-        @param x509List: A list of L{tlslite.x509.X509} instances,
-        starting with the end-entity certificate and with every
-        subsequent certificate certifying the previous.
-        """
-        if x509List:
-            self.x509List = x509List
-        else:
-            self.x509List = []
-
-    def parsePemList(self, s):
-        """Parse a string containing a sequence of PEM certs.
-
-        Raise a SyntaxError if input is malformed.
-        """
-        x509List = []
-        bList = dePemList(s, "CERTIFICATE")
-        for b in bList:
-            x509 = X509()
-            x509.parseBinary(b)
-            x509List.append(x509)
-        self.x509List = x509List
-
-    def getNumCerts(self):
-        """Get the number of certificates in this chain.
-
-        @rtype: int
-        """
-        return len(self.x509List)
-
-    def getEndEntityPublicKey(self):
-        """Get the public key from the end-entity certificate.
-
-        @rtype: L{tlslite.utils.rsakey.RSAKey}
-        """
-        if self.getNumCerts() == 0:
-            raise AssertionError()
-        return self.x509List[0].publicKey
-
-    def getFingerprint(self):
-        """Get the hex-encoded fingerprint of the end-entity certificate.
-
-        @rtype: str
-        @return: A hex-encoded fingerprint.
-        """
-        if self.getNumCerts() == 0:
-            raise AssertionError()
-        return self.x509List[0].getFingerprint()
-        
-    def checkTack(self, tack):
-        if self.x509List:
-            tlsCert = TlsCertificate(self.x509List[0].bytes)
-            if tlsCert.matches(tack):
-                return True
-        return False
-        
-    def getTackExt(self):
-        """Get the TACK and/or Break Sigs from a TACK Cert in the chain."""
-        tackExt = None
-        # Search list in backwards order
-        for x509 in self.x509List[::-1]:
-            tlsCert = TlsCertificate(x509.bytes)
-            if tlsCert.tackExt:
-                if tackExt:
-                    raise SyntaxError("Multiple TACK Extensions")
-                else:
-                    tackExt = tlsCert.tackExt
-        return tackExt
-                
diff --git a/third_party/widevine/cdm/widevine_cdm_common.h b/third_party/widevine/cdm/widevine_cdm_common.h
index 415daa7..eacd2dc 100644
--- a/third_party/widevine/cdm/widevine_cdm_common.h
+++ b/third_party/widevine/cdm/widevine_cdm_common.h
@@ -35,7 +35,7 @@
 
 const char kWidevineCdmDisplayName[] = "Widevine Content Decryption Module";
 
-const base::Token kWidevineCdmGuid{0x05d908e5dcca9960ull,
+const base::Token kWidevineCdmType{0x05d908e5dcca9960ull,
                                    0xcd92d30eac98157aull};
 
 // Identifier used by the PluginPrivateFileSystem to identify the files stored
@@ -50,7 +50,7 @@
 const char kMediaFoundationWidevineCdmLibraryName[] = "Google.Widevine.CDM";
 const char kMediaFoundationWidevineCdmDisplayName[] =
     "Google Widevine Windows CDM";
-const base::Token kMediaFoundationWidevineCdmGuid{0x8e73dec793bf5adcull,
+const base::Token kMediaFoundationWidevineCdmType{0x8e73dec793bf5adcull,
                                                   0x27e572c9a1fd930eull};
 #endif  // defined(OS_WIN)
 
diff --git a/tools/OWNERS b/tools/OWNERS
index baffc4e0..c61e844a 100644
--- a/tools/OWNERS
+++ b/tools/OWNERS
@@ -30,7 +30,6 @@
 
 per-file ipc_messages_log.py=yfriedman@chromium.org
 
-per-file nocompile_driver.py=ajwong@chromium.org
 per-file nocompile_driver.py=wychen@chromium.org
 
 per-file roll_webgl_conformance.py=bajones@chromium.org
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py
index bef0318..b71fb52 100755
--- a/tools/checklicenses/checklicenses.py
+++ b/tools/checklicenses/checklicenses.py
@@ -505,9 +505,6 @@
     'third_party/tcmalloc': [
         'UNKNOWN',  # http://crbug.com/98589
     ],
-    'third_party/tlslite': [
-        'UNKNOWN',
-    ],
     # MIT license but some files contain no licensing info. e.g. autogen.sh.
     # Files missing licensing info are not shipped.
     'third_party/wayland': [  #  http://crbug.com/553573
diff --git a/tools/checkperms/checkperms.py b/tools/checkperms/checkperms.py
index 3141417..68f9aea 100755
--- a/tools/checkperms/checkperms.py
+++ b/tools/checkperms/checkperms.py
@@ -185,7 +185,6 @@
   'third_party/protobuf/',
   'third_party/sqlite/',
   'third_party/tcmalloc/',
-  'third_party/tlslite/setup.py',
 )
 
 #### USER EDITABLE SECTION ENDS HERE ####
diff --git a/tools/git/move_source_file.py b/tools/git/move_source_file.py
index 9c03343c..183e78d 100755
--- a/tools/git/move_source_file.py
+++ b/tools/git/move_source_file.py
@@ -80,7 +80,7 @@
   # . Object-C imports
   # . Imports in mojom files.
   files_with_changed_includes = mffr.MultiFileFindReplace(
-      r'(#?(include|import)\s*["<])%s([>"]);?' % re.escape(from_path),
+      r'(#?(include|import)\s*["<])%s([>"])' % re.escape(from_path),
       r'\1%s\3' % to_path, ['*.cc', '*.h', '*.m', '*.mm', '*.cpp', '*.mojom'])
 
 
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 08222ad..14c2fab 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -114,7 +114,7 @@
     'chromium.android.fyi': {
       'Android ASAN (dbg) (reclient)': 'android_clang_asan_debug_bot_reclient',
       'Android arm64 Builder (dbg) (reclient)': 'android_webview_google_debug_static_bot_arm64_reclient',
-      'Android WebView P FYI (rel)': 'android_release_bot_minimal_symbols_arm64_webview_monochrome',
+      'Android WebView P FYI (rel)': 'android_release_bot_minimal_symbols_arm64_webview_monochrome_reclient',
       'android-12-x64-fyi-rel': 'android_release_bot_minimal_symbols_x64_fastbuild_webview_trichrome',
       'android-annotator-rel': 'android_release_bot_minimal_symbols_arm64_webview_google',
       'android-pie-arm64-wpt-rel-non-cq': 'android_release_bot_minimal_symbols_arm64_webview_monochrome',
@@ -302,7 +302,7 @@
       'Mac Builder Next': 'gpu_tests_release_bot_minimal_symbols',
       'Mac deterministic': 'release_bot_mac_strip_minimal_symbols',
       'Mac deterministic (dbg)': 'debug_bot',
-      'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64',
+      'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64_reclient',
       'VR Linux': 'vr_release_bot_reclient',
       'Win 10 Fast Ring': 'release_trybot_minimal_symbols',
       'Win x64 Builder (reclient)': 'gpu_tests_release_bot_minimal_symbols_reclient',
@@ -453,7 +453,7 @@
       'GPU Win x64 Builder': 'gpu_tests_release_bot_dcheck_always_on_resource_allowlisting',
       'GPU Win x64 Builder Code Coverage': 'gpu_tests_release_trybot_resource_allowlisting_code_coverage',
       'GPU Win x64 Builder (dbg)': 'gpu_tests_debug_bot',
-      'Android Release (Nexus 5X)': 'gpu_tests_android_release_bot_dcheck_always_on_arm64_fastbuild',
+      'Android Release (Nexus 5X)': 'gpu_tests_android_release_bot_dcheck_always_on_arm64_fastbuild_reclient',
     },
 
     'chromium.gpu.fyi': {
@@ -555,7 +555,7 @@
     },
 
     'chromium.mojo': {
-      'Mojo Android': 'android_release_bot_minimal_symbols_arm64',
+      'Mojo Android': 'android_release_bot_minimal_symbols_arm64_reclient',
       'Mojo ChromiumOS': 'chromeos_with_codecs_release_trybot',
       'Mojo Linux': 'release_trybot_minimal_symbols_reclient',
       'Mojo Windows': 'release_bot_x86_minimal_symbols',
@@ -1424,8 +1424,8 @@
       'android', 'release_bot', 'minimal_symbols', 'strip_debug_info',
     ],
 
-    'android_release_bot_minimal_symbols_arm64': [
-      'android', 'release_bot', 'minimal_symbols', 'arm64',
+    'android_release_bot_minimal_symbols_arm64_reclient': [
+      'android', 'release_bot_reclient', 'minimal_symbols', 'arm64',
       'strip_debug_info',
     ],
 
@@ -1454,6 +1454,11 @@
       'strip_debug_info', 'webview_monochrome',
     ],
 
+    'android_release_bot_minimal_symbols_arm64_webview_monochrome_reclient': [
+      'android', 'release_bot_reclient', 'minimal_symbols', 'arm64',
+      'strip_debug_info', 'webview_monochrome',
+    ],
+
     'android_release_bot_minimal_symbols_x64_fastbuild_webview_trichrome': [
       'android', 'release_bot', 'minimal_symbols', 'x64',
       'strip_debug_info', 'android_fastbuild', 'webview_trichrome',
@@ -2264,6 +2269,11 @@
       'android_fastbuild',
     ],
 
+    'gpu_tests_android_release_bot_dcheck_always_on_arm64_fastbuild_reclient': [
+      'gpu_tests', 'android', 'release_trybot_minimal_symbols_reclient', 'arm64', 'static_angle',
+      'android_fastbuild',
+    ],
+
     'gpu_tests_android_release_trybot_arm64_fastbuild': [
       'gpu_tests', 'android', 'release_trybot', 'arm64', 'static_angle',
       'android_fastbuild',
diff --git a/tools/mb/mb_config_expectations/chromium.android.fyi.json b/tools/mb/mb_config_expectations/chromium.android.fyi.json
index 547d3ac..eaf75e2 100644
--- a/tools/mb/mb_config_expectations/chromium.android.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.android.fyi.json
@@ -26,7 +26,8 @@
       "system_webview_package_name": "com.google.android.apps.chrome",
       "target_cpu": "arm64",
       "target_os": "android",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "Android arm64 Builder (dbg) (reclient)": {
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index 56892b2..ed87d1d6 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -278,7 +278,8 @@
       "symbol_level": 1,
       "target_cpu": "arm64",
       "target_os": "android",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "VR Linux": {
diff --git a/tools/mb/mb_config_expectations/chromium.gpu.json b/tools/mb/mb_config_expectations/chromium.gpu.json
index 97077a76..287c4853 100644
--- a/tools/mb/mb_config_expectations/chromium.gpu.json
+++ b/tools/mb/mb_config_expectations/chromium.gpu.json
@@ -12,7 +12,8 @@
       "target_cpu": "arm64",
       "target_os": "android",
       "use_errorprone_java_compiler": false,
-      "use_goma": true,
+      "use_rbe": true,
+      "use_remoteexec": true,
       "use_static_angle": true
     }
   },
diff --git a/tools/mb/mb_config_expectations/chromium.mojo.json b/tools/mb/mb_config_expectations/chromium.mojo.json
index 96c572dc..5234c6a7 100644
--- a/tools/mb/mb_config_expectations/chromium.mojo.json
+++ b/tools/mb/mb_config_expectations/chromium.mojo.json
@@ -10,7 +10,8 @@
       "symbol_level": 1,
       "target_cpu": "arm64",
       "target_os": "android",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "Mojo ChromiumOS": {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 302afc7..ec1055bc 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3720,11 +3720,12 @@
   <summary>Defines ARC ANR types.</summary>
   <int value="0" label="Unknown">ANR type cannot be determined.</int>
   <int value="1" label="Input">ANR while handling input event dispatching.</int>
-  <int value="2" label="Service">ANR in service.</int>
+  <int value="2" label="ForegroundService">ANR in foreground service.</int>
   <int value="3" label="Broadcast">ANR handling broadcast.</int>
   <int value="4" label="ContentProvider">ANR from ContentProvider.</int>
   <int value="5" label="AppRequested">ANR requested explicitly by app.</int>
   <int value="6" label="Process">ANR in process.</int>
+  <int value="7" label="BackgroundService">ANR in background service.</int>
 </enum>
 
 <enum name="ArcAppShortcutStatus">
@@ -50111,6 +50112,7 @@
   <int value="-1010588306" label="SlideTopChromeWithPageScrolls:disabled"/>
   <int value="-1008511612" label="EnableCustomMacPaperSizes:disabled"/>
   <int value="-1007961880" label="PrivacySandboxSettings:enabled"/>
+  <int value="-1007856269" label="CssSelectorFragmentAnchor:disabled"/>
   <int value="-1005937042" label="ArcVmBalloonPolicy:enabled"/>
   <int value="-1005164075" label="ContextualSearchTranslations:enabled"/>
   <int value="-1002537430" label="HudDisplayForPerformanceMetrics:disabled"/>
@@ -50356,6 +50358,7 @@
   <int value="-823165021" label="MaterialDesignUserMenu:enabled"/>
   <int value="-822712881"
       label="ContextualSearchThinWebViewImplementation:enabled"/>
+  <int value="-822237807" label="UnifiedSidePanel:enabled"/>
   <int value="-821635312" label="EyeDropper:enabled"/>
   <int value="-820041355" label="enable-transition-compositing"/>
   <int value="-819165158" label="ScrollableTabStripButtons:enabled"/>
@@ -50589,6 +50592,7 @@
   <int value="-645455405" label="MacViewsNativeDialogs:enabled"/>
   <int value="-643217597" label="EduCoexistenceConsentLog:enabled"/>
   <int value="-642346675" label="DesktopPWAsAttentionBadgingCrOS:enabled"/>
+  <int value="-641846393" label="WebViewLegacyTlsSupport:enabled"/>
   <int value="-641820371" label="EnableCustomMacPaperSizes:enabled"/>
   <int value="-641719457" label="disable-compositor-touch-hit-testing"/>
   <int value="-641423897" label="CompositeAfterPaint:disabled"/>
@@ -52278,6 +52282,7 @@
   <int value="644084236" label="CloseButtonsInactiveTabs:enabled"/>
   <int value="644189071" label="PermissionsBlacklist:enabled"/>
   <int value="646252875" label="ReadItLaterInMenu:enabled"/>
+  <int value="646269021" label="UnifiedSidePanel:disabled"/>
   <int value="646738320" label="disable-gesture-editing"/>
   <int value="647662142" label="use-angle"/>
   <int value="649111851" label="MidiManagerCros:enabled"/>
@@ -52547,6 +52552,7 @@
       label="DesktopPWAsLocalUpdatingThrottlePersistence:disabled"/>
   <int value="845659238" label="DevicePosture:enabled"/>
   <int value="846951416" label="CopylessPaste:enabled"/>
+  <int value="848005486" label="WebViewLegacyTlsSupport:disabled"/>
   <int value="848324390" label="enable-lock-screen-apps"/>
   <int value="849980462" label="RemoveNtpFakebox:disabled"/>
   <int value="850779988" label="allow-popups-during-page-unload"/>
@@ -53669,6 +53675,7 @@
   <int value="1698089268" label="WebXRMultiGpu:disabled"/>
   <int value="1699180023" label="PaymentRequestOptionalTotal:disabled"/>
   <int value="1699182601" label="DockedMagnifier:disabled"/>
+  <int value="1699290689" label="CssSelectorFragmentAnchor:enabled"/>
   <int value="1700117535" label="MediaFeedsBackgroundFetching:disabled"/>
   <int value="1700394127" label="OverlayScrollbar:disabled"/>
   <int value="1701972870" label="NTPSnippetsIncreasedVisibility:enabled"/>
@@ -91733,6 +91740,7 @@
   <int value="2" label="Load failed and error page whas shown"/>
   <int value="3" label="Load failed and was redirected to NTP"/>
   <int value="4" label="Load failed and tab was closed"/>
+  <int value="5" label="Load failed in preload and tab was never opened"/>
 </enum>
 
 <enum name="WhitelistedDownloadType">
diff --git a/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS b/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS
index 2351791..f294359f 100644
--- a/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS
+++ b/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS
@@ -15,6 +15,7 @@
 dmurph@chromium.org
 drubery@chromium.org
 dschinazi@chromium.org
+dschuff@chromium.org
 dullweber@chromium.org
 eirage@chromium.org
 ellyjones@chromium.org
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml
index eff1a83..6900464 100644
--- a/tools/metrics/histograms/metadata/browser/histograms.xml
+++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -533,7 +533,7 @@
 
 <histogram
     name="Browser.PaintPreview.TabbedPlayer.UpTime{TabbedPaintPreviewPlayerUptime}"
-    units="ms" expires_after="2022-01-02">
+    units="ms" expires_after="2022-03-31">
   <owner>ckitagawa@chromium.org</owner>
   <owner>yashard@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/cras/histograms.xml b/tools/metrics/histograms/metadata/cras/histograms.xml
index 585cda9d..03e3093 100644
--- a/tools/metrics/histograms/metadata/cras/histograms.xml
+++ b/tools/metrics/histograms/metadata/cras/histograms.xml
@@ -71,7 +71,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cras.BusyloopLength" units="units" expires_after="2021-12-01">
+<histogram name="Cras.BusyloopLength" units="units" expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -94,7 +94,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceNoiseCancellationEnabled" units="BooleanEnabled"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
 <!-- Name completed by histogram_suffixes
      name="Cras.DeviceType" -->
 
@@ -156,7 +156,7 @@
 </histogram>
 
 <histogram name="Cras.HfpBatteryIndicatorSupported"
-    enum="CrasHfpBatteryIndicator" expires_after="2021-12-01">
+    enum="CrasHfpBatteryIndicator" expires_after="2022-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -165,7 +165,7 @@
 </histogram>
 
 <histogram name="Cras.HfpBatteryReport" enum="CrasHfpBatteryIndicator"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -177,7 +177,7 @@
 </histogram>
 
 <histogram name="Cras.HfpScoConnectionError" enum="CrasHfpScoError"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>enshuo@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -208,7 +208,7 @@
 </histogram>
 
 <histogram name="Cras.HighestDeviceDelayInput" units="units"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -221,7 +221,7 @@
 </histogram>
 
 <histogram name="Cras.HighestDeviceDelayOutput" units="units"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -245,7 +245,7 @@
 </histogram>
 
 <histogram name="Cras.HighestOutputHardwareLevel" units="frames"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -256,7 +256,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceA2DPRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -267,7 +267,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceAbnormalFallbackRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -289,7 +289,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceBluetoothRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -312,7 +312,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceFrontMicRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -323,7 +323,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceHFPRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -345,7 +345,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceHSPRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -356,7 +356,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceInternalMicRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -367,7 +367,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceKeyboardMicRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -389,7 +389,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceNormalFallbackRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -400,7 +400,7 @@
 </histogram>
 
 <histogram name="Cras.InputDevicePostDspLoopbackRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -411,7 +411,7 @@
 </histogram>
 
 <histogram name="Cras.InputDevicePostMixLoopbackRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -422,7 +422,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceRearMicRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -433,7 +433,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceSilentHotwordRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -444,7 +444,7 @@
 </histogram>
 
 <histogram name="Cras.InputDeviceUnknownRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -483,7 +483,7 @@
 </histogram>
 
 <histogram name="Cras.kHfpWidebandSpeechSelectedCodec" enum="CrasHfpCodec"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -599,7 +599,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceAbnormalFallbackRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -610,7 +610,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceBluetoothRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -622,7 +622,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHapticRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -666,7 +666,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceHSPRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -699,7 +699,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceNormalFallbackRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -710,7 +710,7 @@
 </histogram>
 
 <histogram name="Cras.OutputDeviceUnknownRuntime" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -759,7 +759,7 @@
 </histogram>
 
 <histogram name="Cras.RtcRuntime.{InDevice}.{OutDevice}" units="seconds"
-    expires_after="2021-12-01">
+    expires_after="2022-12-01">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 18dcde0..087d2b4 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -955,12 +955,17 @@
   <owner>poromov@chromium.org</owner>
   <owner>chromeos-dlp@google.com</owner>
   <summary>
-    Result of Data Leak Prevention evaluation for taking a screenshot.
+    Result of Data Leak Prevention evaluation for taking a screenshot or a video
+    capture.
   </summary>
 </histogram>
 
 <histogram name="Enterprise.Dlp.VideoCaptureBlocked" enum="BooleanBlocked"
-    expires_after="2022-05-01">
+    expires_after="M98">
+  <obsolete>
+    Deprecated after M98. Events of this type are now included in
+    Enterprise.Dlp.ScreenshotBlocked.
+  </obsolete>
   <owner>poromov@chromium.org</owner>
   <owner>chromeos-dlp@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/language/histograms.xml b/tools/metrics/histograms/metadata/language/histograms.xml
index 40266a0..bdb50f61 100644
--- a/tools/metrics/histograms/metadata/language/histograms.xml
+++ b/tools/metrics/histograms/metadata/language/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="LanguageDetection.TFLiteModel.LanguageDetectionModelState"
-    enum="LanguageDetectionModelState" expires_after="2022-04-17">
+    enum="LanguageDetectionModelState" expires_after="2022-06-30">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -33,7 +33,7 @@
 </histogram>
 
 <histogram name="LanguageDetection.TFLiteModel.WasModelAvailableForDetection"
-    enum="BooleanAvailable" expires_after="2022-04-03">
+    enum="BooleanAvailable" expires_after="2022-06-30">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -44,7 +44,7 @@
 </histogram>
 
 <histogram name="LanguageDetection.TFLiteModel.WasModelRequestDeferred"
-    enum="BooleanDeferred" expires_after="2022-04-24">
+    enum="BooleanDeferred" expires_after="2022-06-30">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -56,7 +56,7 @@
 
 <histogram
     name="LanguageDetection.TFLiteModel.WasModelUnavailableDueToDeferredLoad"
-    enum="Boolean" expires_after="2022-04-24">
+    enum="Boolean" expires_after="2022-06-30">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -67,7 +67,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.Actions" enum="LanguageSettingsActionType"
-    expires_after="2021-12-01">
+    expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -79,7 +79,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.AppLanguagePrompt.Action"
-    enum="LanguageSettingsAppLanguagePromptAction" expires_after="2022-04-10">
+    enum="LanguageSettingsAppLanguagePromptAction" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -91,7 +91,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.AppLanguagePrompt.IsOnline"
-    enum="BooleanYesNo" expires_after="2021-12-01">
+    enum="BooleanYesNo" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -105,7 +105,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.AppLanguagePrompt.IsTopLanguageSelected"
-    enum="BooleanYesNo" expires_after="2022-04-17">
+    enum="BooleanYesNo" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -119,7 +119,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.AppLanguagePrompt.Language"
-    enum="LocaleCodeISO639" expires_after="2021-12-01">
+    enum="LocaleCodeISO639" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -134,7 +134,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.AppLanguagePrompt.OpenDuration.{ActionType}"
-    units="ms" expires_after="2021-12-01">
+    units="ms" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -153,7 +153,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.PageImpression"
-    enum="LanguageSettingsPageType" expires_after="2022-04-03">
+    enum="LanguageSettingsPageType" expires_after="2022-06-30">
   <owner>googleo@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -164,7 +164,7 @@
 </histogram>
 
 <histogram name="LanguageSettings.SplitInstallFinalStatus"
-    enum="LanguageSettingsSplitInstallStatus" expires_after="2022-05-01">
+    enum="LanguageSettingsSplitInstallStatus" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -176,7 +176,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.AcceptLanguage" enum="LanguageName"
-    expires_after="2022-04-03">
+    expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -186,7 +186,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.AcceptLanguage.Count" units="units"
-    expires_after="2022-04-17">
+    expires_after="2022-06-30">
   <owner>dvallet@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -196,7 +196,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageName"
-    expires_after="2022-04-03">
+    expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -206,7 +206,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.MostFrequentPageLanguages" enum="LanguageName"
-    expires_after="2022-04-10">
+    expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -224,7 +224,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.UI.Android.Availability"
-    enum="LanguageUsage.UI.Android.Availability" expires_after="2022-04-03">
+    enum="LanguageUsage.UI.Android.Availability" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -240,7 +240,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.UI.Android.Correctness"
-    enum="LanguageUsage.UI.Android.Correctness" expires_after="2021-12-01">
+    enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -252,7 +252,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.UI.Android.Correctness.NoOverride"
-    enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-04-10">
+    enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -266,7 +266,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.UI.Android.Correctness.Override"
-    enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-04-10">
+    enum="LanguageUsage.UI.Android.Correctness" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -281,8 +281,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.UI.Android.IsLocaleUpdated"
-    enum="LanguageUsage.UI.Android.LocaleUpdateStatus"
-    expires_after="2022-04-24">
+    enum="LanguageUsage.UI.Android.LocaleUpdateStatus" expires_after="M100">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -296,7 +295,7 @@
 </histogram>
 
 <histogram name="LanguageUsage.UI.Android.OverrideLanguage"
-    enum="LocaleCodeISO639" expires_after="2022-04-03">
+    enum="LocaleCodeISO639" expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -310,7 +309,7 @@
 
 <histogram name="LanguageUsage.UI.Android.OverrideLanguage.IsSystemLanguage"
     enum="LanguageUsage.UI.Android.OverrideLanguage.IsSystemLanguage"
-    expires_after="2022-04-10">
+    expires_after="2022-06-30">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/na_cl/OWNERS b/tools/metrics/histograms/metadata/na_cl/OWNERS
new file mode 100644
index 0000000..ab753e84
--- /dev/null
+++ b/tools/metrics/histograms/metadata/na_cl/OWNERS
@@ -0,0 +1,5 @@
+per-file OWNERS=file://tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS
+
+# Prefer sending CLs to the owners listed below.
+# Use chromium-metrics-reviews@google.com as a backup.
+dschuff@chromium.org
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index 3e26dac..6f4ae755 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -339,7 +339,7 @@
 
 <histogram
     name="OptimizationGuide.ModelExecutor.ExecutionLatency.{OptimizationTarget}"
-    units="ms" expires_after="M96">
+    units="ms" expires_after="M106">
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -477,7 +477,7 @@
 </histogram>
 
 <histogram base="true" name="OptimizationGuide.OptimizationFilterStatus"
-    enum="OptimizationGuideOptimizationFilterStatus" expires_after="2022-01-02">
+    enum="OptimizationGuideOptimizationFilterStatus" expires_after="M106">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 371dd29..33272f46 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -19344,9 +19344,10 @@
     Records load events for the What's New page when a load event occurs. This
     tracks how many times loading remote content is attempted, and whether it
     succeeds, fails and results in an error page, fails and redirects to the New
-    Tab Page, or fails and closes the tab. Load is attempted when the page is
-    first opened, and success or failure will occur when the network request
-    completes. Desktop only.
+    Tab Page, fails and doesn't open the tab (for preloading), or fails and
+    closes the tab. Load is attempted when the page is first opened or on first
+    startup after updating to a new milestone. Success or failure will occur
+    when the network request completes. Desktop only.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml
index d88b6f5..3d20969a5 100644
--- a/tools/metrics/histograms/metadata/renderer/histograms.xml
+++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -402,7 +402,7 @@
 </histogram>
 
 <histogram name="Renderer.PaintPreview.Capture.MainFrameSuccess"
-    enum="BooleanSuccess" expires_after="2022-01-02">
+    enum="BooleanSuccess" expires_after="2022-03-31">
   <owner>ckitagawa@chromium.org</owner>
   <owner>mahmoudi@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index 3a7a6af..e29fedf 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -288,7 +288,7 @@
 </histogram>
 
 <histogram name="Storage.FileSystemAccess.PersistedPermissions.Age.{Type}"
-    units="ms" expires_after="2022-01-01">
+    units="ms" expires_after="2023-01-01">
   <owner>asully@chromium.org</owner>
   <owner>src/content/browser/file_system_access/OWNERS</owner>
   <summary>
@@ -302,7 +302,7 @@
 </histogram>
 
 <histogram name="Storage.FileSystemAccess.PersistedPermissions.Count"
-    units="paths" expires_after="2022-01-01">
+    units="paths" expires_after="2023-01-01">
   <owner>asully@chromium.org</owner>
   <owner>src/content/browser/file_system_access/OWNERS</owner>
   <summary>
@@ -317,7 +317,7 @@
 
 <histogram
     name="Storage.FileSystemAccess.PersistedPermissions.SweepTime.{Type}"
-    units="ms" expires_after="2022-01-01">
+    units="ms" expires_after="2023-01-01">
   <owner>asully@chromium.org</owner>
   <owner>src/content/browser/file_system_access/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index b672ee8..a9d8107 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1730,7 +1730,7 @@
 </histogram>
 
 <histogram name="Tabs.PersistedTabData.Storage.Restore.File"
-    enum="BooleanSuccess" expires_after="2021-12-05">
+    enum="BooleanSuccess" expires_after="2022-11-21">
   <owner>yusufo@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <owner>dtrainor@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/translate/histograms.xml b/tools/metrics/histograms/metadata/translate/histograms.xml
index 8e0e6dd..0747032 100644
--- a/tools/metrics/histograms/metadata/translate/histograms.xml
+++ b/tools/metrics/histograms/metadata/translate/histograms.xml
@@ -264,7 +264,7 @@
 </histogram>
 
 <histogram name="Translate.DeclineTranslateCloseInfobar" units="units"
-    expires_after="M105">
+    expires_after="2022-06-30">
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -394,7 +394,7 @@
 </histogram>
 
 <histogram name="Translate.LanguageDetection.LanguageVerification"
-    enum="TranslateLanguageVerification" expires_after="M94">
+    enum="TranslateLanguageVerification" expires_after="2022-06-30">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -559,7 +559,7 @@
 </histogram>
 
 <histogram name="Translate.NeverTranslateSite" units="units"
-    expires_after="M105">
+    expires_after="2022-06-30">
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -865,7 +865,7 @@
 </histogram>
 
 <histogram name="Translate.Ranker.QueryResult" enum="BooleanAccepted"
-    expires_after="M85">
+    expires_after="2022-06-30">
   <owner>rogerm@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -978,13 +978,13 @@
 </histogram>
 
 <histogram name="Translate.SimilarLanguageMatch" enum="BooleanMatched"
-    expires_after="M77">
+    expires_after="2022-06-30">
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
     This metrics is logged whenever a page is loaded. The logged value is
     &quot;Mathced&quot; when the CLD-detected language differs from the page
-    language code , and the two languages are such similar languages. In that
+    language code, and the two languages are such similar languages. In that
     case, Chrome ignore the CLD-determined language and instead uses the page
     language code. The page language code is decided by Content-Language and
     HTML lang attribute.
@@ -1088,7 +1088,7 @@
 </histogram>
 
 <histogram name="Translate.TranslateFrameCount" units="frames"
-    expires_after="M88">
+    expires_after="2022-06-30">
   <owner>sclittle@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml
index fe692b7..4857ab5c 100644
--- a/tools/metrics/histograms/metadata/web_apk/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -195,7 +195,7 @@
 </histogram>
 
 <histogram name="WebApk.Session.TotalDuration2{WebApkDistributorType}"
-    units="ms" expires_after="2021-12-16">
+    units="ms" expires_after="2022-12-16">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -208,7 +208,7 @@
 </histogram>
 
 <histogram name="WebApk.ShellApkVersion2{WebApkDistributorType}" units="units"
-    expires_after="2022-06-06">
+    expires_after="2022-06-01">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -228,7 +228,7 @@
 </histogram>
 
 <histogram name="WebApk.Startup.Cold.NewStyle.ShellLaunchToSplashscreenVisible"
-    units="ms" expires_after="2021-12-01">
+    units="ms" expires_after="2022-06-01">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -262,7 +262,7 @@
 </histogram>
 
 <histogram name="WebApk.Startup.Cold.ShellLaunchToSplashscreenVisible"
-    units="ms" expires_after="2022-05-01">
+    units="ms" expires_after="2022-06-01">
   <owner>mheikal@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
@@ -278,7 +278,7 @@
 </histogram>
 
 <histogram name="WebApk.Uninstall{WebApkDistributorType}" enum="BooleanHit"
-    expires_after="2022-06-06">
+    expires_after="2022-06-01">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -296,7 +296,7 @@
 </histogram>
 
 <histogram name="WebApk.Update.GooglePlayUpdateResult"
-    enum="WebApkGooglePlayInstallResult" expires_after="2022-05-01">
+    enum="WebApkGooglePlayInstallResult" expires_after="2022-06-01">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index 2572e8f..cb255a1e 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -4178,7 +4178,7 @@
 </histogram>
 
 <histogram name="WebRtcTextLogging{WebRtcLoggingEvent}"
-    enum="WebRtcLoggingWebAppIdHash" expires_after="2021-12-01">
+    enum="WebRtcLoggingWebAppIdHash" expires_after="2022-12-01">
   <owner>toprice@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
diff --git a/tools/origin_trials/PRESUBMIT.py b/tools/origin_trials/PRESUBMIT.py
index 18906ac..e97ba316 100644
--- a/tools/origin_trials/PRESUBMIT.py
+++ b/tools/origin_trials/PRESUBMIT.py
@@ -9,7 +9,9 @@
   results = []
 
   # Run Pylint over the files in the directory.
-  pylint_checks = input_api.canned_checks.GetPylint(input_api, output_api)
+  pylint_checks = input_api.canned_checks.GetPylint(input_api,
+                                                    output_api,
+                                                    version='2.7')
   results.extend(input_api.RunTests(pylint_checks))
 
   # Run the generate_token unittests.
diff --git a/tools/origin_trials/check_token.py b/tools/origin_trials/check_token.py
index 33a0352e..7d0f17d 100755
--- a/tools/origin_trials/check_token.py
+++ b/tools/origin_trials/check_token.py
@@ -63,7 +63,7 @@
 
 class OverrideKeyFileAction(argparse.Action):
   def __init__(self, option_strings, dest, **kwargs):
-    super(OverrideKeyFileAction, self).__init__(option_strings, dest, **kwargs)
+    super().__init__(option_strings, dest, **kwargs)
 
   def __call__(self, parser, namespace, values, option_string=None):
     setattr(namespace, "use_chrome_key", None)
@@ -146,7 +146,7 @@
   for x in version:
     version_number <<= 8
     version_number += ord(x)
-  if (version != VERSION2 and version != VERSION3):
+  if (version not in (VERSION2, VERSION3)):
     print("Token has wrong version: %d" % version_number)
     sys.exit(1)
 
diff --git a/tools/origin_trials/generate_token.py b/tools/origin_trials/generate_token.py
index 4f932f3..687bbd2f 100755
--- a/tools/origin_trials/generate_token.py
+++ b/tools/origin_trials/generate_token.py
@@ -80,6 +80,8 @@
     return None
   if all(DNS_LABEL_REGEX.match(label) for label in arg.split(".")):
     return arg.lower()
+  return None
+
 
 def OriginFromArg(arg):
   """Constructs the origin for the token from a command line argument.
@@ -102,8 +104,9 @@
   # Add default port if it is not specified
   try:
     port = origin.port
-  except ValueError:
-    raise argparse.ArgumentTypeError("%s is not a hostname or a URL" % arg)
+  except ValueError as e:
+    raise argparse.ArgumentTypeError("%s is not a hostname or a URL" %
+                                     arg) from e
   if not port:
     port = {"https": 443, "http": 80}[origin.scheme]
   # Strip any extra components and return the origin URL:
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 0ee5bfc7..fc5bc9c 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "05d5c503e1afca8501aa013849c2c44ecbb3a9fe",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/03cb3fd2f9c1b7475bf3838ecdf014b786b791f3/trace_processor_shell.exe"
+            "hash": "43de31c1b963a50efe9fdde91e42555ed8b348bd",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/715528ea109f8b98cecd82b9ebbad27d8b19a79d/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "186a99c6b3924ba51d617233ae428a97bc45ac4f",
diff --git a/tools/tracing/PRESUBMIT.py b/tools/tracing/PRESUBMIT.py
index 8a503c7..395a4fa 100644
--- a/tools/tracing/PRESUBMIT.py
+++ b/tools/tracing/PRESUBMIT.py
@@ -14,7 +14,9 @@
 def RunUnittests(input_api, output_api):
   results = []
   # Run Pylint over the files in the directory.
-  pylint_checks = input_api.canned_checks.GetPylint(input_api, output_api)
+  pylint_checks = input_api.canned_checks.GetPylint(input_api,
+                                                    output_api,
+                                                    version='2.6')
   results.extend(input_api.RunTests(pylint_checks))
 
   results.extend(
@@ -23,6 +25,7 @@
           output_api,
           '.',
           files_to_check=[r'.+_unittest\.py$'],
+          run_on_python2=not USE_PYTHON3,
           skip_shebang_check=True))
   return results
 
diff --git a/tools/tracing/adb_profile_chrome_startup.py b/tools/tracing/adb_profile_chrome_startup.py
index cbe7927..a58b805 100644
--- a/tools/tracing/adb_profile_chrome_startup.py
+++ b/tools/tracing/adb_profile_chrome_startup.py
@@ -41,7 +41,7 @@
     devices = [a.GetDeviceSerial() for a in adb_wrapper.AdbWrapper.Devices()]
     if len(devices) == 0:
       raise RuntimeError('No ADB devices connected.')
-    elif len(devices) >= 2:
+    if len(devices) >= 2:
       raise RuntimeError('Multiple devices connected, serial number ' +
                          'required. Specify the -e flag.')
     options.device_serial_number = devices[0]
diff --git a/tools/tracing/metadata_extractor.py b/tools/tracing/metadata_extractor.py
index 84370f7..758b663 100644
--- a/tools/tracing/metadata_extractor.py
+++ b/tools/tracing/metadata_extractor.py
@@ -145,19 +145,18 @@
 
     if raw_os_name == 'Android':
       return OSName.ANDROID
-    elif raw_os_name == 'Linux':
+    if raw_os_name == 'Linux':
       return OSName.LINUX
-    elif raw_os_name == 'Mac OS X':
+    if raw_os_name == 'Mac OS X':
       return OSName.MAC
-    elif raw_os_name == 'Windows NT':
+    if raw_os_name == 'Windows NT':
       return OSName.WINDOWS
-    elif raw_os_name == 'CrOS':
+    if raw_os_name == 'CrOS':
       return OSName.CROS
-    elif raw_os_name == 'Fuschia':
+    if raw_os_name == 'Fuschia':
       return OSName.FUSCHIA
-    else:
-      raise Exception('OS name "%s" not recognized: %s' %
-                      (raw_os_name, self._trace_file))
+    raise Exception('OS name "%s" not recognized: %s' %
+                    (raw_os_name, self._trace_file))
 
   def InitializeForTesting(self,
                            version_number=None,
diff --git a/tools/tracing/rename_breakpad_unittest.py b/tools/tracing/rename_breakpad_unittest.py
index 2616d93..cb511fe 100755
--- a/tools/tracing/rename_breakpad_unittest.py
+++ b/tools/tracing/rename_breakpad_unittest.py
@@ -38,11 +38,11 @@
     """
     files = set()
     dirs = set()
-    for root, subdirs, filenames in os.walk(root):
+    for topdir, subdirs, filenames in os.walk(root):
       for filename in filenames:
-        files.add(os.path.join(root, filename))
+        files.add(os.path.join(topdir, filename))
       for subdir in subdirs:
-        dirs.add(os.path.join(root, subdir))
+        dirs.add(os.path.join(topdir, subdir))
     return dirs, files
 
   def _assertFilesInInputDir(self,
diff --git a/tools/tracing/symbol_fetcher_unittest.py b/tools/tracing/symbol_fetcher_unittest.py
index 30198f1..48c1c83 100755
--- a/tools/tracing/symbol_fetcher_unittest.py
+++ b/tools/tracing/symbol_fetcher_unittest.py
@@ -128,7 +128,7 @@
 
 class MacAndLinuxTestCase(SymbolFetcherTestBase):
   def setUp(self):
-    super(MacAndLinuxTestCase, self).setUp()
+    super().setUp()
 
     cloud_storage.Get = mock.Mock()
     # Default: Cloud storage has |gcs_file|.zip file. We use |side_effect|
@@ -257,7 +257,7 @@
 
 class AndroidTestCase(SymbolFetcherTestBase):
   def setUp(self):
-    super(AndroidTestCase, self).setUp()
+    super().setUp()
 
     # Base directories for Android symbols.
     self.out = tempfile.mkdtemp(dir=self.breakpad_output_dir)
diff --git a/tools/typescript/definitions/tabs.d.ts b/tools/typescript/definitions/tabs.d.ts
index c87db457..0ca748f 100644
--- a/tools/typescript/definitions/tabs.d.ts
+++ b/tools/typescript/definitions/tabs.d.ts
@@ -60,7 +60,23 @@
       openerTabId?: number;
     }
 
-    export function create(createProperties: CreateProperties,
-                           callback?: (p1: Tab) => void): void;
+    type UpdateProperties = {
+      url?: string,
+      active?: boolean,
+      highlighted?: boolean,
+      selected?: boolean,
+      pinned?: boolean,
+      muted?: boolean,
+      openerTabId?: number,
+      autoDiscardable?: boolean,
+    }
+
+    export function
+    create(createProperties: CreateProperties, callback?: (p1: Tab) => void):
+        void;
+
+    export function update(
+        tabId: number|undefined, updateProperties: UpdateProperties,
+        callback?: (p1?: Tab) => void): void;
   }
 }
diff --git a/ui/accessibility/platform/inspect/ax_api_type.cc b/ui/accessibility/platform/inspect/ax_api_type.cc
index 2c2ede8..2e9f9f8 100644
--- a/ui/accessibility/platform/inspect/ax_api_type.cc
+++ b/ui/accessibility/platform/inspect/ax_api_type.cc
@@ -10,6 +10,8 @@
   switch (type_) {
     case kAndroid:
       return "android";
+    case kAndroidExternal:
+      return "android_external";
     case kBlink:
       return "blink";
     case kFuchsia:
diff --git a/ui/accessibility/platform/inspect/ax_api_type.h b/ui/accessibility/platform/inspect/ax_api_type.h
index ef8cc3d..ccb6432a 100644
--- a/ui/accessibility/platform/inspect/ax_api_type.h
+++ b/ui/accessibility/platform/inspect/ax_api_type.h
@@ -15,7 +15,8 @@
  public:
   // Inspect types for all platforms.
   enum TypeConstant {
-    kAndroid,
+    kAndroid,          // For the platform specific Android tree (internal).
+    kAndroidExternal,  // For the Java-side "external" Android tree.
     kBlink,
     kFuchsia,
     kMac,
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 1757415..fe454e1 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -43,7 +43,7 @@
       DidNotSwapReason reason) override {
     return DidNotSwapAction::KEEP_ACTIVE;
   }
-  int64_t TraceId() const override { return 0; }
+  int64_t GetTraceId() const override { return 0; }
 
  private:
   const float height_;
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index e5b55194..29ae574 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -1167,7 +1167,12 @@
 
   if (skia_support_skottie && !is_ios) {
     sources += [ "//ui/lottie/animation_unittest.cc" ]
-    deps += [ "//ui/lottie" ]
+    deps += [
+      "//cc:test_support",
+      "//cc/paint",
+      "//third_party/abseil-cpp:absl",
+      "//ui/lottie",
+    ]
   }
 }
 
diff --git a/ui/chromeos/styles/presubmit_support.py b/ui/chromeos/styles/presubmit_support.py
index 74822e2..fd7015b 100644
--- a/ui/chromeos/styles/presubmit_support.py
+++ b/ui/chromeos/styles/presubmit_support.py
@@ -29,8 +29,8 @@
     # stylesheets.
     css_prefixes = set()
     style_generator = CSSStyleGenerator()
+    style_generator.AddJSONFilesToModel(cros_styles)
     for file_path in cros_styles:
-        style_generator.AddJSONFileToModel(file_path)
         context = style_generator.in_file_to_context.get(file_path,
                                                          {}).get('CSS')
         if (not context or 'prefix' not in context):
diff --git a/ui/events/ozone/evdev/event_device_info.cc b/ui/events/ozone/evdev/event_device_info.cc
index 5d0c205..3139e148 100644
--- a/ui/events/ozone/evdev/event_device_info.cc
+++ b/ui/events/ozone/evdev/event_device_info.cc
@@ -75,11 +75,14 @@
     {0x1038, 0x1830},  // SteelSeries Rival 3 Wireless (USB dongle)
     {0x1050, 0x0010},  // Yubico.com Yubikey
     {0x1050, 0x0407},  // Yubico.com Yubikey 4 OTP+U2F+CCID
+    {0x1532, 0x007a},  // Razer Viper Ultimate (Wired)
+    {0x1532, 0x007b},  // Razer Viper Ultimate (Wireless)
     {0x17ef, 0x6123},  // Lenovo USB-C Wired Compact Mouse
     {0x1b1c, 0x1b94},  // Corsair Katar Pro Wireless (USB dongle)
     {0x1bae, 0x1b1c},  // Corsair Katar Pro Wireless (Bluetooth)
     {0x1bcf, 0x08a0},  // Kensington Pro Fit Full-size
     {0x256c, 0x006d},  // Huion HS64
+    {0x258a, 0x1007},  // Acer Cestus 330
     {0x28bd, 0x0914},  // XP-Pen Star G640
     {0x28bd, 0x091f},  // XP-Pen Artist 12 Pro
     {0x28bd, 0x0928},  // XP-Pen Deco mini7W
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.m.js
index a15876c..d1cab376 100644
--- a/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js
+++ b/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js
@@ -9,7 +9,7 @@
 import {metrics} from '../../common/js/metrics.js';
 import {installMockChrome, MockChromeStorageAPI} from '../../common/js/mock_chrome.js';
 import {MockFileSystem} from '../../common/js/mock_entry.js';
-import {reportPromise} from '../../common/js/test_error_reporting.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';
 import {VolumeInfo} from '../../externs/volume_info.js';
@@ -48,8 +48,28 @@
  */
 metrics.recordEnum = function(name, value, opt_validValues) {};
 
+/**
+ * @type {function(function():void): !Promise<boolean>}
+ */
+let originalDoIfPrimaryContext;
+
+/**
+ * Helper function for reporting errors from a promise handling code.
+ * @param {string} message
+ * @param {function(boolean):void} done
+ * @return {!Promise<boolean>} Always Promise.resolve(false);
+ */
+function reportError(message, done) {
+  console.error(message);
+  done(/*error=*/ true);
+  return Promise.resolve(false);
+}
+
+
 // Set up the test components.
 export function setUp() {
+  // store the doIfPrimary original function, as we frequently modify it.
+  originalDoIfPrimaryContext = util.doIfPrimaryContext;
   // Set up string assets.
   loadTimeData.resetForTesting({
     DEVICE_UNSUPPORTED_MESSAGE: 'DEVICE_UNSUPPORTED: $1',
@@ -84,13 +104,14 @@
 export function tearDown() {
   util.isSwaEnabled = restoreIsSwaEnabled;
   swaEnabledState = false;
+  util.doIfPrimaryContext = originalDoIfPrimaryContext;
 }
 
 function setUpInIncognitoContext() {
   mockChrome.extension.inIncognitoContext = true;
 }
 
-export function testGoodDevice(callback) {
+export async function testGoodDevice(done) {
   // Turn off ARC so that the notification won't show the "OPEN SETTINGS"
   // button.
   mockChrome.fileManagerPrivate.arcEnabledPref = false;
@@ -107,18 +128,16 @@
     shouldNotify: true
   });
 
-  // Since arcEnabled is false here, the notification doesn't mention ARC.
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertEquals(1, Object.keys(notifications).length);
-        const options = notifications['deviceNavigation:/device/path'];
-        assertEquals('REMOVABLE_DEVICE_NAVIGATION_MESSAGE', options.message);
-        assertTrue(options.isClickable);
-      }),
-      callback);
+  await waitUntil(() => {
+    const item =
+        mockChrome.notifications.items['deviceNavigation:/device/path'];
+    return item && item.message === 'REMOVABLE_DEVICE_NAVIGATION_MESSAGE' &&
+        item.isClickable;
+  });
+  done(/*error=*/ false);
 }
 
-export function testGoodDeviceWithAllowPlayStoreMessage(callback) {
+export async function testGoodDeviceWithAllowPlayStoreMessage(done) {
   // Turn on ARC so that the notification shows the "OPEN SETTINGS" button.
   mockChrome.fileManagerPrivate.arcEnabledPref = true;
   // Turn off the ARC pref so that the notification shows the "Allow Play Store
@@ -137,20 +156,19 @@
     shouldNotify: true
   });
 
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertEquals(1, Object.keys(notifications).length);
-        const options = notifications['deviceNavigationAppAccess:/device/path'];
-        assertEquals(
-            'REMOVABLE_DEVICE_NAVIGATION_MESSAGE ' +
-                'REMOVABLE_DEVICE_ALLOW_PLAY_STORE_ACCESS_MESSAGE',
-            options.message);
-        assertTrue(options.isClickable);
-      }),
-      callback);
+  await waitUntil(() => {
+    const key = 'deviceNavigationAppAccess:/device/path';
+    const item = mockChrome.notifications.items[key];
+    return item && item.isClickable &&
+        item.message ===
+        'REMOVABLE_DEVICE_NAVIGATION_MESSAGE ' +
+            'REMOVABLE_DEVICE_ALLOW_PLAY_STORE_ACCESS_MESSAGE';
+  });
+
+  done(/*error=*/ false);
 }
 
-export function testGoodDeviceWithPlayStoreAppsHaveAccessMessage(callback) {
+export async function testGoodDeviceWithPlayStoreAppsHaveAccessMessage(done) {
   // Turn on ARC so that the notification shows the "OPEN SETTINGS" button.
   mockChrome.fileManagerPrivate.arcEnabledPref = true;
   // Turn on the ARC pref so that the notification shows the "Play Store apps
@@ -171,21 +189,19 @@
 
   // Since arcRemovableMediaAccessEnabled is true here, "Play Store apps have
   // access to ..." message is shown.
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertEquals(1, Object.keys(notifications).length);
-        const options = notifications['deviceNavigationAppAccess:/device/path'];
-        assertEquals(
-            'REMOVABLE_DEVICE_NAVIGATION_MESSAGE ' +
-                'REMOVABLE_DEVICE_PLAY_STORE_APPS_HAVE_ACCESS_MESSAGE',
-            options.message);
-        console.log(options.message);
-        assertTrue(options.isClickable);
-      }),
-      callback);
+  await waitUntil(() => {
+    const key = 'deviceNavigationAppAccess:/device/path';
+    const item = mockChrome.notifications.items[key];
+    return item && item.isClickable &&
+        item.message ===
+        'REMOVABLE_DEVICE_NAVIGATION_MESSAGE ' +
+            'REMOVABLE_DEVICE_PLAY_STORE_APPS_HAVE_ACCESS_MESSAGE';
+  });
+
+  done(/*error=*/ false);
 }
 
-export function testRemovableMediaDeviceWithImportEnabled(callback) {
+export function testRemovableMediaDeviceWithImportEnabled(done) {
   const storage = new MockChromeStorageAPI();
 
   setupFileSystem(VolumeManagerCommon.VolumeType.REMOVABLE, 'blabbity', [
@@ -212,10 +228,10 @@
       resolver.promise.then(event => {
         assertEquals('blabbity', event.volumeId);
       }),
-      callback);
+      done);
 }
 
-export function testMtpMediaDeviceWithImportEnabled(callback) {
+export function testMtpMediaDeviceWithImportEnabled(done) {
   const storage = new MockChromeStorageAPI();
 
   setupFileSystem(VolumeManagerCommon.VolumeType.MTP, 'blabbity', [
@@ -242,7 +258,7 @@
       resolver.promise.then(event => {
         assertEquals('blabbity', event.volumeId);
       }),
-      callback);
+      done);
 }
 
 export function testGoodDeviceNotNavigated() {
@@ -262,7 +278,7 @@
   assertFalse(mockChrome.notifications.resolver.settled);
 }
 
-export function testGoodDeviceWithBadParent(callback) {
+export async function testGoodDeviceWithBadParent(done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'error_internal',
@@ -275,17 +291,14 @@
     shouldNotify: true
   });
 
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertFalse(!!notifications['device:/device/path']);
-        assertEquals(
-            'DEVICE_UNKNOWN: label',
-            notifications['deviceFail:/device/path'].message);
-      }),
-      callback);
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'DEVICE_UNKNOWN: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testGoodDeviceWithBadParent_DuplicateMount(callback) {
+export function testGoodDeviceWithBadParent_DuplicateMount(done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'success',
@@ -319,10 +332,10 @@
             'REMOVABLE_DEVICE_NAVIGATION_MESSAGE',
             notifications['deviceNavigation:/device/path'].message);
       }),
-      callback);
+      done);
 }
 
-export function testUnsupportedDevice(callback) {
+export function testUnsupportedDevice(done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'error_unsupported_filesystem',
@@ -342,10 +355,10 @@
             'DEVICE_UNSUPPORTED: label',
             mockChrome.notifications.items['deviceFail:/device/path'].message);
       }),
-      callback);
+      done);
 }
 
-export function testUnknownDevice(callback) {
+export async function testUnknownDevice(done) {
   // Emulate adding a device which has unknown filesystem.
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
@@ -359,18 +372,18 @@
     shouldNotify: true
   });
 
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertFalse(!!mockChrome.notifications.items['device:/device/path']);
-        const item = mockChrome.notifications.items['deviceFail:/device/path'];
-        assertEquals('DEVICE_UNKNOWN_DEFAULT_MESSAGE', item.message);
-        // "Format device" button should appear.
-        assertEquals('DEVICE_UNKNOWN_BUTTON_LABEL', item.buttons[0].title);
-      }),
-      callback);
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item &&
+        (item.message === 'DEVICE_UNKNOWN_DEFAULT_MESSAGE' &&
+         item.buttons[0].title === 'DEVICE_UNKNOWN_BUTTON_LABEL');
+  });
+
+  assertFalse(!!mockChrome.notifications.items['device:/device/path']);
+  done(/*error=*/ false);
 }
 
-export function testUnknownReadonlyDevice(callback) {
+export async function testUnknownReadonlyDevice(done) {
   // Emulate adding a device which has unknown filesystem but is read-only.
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
@@ -384,18 +397,19 @@
     shouldNotify: true
   });
 
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertFalse(!!mockChrome.notifications.items['device:/device/path']);
-        const item = mockChrome.notifications.items['deviceFail:/device/path'];
-        assertEquals('DEVICE_UNKNOWN_DEFAULT_MESSAGE', item.message);
-        // "Format device" button should not appear.
-        assertFalse(!!item.buttons);
-      }),
-      callback);
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'DEVICE_UNKNOWN_DEFAULT_MESSAGE' &&
+        !item.buttons;
+  });
+
+  assertTrue(
+      mockChrome.notifications.items['device:/device/path'] === undefined);
+  done(/*error=*/ false);
 }
 
-export function testUnsupportedWithUnknownParentReplacesNotification() {
+export async function testUnsupportedWithUnknownParentReplacesNotification(
+    done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'error_internal',
@@ -408,9 +422,10 @@
     shouldNotify: true
   });
 
-  assertEquals(
-      'DEVICE_UNKNOWN: label',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'DEVICE_UNKNOWN: label';
+  });
 
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
@@ -424,13 +439,14 @@
     shouldNotify: true
   });
 
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'DEVICE_UNSUPPORTED: label',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'DEVICE_UNKNOWN: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testMountPartialSuccess(callback) {
+export async function testMountPartialSuccess(done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'success',
@@ -443,38 +459,33 @@
     shouldNotify: true
   });
 
-  reportPromise(
-      mockChrome.notifications.resolver.promise
-          .then(notifications => {
-            assertEquals(1, Object.keys(notifications).length);
-            assertEquals(
-                'REMOVABLE_DEVICE_NAVIGATION_MESSAGE',
-                notifications['deviceNavigation:/device/path'].message);
-          })
-          .then(() => {
-            mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
-              eventType: 'mount',
-              status: 'error_unsupported_filesystem',
-              volumeMetadata: {
-                isParentDevice: false,
-                deviceType: 'usb',
-                devicePath: '/device/path',
-                deviceLabel: 'label'
-              },
-              shouldNotify: true
-            });
-          })
-          .then(() => {
-            const notifications = mockChrome.notifications.items;
-            assertEquals(2, Object.keys(notifications).length);
-            assertEquals(
-                'MULTIPART_DEVICE_UNSUPPORTED: label',
-                notifications['deviceFail:/device/path'].message);
-          }),
-      callback);
+  await waitUntil(() => {
+    const key = 'deviceNavigation:/device/path';
+    const item = mockChrome.notifications.items[key];
+    return item && item.message === 'REMOVABLE_DEVICE_NAVIGATION_MESSAGE';
+  });
+
+  mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
+    eventType: 'mount',
+    status: 'error_unsupported_filesystem',
+    volumeMetadata: {
+      isParentDevice: false,
+      deviceType: 'usb',
+      devicePath: '/device/path',
+      deviceLabel: 'label'
+    },
+    shouldNotify: true
+  });
+
+  await waitUntil(() => {
+    const key = 'deviceFail:/device/path';
+    const item = mockChrome.notifications.items[key];
+    return item && item.message === 'MULTIPART_DEVICE_UNSUPPORTED: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testUnknown(callback) {
+export async function testUnknown(done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'error_unknown',
@@ -487,17 +498,15 @@
     shouldNotify: true
   });
 
-  reportPromise(
-      mockChrome.notifications.resolver.promise.then(notifications => {
-        assertEquals(1, Object.keys(notifications).length);
-        assertEquals(
-            'DEVICE_UNKNOWN: label',
-            notifications['deviceFail:/device/path'].message);
-      }),
-      callback);
+  await waitUntil(() => {
+    const key = 'deviceFail:/device/path';
+    const item = mockChrome.notifications.items[key];
+    return item && item.message === 'DEVICE_UNKNOWN: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testNonASCIILabel(callback) {
+export function testNonASCIILabel(done) {
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'error_internal',
@@ -518,10 +527,10 @@
             'DEVICE_UNKNOWN: \u30E9\u30D9\u30EB',
             notifications['deviceFail:/device/path'].message);
       }),
-      callback);
+      done);
 }
 
-export function testMulitpleFail() {
+export async function testMultipleFail(done) {
   // The first parent error.
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
@@ -534,10 +543,11 @@
     },
     shouldNotify: true
   });
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'DEVICE_UNKNOWN: label',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
+
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'DEVICE_UNKNOWN: label';
+  });
 
   // The first child error that replaces the parent error.
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
@@ -551,10 +561,11 @@
     },
     shouldNotify: true
   });
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'DEVICE_UNKNOWN: label',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
+
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'DEVICE_UNKNOWN: label';
+  });
 
   // The second child error that turns to a multi-partition error.
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
@@ -568,13 +579,14 @@
     },
     shouldNotify: true
   });
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'MULTIPART_DEVICE_UNSUPPORTED: label',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
 
-  // The third child error that should be ignored because the error message does
-  // not changed.
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'MULTIPART_DEVICE_UNSUPPORTED: label';
+  });
+
+  // The third child error that should be ignored because the error
+  // message does not changed.
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'error_internal',
@@ -586,128 +598,211 @@
     },
     shouldNotify: true
   });
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'MULTIPART_DEVICE_UNSUPPORTED: label',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
+
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'MULTIPART_DEVICE_UNSUPPORTED: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testDisabledDevice() {
+export async function testDisabledDevice(done) {
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'disabled', devicePath: '/device/path'});
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'EXTERNAL_STORAGE_DISABLED_MESSAGE',
-      mockChrome.notifications.items['deviceFail:/device/path'].message);
+
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['deviceFail:/device/path'];
+    return item && item.message === 'EXTERNAL_STORAGE_DISABLED_MESSAGE';
+  });
+
+  // Prepare for the second event: here we expect no notifications, thus
+  // we are unable to wait until this happens. Instead, we synchronously invoke
+  // the originalDoIfPrimaryContext and check that no notifications were
+  // recorded.
+  util.doIfPrimaryContext = async (fn) => {
+    await originalDoIfPrimaryContext(fn);
+    const keys = Object.keys(mockChrome.notifications.items);
+    if (keys.length !== 0) {
+      return reportError(`Unexpected keys ${keys}`, done);
+    }
+    done(/*error=*/ false);
+    return Promise.resolve(true);
+  };
 
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'removed', devicePath: '/device/path'});
-  assertEquals(0, Object.keys(mockChrome.notifications.items).length);
 }
 
-export function testFormatSucceeded() {
+export async function testFormatSucceeded(done) {
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'format_start', devicePath: '/device/path', deviceLabel: 'label'});
-  assertEquals(1, progressCenter.getItemCount());
-  assertEquals(
-      'FORMAT_PROGRESS_MESSAGE: label',
-      progressCenter.getItemById('format:/device/path').message);
+
+  await waitUntil(() => {
+    const item = progressCenter.getItemById('format:/device/path');
+    return !!item && item.message === 'FORMAT_PROGRESS_MESSAGE: label';
+  });
 
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
     type: 'format_success',
     devicePath: '/device/path',
     deviceLabel: 'label'
   });
-  assertEquals(1, progressCenter.getItemCount());
-  assertEquals(
-      'FORMAT_SUCCESS_MESSAGE: label',
-      progressCenter.getItemById('format:/device/path').message);
+
+  await waitUntil(() => {
+    const item = progressCenter.getItemById('format:/device/path');
+    return !!item && item.message === 'FORMAT_SUCCESS_MESSAGE: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testFormatFailed() {
+export async function testFormatFailed(done) {
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'format_start', devicePath: '/device/path', deviceLabel: 'label'});
-  assertEquals(1, progressCenter.getItemCount());
-  assertEquals(
-      'FORMAT_PROGRESS_MESSAGE: label',
-      progressCenter.getItemById('format:/device/path').message);
+
+  await waitUntil(() => {
+    const item = progressCenter.getItemById('format:/device/path');
+    return !!item && item.message === 'FORMAT_PROGRESS_MESSAGE: label';
+  });
 
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'format_fail', devicePath: '/device/path', deviceLabel: 'label'});
-  assertEquals(1, progressCenter.getItemCount());
-  assertEquals(
-      'FORMAT_FAILURE_MESSAGE: label',
-      progressCenter.getItemById('format:/device/path').message);
+
+  await waitUntil(() => {
+    const item = progressCenter.getItemById('format:/device/path');
+    return !!item && item.message === 'FORMAT_FAILURE_MESSAGE: label';
+  });
+  done(/*error=*/ false);
 }
 
-export function testPartitionSucceeded() {
+export function testPartitionSucceeded(done) {
+  util.doIfPrimaryContext = async (fn) => {
+    await originalDoIfPrimaryContext(fn);
+    const itemCount = progressCenter.getItemCount();
+    if (itemCount !== 0) {
+      return reportError(
+          `Unexpected progress center item count got: ${itemCount} want: 0`,
+          done);
+    }
+    util.doIfPrimaryContext = async (fn) => {
+      await originalDoIfPrimaryContext(fn);
+      const itemCount = progressCenter.getItemCount();
+      if (itemCount !== 0) {
+        return reportError(
+            `Unexpected progress center item count got: ${itemCount} want: 0`,
+            done);
+      }
+      done(/*error=*/ itemCount !== 0);
+      return Promise.resolve(true);
+    };
+    // Second event: partition_success.
+    mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
+      type: 'partition_success',
+      devicePath: '/device/path',
+      deviceLabel: 'label'
+    });
+    return Promise.resolve(true);
+  };
+  // First event: partition_start.
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
     type: 'partition_start',
     devicePath: '/device/path',
     deviceLabel: 'label'
   });
-  assertEquals(0, progressCenter.getItemCount());
-
-  mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
-    type: 'partition_success',
-    devicePath: '/device/path',
-    deviceLabel: 'label'
-  });
-  assertEquals(0, progressCenter.getItemCount());
 }
 
-export function testPartitionFailed() {
+export function testPartitionFailed(done) {
+  util.doIfPrimaryContext = async (fn) => {
+    await originalDoIfPrimaryContext(fn);
+    const itemCount = progressCenter.getItemCount();
+    if (itemCount !== 0) {
+      return reportError(
+          `Unexpected progress center item count got: ${itemCount} want: 0`,
+          done);
+    }
+    util.doIfPrimaryContext = async (fn) => {
+      await originalDoIfPrimaryContext(fn);
+      // Second event callback handled. Check the progress center.
+      const itemCount = progressCenter.getItemCount();
+      if (itemCount !== 1) {
+        return reportError(
+            `Unexpected progress center item count got:${itemCount}, want 1`,
+            done);
+      }
+      const item = progressCenter.getItemById('partition:/device/path');
+      if (item.message !== 'FORMAT_FAILURE_MESSAGE: label') {
+        return reportError(`Unexpected item message "${item.message}"`, done);
+      }
+      done(/*error=*/ false);
+      return Promise.resolve(true);
+    };
+    // Second event
+    mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
+      type: 'partition_fail',
+      devicePath: '/device/path',
+      deviceLabel: 'label'
+    });
+    return Promise.resolve(true);
+  };
+
+  // First event.
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
     type: 'partition_start',
     devicePath: '/device/path',
     deviceLabel: 'label'
   });
-  assertEquals(0, progressCenter.getItemCount());
-
-  mockChrome.fileManagerPrivate.onDeviceChanged.dispatch({
-    type: 'partition_fail',
-    devicePath: '/device/path',
-    deviceLabel: 'label'
-  });
-  assertEquals(1, progressCenter.getItemCount());
-  assertEquals(
-      'FORMAT_FAILURE_MESSAGE: label',
-      progressCenter.getItemById('partition:/device/path').message);
 }
 
-export function testRenameSucceeded() {
+export function testRenameSucceeded(done) {
+  util.doIfPrimaryContext = async (fn) => {
+    await originalDoIfPrimaryContext(fn);
+    const keys = Object.keys(mockChrome.notifications.items);
+    if (keys.length !== 0) {
+      return reportError(`Unexpected keys ${keys}`, done);
+    }
+    util.doIfPrimaryContext = async (fn) => {
+      await originalDoIfPrimaryContext(fn);
+      const keys = Object.keys(mockChrome.notifications.items);
+      done(/*error=*/ keys.length !== 0);
+      return Promise.resolve(true);
+    };
+    mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
+        {type: 'rename_success', devicePath: '/device/path'});
+    return Promise.resolve(true);
+  };
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'rename_start', devicePath: '/device/path'});
-  assertEquals(0, Object.keys(mockChrome.notifications.items).length);
-
-  mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
-      {type: 'rename_success', devicePath: '/device/path'});
-  assertEquals(0, Object.keys(mockChrome.notifications.items).length);
 }
 
-export function testRenameFailed() {
+export async function testRenameFailed(done) {
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'rename_start', devicePath: '/device/path'});
+
+  // TODO(b/194246635): Fix this; async execution makes this check useless.
   assertEquals(0, Object.keys(mockChrome.notifications.items).length);
 
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'rename_fail', devicePath: '/device/path'});
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'RENAMING_OF_DEVICE_FINISHED_FAILURE_MESSAGE',
-      mockChrome.notifications.items['renameFail:/device/path'].message);
+
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['renameFail:/device/path'];
+    return item &&
+        item.message == 'RENAMING_OF_DEVICE_FINISHED_FAILURE_MESSAGE';
+  });
+  done(/*error=*/ false);
 }
 
-export function testDeviceHardUnplugged() {
+export async function testDeviceHardUnplugged(done) {
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'hard_unplugged', devicePath: '/device/path'});
-  assertEquals(1, Object.keys(mockChrome.notifications.items).length);
-  assertEquals(
-      'DEVICE_HARD_UNPLUGGED_MESSAGE',
-      mockChrome.notifications.items['hardUnplugged:/device/path'].message);
+
+  await waitUntil(() => {
+    const item = mockChrome.notifications.items['hardUnplugged:/device/path'];
+    return item && item.message === 'DEVICE_HARD_UNPLUGGED_MESSAGE';
+  });
+  done(/*error=*/ false);
 }
 
-export function testNotificationClicked(callback) {
+export function testNotificationClicked(done) {
   const devicePath = '/device/path';
   const notificationId = 'deviceNavigation:' + devicePath;
 
@@ -727,19 +822,30 @@
         assertEquals(devicePath, event.devicePath);
         assertEquals(null, event.filePath);
       }),
-      callback);
+      done);
 }
 
-export function testMiscMessagesInIncognito() {
+export function testMiscMessagesInIncognito(done) {
   setUpInIncognitoContext();
+
+  util.doIfPrimaryContext = async (fn) => {
+    await originalDoIfPrimaryContext(fn);
+    done(0 !== Object.keys(mockChrome.notifications.items).length);
+    return Promise.resolve(true);
+  };
   mockChrome.fileManagerPrivate.onDeviceChanged.dispatch(
       {type: 'format_start', devicePath: '/device/path', deviceLabel: 'label'});
-  // No notification sent by this instance in incognito context.
-  assertEquals(0, progressCenter.getItemCount());
 }
 
-export function testMountCompleteInIncognito() {
+export function testMountCompleteInIncognito(done) {
   setUpInIncognitoContext();
+
+  util.doIfPrimaryContext = async (fn) => {
+    await originalDoIfPrimaryContext(fn);
+    done(0 !== Object.keys(mockChrome.notifications.items).length);
+    return Promise.resolve(true);
+  };
+
   mockChrome.fileManagerPrivate.onMountCompleted.dispatch({
     eventType: 'mount',
     status: 'success',
@@ -751,12 +857,6 @@
     },
     shouldNotify: true
   });
-
-  assertEquals(0, Object.keys(mockChrome.notifications.items).length);
-  // TODO(yamaguchi): I think this test is incomplete.
-  // This looks as if notification is not generated yet because the promise
-  // is not settled yet. Same for testGoodDeviceNotNavigated.
-  assertFalse(mockChrome.notifications.resolver.settled);
 }
 
 /**
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index f30544f..94c11ec4 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -13,6 +13,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
 
+import {promisify} from '../../common/js/api.js';
 import {EntryLocation} from '../../externs/entry_location.js';
 import {FakeEntry, FilesAppEntry} from '../../externs/files_app_entry_interfaces.js';
 import {VolumeInfo} from '../../externs/volume_info.js';
@@ -1615,16 +1616,24 @@
 
 /**
  * Executes a functions only when the context is not the incognito one in a
- * regular session.
- * @param {function()} callback
+ * regular session. Returns a promise that when fulfilled informs us whether or
+ * not the callback was invoked.
+ * @param {function():void} callback
+ * @return {!Promise<boolean>}
  */
-util.doIfPrimaryContext = callback => {
-  chrome.fileManagerPrivate.getProfiles((profiles) => {
-    if ((profiles[0] && profiles[0].profileId == '$guest') ||
-        !chrome.extension.inIncognitoContext) {
+util.doIfPrimaryContext = async (callback) => {
+  const guestMode = await util.isInGuestMode();
+  if (guestMode) {
+    callback();
+    return true;
+  }
+  if (!window.isSWA) {
+    if (!chrome.extension.inIncognitoContext) {
       callback();
+      return true;
     }
-  });
+  }
+  return false;
 };
 
 /**
@@ -1830,4 +1839,18 @@
   return `${appId}|${taskType}|${actionId}`;
 };
 
+/**
+ * Returns a new promise which, when fulfilled carries a boolean indicating
+ * whether the app is in the guest mode. Typical use:
+ *
+ * util.isInGuestMode().then(
+ *     (guest) => { if (guest) { ... in guest mode } }
+ * );
+ * @return {Promise<boolean>}
+ */
+util.isInGuestMode = async () => {
+  const profiles = await promisify(chrome.fileManagerPrivate.getProfiles);
+  return profiles.length > 0 && profiles[0].profileId === '$guest';
+};
+
 export {util};
diff --git a/ui/file_manager/file_manager/externs/command_handler_deps.js b/ui/file_manager/file_manager/externs/command_handler_deps.js
index 015d9df..b223833 100644
--- a/ui/file_manager/file_manager/externs/command_handler_deps.js
+++ b/ui/file_manager/file_manager/externs/command_handler_deps.js
@@ -87,6 +87,9 @@
 
     /** @type {Crostini} */
     this.crostini;
+
+    /** @type {boolean} */
+    this.guestMode;
   }
 
   /** @return {DirectoryEntry|FilesAppEntry} */
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index bc0065e..54971b1 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -422,6 +422,12 @@
      * @private {?FakeEntry}
      */
     this.recentEntry_ = null;
+
+    /**
+     * Whether or not we are running in guest mode.
+     * @private {boolean}
+     */
+    this.guestMode_ = false;
   }
 
   /**
@@ -585,6 +591,13 @@
   }
 
   /**
+   * @return {boolean} If the app is running in the guest mode.
+   */
+  get guestMode() {
+    return this.guestMode_;
+  }
+
+  /**
    * Launch a new File Manager app.
    * @param {!FilesAppState=} appState App state.
    */
@@ -615,6 +628,23 @@
   }
 
   /**
+   * Updates guestMode_ field based on what the result of the util.isInGuestMode
+   * helper function. It errs on the side of not-in-guestmode, if the util
+   * function fails. The worse this causes are extra notifications.
+   */
+  async setGuestMode_() {
+    try {
+      const guest = await util.isInGuestMode();
+      if (guest !== null) {
+        this.guestMode_ = guest;
+      }
+    } catch (error) {
+      console.error(error);
+      // Leave this.guestMode_ as its initial value.
+    }
+  }
+
+  /**
    * One time initialization for the file system and related things.
    * @return {!Promise<void>}
    * @private
@@ -754,7 +784,8 @@
     this.ui_.decorateFilesMenuItems();
     this.ui_.selectionMenuButton.hidden = false;
 
-    await Promise.all([fileListPromise, currentDirectoryPromise]);
+    await Promise.all(
+        [fileListPromise, currentDirectoryPromise, this.setGuestMode_()]);
   }
 
   /**
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 3c4742a..e1d4a27 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -2912,9 +2912,15 @@
 
   /** @override */
   canExecute(event, fileManager) {
-    event.canExecute =
-        (fileManager.dialogType === DialogType.FULL_PAGE &&
-         !chrome.extension.inIncognitoContext);
+    if (fileManager.dialogType !== DialogType.FULL_PAGE) {
+      event.canExecute = false;
+    } else {
+      if (window.isSWA) {
+        event.canExecute = !fileManager.guestMode;
+      } else {
+        event.canExecute = !chrome.extension.inIncognitoContext;
+      }
+    }
   }
 };
 
diff --git a/ui/gfx/android/android_surface_control_compat.cc b/ui/gfx/android/android_surface_control_compat.cc
index 26f65b0f..a0da05f 100644
--- a/ui/gfx/android/android_surface_control_compat.cc
+++ b/ui/gfx/android/android_surface_control_compat.cc
@@ -5,6 +5,7 @@
 #include "ui/gfx/android/android_surface_control_compat.h"
 
 #include <android/data_space.h>
+#include <android/hdr_metadata.h>
 #include <dlfcn.h>
 
 #include "base/android/build_info.h"
@@ -97,6 +98,14 @@
     void (*)(ASurfaceTransaction* transaction,
              ASurfaceControl* surface,
              uint64_t data_space);
+using pASurfaceTransaction_setHdrMetadata_cta861_3 =
+    void (*)(ASurfaceTransaction* transaction,
+             ASurfaceControl* surface,
+             struct AHdrMetadata_cta861_3* metadata);
+using pASurfaceTransaction_setHdrMetadata_smpte2086 =
+    void (*)(ASurfaceTransaction* transaction,
+             ASurfaceControl* surface,
+             struct AHdrMetadata_smpte2086* metadata);
 using pASurfaceTransaction_setFrameRate =
     void (*)(ASurfaceTransaction* transaction,
              ASurfaceControl* surface_control,
@@ -230,6 +239,8 @@
     LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBufferTransparency);
     LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setDamageRegion);
     LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBufferDataSpace);
+    LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setHdrMetadata_cta861_3);
+    LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setHdrMetadata_smpte2086);
     LOAD_FUNCTION_MAYBE(main_dl_handle, ASurfaceTransaction_setFrameRate);
 
     LOAD_FUNCTION(main_dl_handle, ASurfaceTransactionStats_getPresentFenceFd);
@@ -268,6 +279,10 @@
   pASurfaceTransaction_setDamageRegion ASurfaceTransaction_setDamageRegionFn;
   pASurfaceTransaction_setBufferDataSpace
       ASurfaceTransaction_setBufferDataSpaceFn;
+  pASurfaceTransaction_setHdrMetadata_cta861_3
+      ASurfaceTransaction_setHdrMetadata_cta861_3Fn;
+  pASurfaceTransaction_setHdrMetadata_smpte2086
+      ASurfaceTransaction_setHdrMetadata_smpte2086Fn;
   pASurfaceTransaction_setFrameRate ASurfaceTransaction_setFrameRateFn;
 
   // TransactionStats methods.
@@ -311,6 +326,75 @@
   return ANATIVEWINDOW_TRANSFORM_IDENTITY;
 }
 
+// Remove this and use ADataSpace when SDK will roll. Note, this doesn't define
+// any new data spaces, just defines a primary(standard)/transfer/range
+// separately.
+enum DataSpace : uint64_t {
+  // Primaries
+  STANDARD_BT709 = 1 << 16,
+  STANDARD_BT601_625 = 2 << 16,
+  STANDARD_BT601_525 = 4 << 16,
+  STANDARD_BT2020 = 6 << 16,
+  // Transfer functions
+  TRANSFER_LINEAR = 1 << 22,
+  TRANSFER_SRGB = 2 << 22,
+  TRANSFER_SMPTE_170M = 3 << 22,
+  TRANSFER_ST2084 = 7 << 22,
+  TRANSFER_HLG = 8 << 22,
+  // Ranges;
+  RANGE_FULL = 1 << 27,
+  RANGE_LIMITED = 2 << 27,
+
+  ADATASPACE_DCI_P3 = 155844608
+};
+
+absl::optional<uint64_t> GetDataSpaceStandard(
+    const gfx::ColorSpace& color_space) {
+  switch (color_space.GetPrimaryID()) {
+    case gfx::ColorSpace::PrimaryID::BT709:
+      return DataSpace::STANDARD_BT709;
+    case gfx::ColorSpace::PrimaryID::BT470BG:
+      return DataSpace::STANDARD_BT601_625;
+    case gfx::ColorSpace::PrimaryID::SMPTE170M:
+      return DataSpace::STANDARD_BT601_525;
+    case gfx::ColorSpace::PrimaryID::BT2020:
+      return DataSpace::STANDARD_BT2020;
+    default:
+      return absl::nullopt;
+  }
+}
+
+absl::optional<uint64_t> GetDataSpaceTransfer(
+    const gfx::ColorSpace& color_space) {
+  switch (color_space.GetTransferID()) {
+    case gfx::ColorSpace::TransferID::SMPTE170M:
+      return DataSpace::TRANSFER_SMPTE_170M;
+    case gfx::ColorSpace::TransferID::LINEAR_HDR:
+      return DataSpace::TRANSFER_LINEAR;
+    case gfx::ColorSpace::TransferID::SMPTEST2084:
+      return DataSpace::TRANSFER_ST2084;
+    case gfx::ColorSpace::TransferID::ARIB_STD_B67:
+      return DataSpace::TRANSFER_HLG;
+    // We use SRGB for BT709. See |ColorSpace::GetTransferFunction()| for
+    // details.
+    case gfx::ColorSpace::TransferID::BT709:
+      return DataSpace::TRANSFER_SRGB;
+    default:
+      return absl::nullopt;
+  }
+}
+
+absl::optional<uint64_t> GetDataSpaceRange(const gfx::ColorSpace& color_space) {
+  switch (color_space.GetRangeID()) {
+    case gfx::ColorSpace::RangeID::FULL:
+      return DataSpace::RANGE_FULL;
+    case gfx::ColorSpace::RangeID::LIMITED:
+      return DataSpace::RANGE_LIMITED;
+    default:
+      return absl::nullopt;
+  };
+}
+
 uint64_t ColorSpaceToADataSpace(const gfx::ColorSpace& color_space) {
   if (!color_space.IsValid() || color_space == gfx::ColorSpace::CreateSRGB())
     return ADATASPACE_SRGB;
@@ -321,8 +405,17 @@
   if (color_space == gfx::ColorSpace::CreateDisplayP3D65())
     return ADATASPACE_DISPLAY_P3;
 
-  // TODO(khushalsagar): Check if we can support BT2020 using
-  // ADATASPACE_BT2020_PQ.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+      base::android::SDK_VERSION_S) {
+    auto standard = GetDataSpaceStandard(color_space);
+    auto transfer = GetDataSpaceTransfer(color_space);
+    auto range = GetDataSpaceRange(color_space);
+
+    // Data space is set of the flags, so check if all components are valid.
+    if (standard && transfer && range)
+      return standard.value() | transfer.value() | range.value();
+  }
+
   return ADATASPACE_UNKNOWN;
 }
 
@@ -621,6 +714,44 @@
       transaction_, surface.surface(), data_space);
 }
 
+void SurfaceControl::Transaction::SetHDRMetadata(
+
+    const Surface& surface,
+    const absl::optional<HDRMetadata>& metadata) {
+  if (metadata) {
+    AHdrMetadata_cta861_3 cta861_3 = {
+        .maxContentLightLevel =
+            static_cast<float>(metadata->max_content_light_level),
+        .maxFrameAverageLightLevel =
+            static_cast<float>(metadata->max_frame_average_light_level)};
+
+    AHdrMetadata_smpte2086 smpte2086 = {
+        .displayPrimaryRed =
+            {.x = metadata->color_volume_metadata.primary_r.x(),
+             .y = metadata->color_volume_metadata.primary_r.y()},
+        .displayPrimaryGreen =
+            {.x = metadata->color_volume_metadata.primary_g.x(),
+             .y = metadata->color_volume_metadata.primary_g.y()},
+        .displayPrimaryBlue =
+            {.x = metadata->color_volume_metadata.primary_b.x(),
+             .y = metadata->color_volume_metadata.primary_b.y()},
+        .whitePoint = {.x = metadata->color_volume_metadata.white_point.x(),
+                       .y = metadata->color_volume_metadata.white_point.y()},
+        .maxLuminance = metadata->color_volume_metadata.luminance_max,
+        .minLuminance = metadata->color_volume_metadata.luminance_min};
+
+    SurfaceControlMethods::Get().ASurfaceTransaction_setHdrMetadata_cta861_3Fn(
+        transaction_, surface.surface(), &cta861_3);
+    SurfaceControlMethods::Get().ASurfaceTransaction_setHdrMetadata_smpte2086Fn(
+        transaction_, surface.surface(), &smpte2086);
+  } else {
+    SurfaceControlMethods::Get().ASurfaceTransaction_setHdrMetadata_cta861_3Fn(
+        transaction_, surface.surface(), nullptr);
+    SurfaceControlMethods::Get().ASurfaceTransaction_setHdrMetadata_smpte2086Fn(
+        transaction_, surface.surface(), nullptr);
+  }
+}
+
 void SurfaceControl::Transaction::SetFrameRate(const Surface& surface,
                                                float frame_rate) {
   DCHECK(SupportsSetFrameRate());
diff --git a/ui/gfx/android/android_surface_control_compat.h b/ui/gfx/android/android_surface_control_compat.h
index 7aa0c71..77428bc 100644
--- a/ui/gfx/android/android_surface_control_compat.h
+++ b/ui/gfx/android/android_surface_control_compat.h
@@ -14,8 +14,10 @@
 #include "base/files/scoped_file.h"
 #include "base/memory/ref_counted.h"
 #include "base/task/single_thread_task_runner.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/gfx_export.h"
+#include "ui/gfx/hdr_metadata.h"
 #include "ui/gfx/overlay_transform.h"
 
 extern "C" {
@@ -139,6 +141,8 @@
     void SetDamageRect(const Surface& surface, const gfx::Rect& rect);
     void SetColorSpace(const Surface& surface,
                        const gfx::ColorSpace& color_space);
+    void SetHDRMetadata(const Surface& surface,
+                        const absl::optional<HDRMetadata>& hdr_metadata);
     void SetFrameRate(const Surface& surface, float frame_rate);
     void SetParent(const Surface& surface, Surface* new_parent);
     void SetPosition(const Surface& surface, const gfx::Point& position);
diff --git a/ui/gfx/hdr_metadata.h b/ui/gfx/hdr_metadata.h
index 5fc0319..c06f9e2 100644
--- a/ui/gfx/hdr_metadata.h
+++ b/ui/gfx/hdr_metadata.h
@@ -58,6 +58,8 @@
         (max_frame_average_light_level == rhs.max_frame_average_light_level) &&
         (color_volume_metadata == rhs.color_volume_metadata));
   }
+
+  bool operator!=(const HDRMetadata& rhs) const { return !(*this == rhs); }
 };
 
 // HDR metadata types as described in
diff --git a/ui/gfx/image/image_mac.mm b/ui/gfx/image/image_mac.mm
index 71d8bf3..939099f 100644
--- a/ui/gfx/image/image_mac.mm
+++ b/ui/gfx/image/image_mac.mm
@@ -35,14 +35,13 @@
 
 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
     NSImage* nsimage) {
-  // TODO(crbug.com/1253882): Remove this once the root cause has been found.
-  CHECK(nsimage);
+  DCHECK(nsimage);
   CGImageRef cg_image = [nsimage CGImageForProposedRect:NULL
                                                 context:nil
                                                   hints:nil];
-  // TODO(crbug.com/1253882): Remove this once the root cause has been found.
   if (!cg_image) {
-    base::debug::DumpWithoutCrashing();
+    // TODO(crbug.com/1271762): Look at DumpWithoutCrashing() reports to figure
+    // out what's going on here.
     return scoped_refptr<base::RefCountedMemory>();
   }
   base::scoped_nsobject<NSBitmapImageRep> ns_bitmap(
diff --git a/ui/gl/gl_surface_egl_surface_control.cc b/ui/gl/gl_surface_egl_surface_control.cc
index 34f31ec..5c6787a 100644
--- a/ui/gl/gl_surface_egl_surface_control.cc
+++ b/ui/gl/gl_surface_egl_surface_control.cc
@@ -450,6 +450,15 @@
                                         image_color_space);
   }
 
+  if (uninitialized ||
+      surface_state.hdr_metadata != overlay_plane_data.hdr_metadata) {
+    DCHECK(!overlay_plane_data.hdr_metadata ||
+           surface_state.color_space.IsHDR());
+    surface_state.hdr_metadata = overlay_plane_data.hdr_metadata;
+    pending_transaction_->SetHDRMetadata(*surface_state.surface,
+                                         surface_state.hdr_metadata);
+  }
+
   if (frame_rate_update_pending_)
     pending_transaction_->SetFrameRate(*surface_state.surface, frame_rate_);
 
diff --git a/ui/gl/gl_surface_egl_surface_control.h b/ui/gl/gl_surface_egl_surface_control.h
index 49bb65eb..2bb7515c 100644
--- a/ui/gl/gl_surface_egl_surface_control.h
+++ b/ui/gl/gl_surface_egl_surface_control.h
@@ -102,6 +102,7 @@
     gfx::OverlayTransform transform = gfx::OVERLAY_TRANSFORM_NONE;
     bool opaque = true;
     gfx::ColorSpace color_space;
+    absl::optional<gfx::HDRMetadata> hdr_metadata;
 
     // Indicates whether buffer for this layer was updated in the currently
     // pending transaction, or the last transaction submitted if there isn't
diff --git a/ui/lottie/DEPS b/ui/lottie/DEPS
index 24f1389..596063a 100644
--- a/ui/lottie/DEPS
+++ b/ui/lottie/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+cc/paint",
+  "+cc/test",
   "+third_party/skia",
   "+ui/gfx",
 ]
diff --git a/ui/lottie/OWNERS b/ui/lottie/OWNERS
new file mode 100644
index 0000000..55477237
--- /dev/null
+++ b/ui/lottie/OWNERS
@@ -0,0 +1,2 @@
+amusbach@chromium.org
+fmalita@chromium.org
diff --git a/ui/lottie/animation.cc b/ui/lottie/animation.cc
index a4de151..d92eb403 100644
--- a/ui/lottie/animation.cc
+++ b/ui/lottie/animation.cc
@@ -4,12 +4,14 @@
 
 #include "ui/lottie/animation.h"
 
+#include "base/bind.h"
+#include "base/check.h"
 #include "base/trace_event/trace_event.h"
-#include "cc/paint/skottie_frame_data.h"
 #include "cc/paint/skottie_wrapper.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkSamplingOptions.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/skia_conversions.h"
@@ -67,8 +69,27 @@
   return end_offset_ / total_duration_;
 }
 
-Animation::Animation(scoped_refptr<cc::SkottieWrapper> skottie)
-    : skottie_(skottie) {}
+Animation::Animation(scoped_refptr<cc::SkottieWrapper> skottie,
+                     cc::SkottieFrameDataProvider* frame_data_provider)
+    : skottie_(skottie) {
+  DCHECK(skottie_);
+  bool animation_has_image_assets =
+      !skottie_->GetImageAssetMetadata().asset_storage().empty();
+  if (animation_has_image_assets) {
+    DCHECK(frame_data_provider)
+        << "SkottieFrameDataProvider required for animations with image assets";
+    for (const auto& asset_metadata :
+         skottie_->GetImageAssetMetadata().asset_storage()) {
+      const std::string& asset_id = asset_metadata.first;
+      const base::FilePath& asset_path = asset_metadata.second;
+      scoped_refptr<cc::SkottieFrameDataProvider::ImageAsset> new_asset =
+          frame_data_provider->LoadImageAsset(asset_id, asset_path);
+      DCHECK(new_asset);
+      image_assets_.emplace(cc::HashSkottieResourceId(asset_id),
+                            std::move(new_asset));
+    }
+  }
+}
 
 Animation::~Animation() = default;
 
@@ -199,7 +220,35 @@
                            const gfx::Size& size) {
   DCHECK_GE(t, 0.f);
   DCHECK_LE(t, 1.f);
-  canvas->DrawSkottie(skottie(), gfx::Rect(size), t, cc::SkottieFrameDataMap());
+  // Not all of the image assets necessarily appear in the frame at time |t|. To
+  // determine which assets are actually needed, Seek() and capture the set of
+  // images in the frame. Seek() without rendering is a cheap operation.
+  cc::SkottieFrameDataMap all_frame_data;
+  // Using Unretained is safe because the callback is guaranteed to be invoked
+  // synchronously within Seek().
+  skottie_->Seek(t, base::BindRepeating(&Animation::LoadImageForAsset,
+                                        base::Unretained(this), canvas,
+                                        std::ref(all_frame_data)));
+  canvas->DrawSkottie(skottie(), gfx::Rect(size), t, std::move(all_frame_data));
+}
+
+cc::SkottieWrapper::FrameDataFetchResult Animation::LoadImageForAsset(
+    gfx::Canvas* canvas,
+    cc::SkottieFrameDataMap& all_frame_data,
+    cc::SkottieResourceIdHash asset_id,
+    float t,
+    sk_sp<SkImage>&,
+    SkSamplingOptions&) {
+  cc::SkottieFrameDataProvider::ImageAsset& image_asset =
+      *image_assets_.at(asset_id);
+  absl::optional<cc::SkottieFrameData> frame_data =
+      image_asset.GetFrameData(t, canvas->image_scale());
+  if (frame_data) {
+    all_frame_data.emplace(asset_id, std::move(frame_data.value()));
+  }
+  // Since this callback is only used for Seek() and not rendering, the output
+  // arguments can be ignored and NO_UPDATE can be returned.
+  return cc::SkottieWrapper::FrameDataFetchResult::NO_UPDATE;
 }
 
 void Animation::InitTimer(const base::TimeTicks& timestamp) {
diff --git a/ui/lottie/animation.h b/ui/lottie/animation.h
index 2535095..38d0657 100644
--- a/ui/lottie/animation.h
+++ b/ui/lottie/animation.h
@@ -5,17 +5,26 @@
 #ifndef UI_LOTTIE_ANIMATION_H_
 #define UI_LOTTIE_ANIMATION_H_
 
+#include <functional>
 #include <memory>
 
 #include "base/component_export.h"
+#include "base/containers/flat_map.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
+#include "cc/paint/skottie_frame_data.h"
+#include "cc/paint/skottie_frame_data_provider.h"
+#include "cc/paint/skottie_resource_metadata.h"
 #include "cc/paint/skottie_wrapper.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkStream.h"
 #include "third_party/skia/modules/skottie/include/Skottie.h"
 #include "ui/gfx/geometry/size.h"
 
+class SkImage;
+struct SkSamplingOptions;
+
 namespace gfx {
 class Canvas;
 }  // namespace gfx
@@ -81,7 +90,11 @@
     kLoop         // Same as LINEAR, except the animation repeats after it ends.
   };
 
-  explicit Animation(scoped_refptr<cc::SkottieWrapper> skottie);
+  // |frame_data_provider| may be null if it's known that the incoming skottie
+  // animation does not contain any image assets.
+  explicit Animation(
+      scoped_refptr<cc::SkottieWrapper> skottie,
+      cc::SkottieFrameDataProvider* frame_data_provider = nullptr);
   Animation(const Animation&) = delete;
   Animation& operator=(const Animation&) = delete;
   ~Animation();
@@ -215,6 +228,13 @@
 
   void InitTimer(const base::TimeTicks& timestamp);
   void UpdateState(const base::TimeTicks& timestamp);
+  cc::SkottieWrapper::FrameDataFetchResult LoadImageForAsset(
+      gfx::Canvas* canvas,
+      cc::SkottieFrameDataMap& all_frame_data,
+      cc::SkottieResourceIdHash asset_id,
+      float t,
+      sk_sp<SkImage>&,
+      SkSamplingOptions&);
 
   // Manages the timeline for the current playing animation.
   std::unique_ptr<TimerControl> timer_control_;
@@ -233,6 +253,9 @@
   AnimationObserver* observer_ = nullptr;
 
   scoped_refptr<cc::SkottieWrapper> skottie_;
+  base::flat_map<cc::SkottieResourceIdHash,
+                 scoped_refptr<cc::SkottieFrameDataProvider::ImageAsset>>
+      image_assets_;
 };
 
 }  // namespace lottie
diff --git a/ui/lottie/animation_unittest.cc b/ui/lottie/animation_unittest.cc
index ceade949..8df5c98 100644
--- a/ui/lottie/animation_unittest.cc
+++ b/ui/lottie/animation_unittest.cc
@@ -4,21 +4,45 @@
 
 #include "ui/lottie/animation.h"
 
+#include <map>
 #include <string>
 
+#include "base/check.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "cc/paint/display_item_list.h"
+#include "cc/paint/paint_op_buffer.h"
+#include "cc/paint/paint_record.h"
+#include "cc/paint/record_paint_canvas.h"
+#include "cc/paint/skottie_frame_data.h"
+#include "cc/paint/skottie_frame_data_provider.h"
+#include "cc/paint/skottie_resource_metadata.h"
 #include "cc/paint/skottie_wrapper.h"
+#include "cc/test/lottie_test_data.h"
+#include "cc/test/skia_common.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkStream.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/lottie/animation_observer.h"
 
 namespace lottie {
 namespace {
 
+using ::testing::Eq;
+using ::testing::FloatEq;
+using ::testing::FloatNear;
+using ::testing::IsEmpty;
+using ::testing::NotNull;
+using ::testing::Pair;
+using ::testing::SizeIs;
+using ::testing::UnorderedElementsAre;
+
 // A skottie animation with solid green color for the first 2.5 seconds and then
 // a solid blue color for the next 2.5 seconds.
 constexpr char kData[] =
@@ -53,6 +77,8 @@
 constexpr float kAnimationWidth = 400.f;
 constexpr float kAnimationHeight = 200.f;
 constexpr auto kAnimationDuration = base::Seconds(5);
+constexpr float kCanvasImageScale = 2.f;
+constexpr float kFrameTimestampToleranceSec = 0.1f;
 
 class TestAnimationObserver : public AnimationObserver {
  public:
@@ -91,6 +117,65 @@
   bool animation_resuming_ = false;
 };
 
+class TestSkottieFrameDataProvider : public cc::SkottieFrameDataProvider {
+ public:
+  class ImageAssetImpl : public cc::SkottieFrameDataProvider::ImageAsset {
+   public:
+    ImageAssetImpl() = default;
+    ImageAssetImpl(const ImageAssetImpl& other) = delete;
+    ImageAssetImpl& operator=(const ImageAssetImpl& other) = delete;
+
+    absl::optional<cc::SkottieFrameData> GetFrameData(
+        float t,
+        float scale_factor) override {
+      last_frame_t_ = t;
+      last_frame_scale_factor_ = scale_factor;
+      return current_frame_data_;
+    }
+
+    void set_current_frame_data(
+        absl::optional<cc::SkottieFrameData> current_frame_data) {
+      current_frame_data_ = std::move(current_frame_data);
+    }
+
+    const absl::optional<float>& last_frame_t() const { return last_frame_t_; }
+    const absl::optional<float>& last_frame_scale_factor() const {
+      return last_frame_scale_factor_;
+    }
+
+   private:
+    friend class TestSkottieFrameDataProvider;
+
+    ~ImageAssetImpl() override = default;
+
+    absl::optional<cc::SkottieFrameData> current_frame_data_;
+    absl::optional<float> last_frame_t_;
+    absl::optional<float> last_frame_scale_factor_;
+  };
+
+  TestSkottieFrameDataProvider() = default;
+  TestSkottieFrameDataProvider(const TestSkottieFrameDataProvider&) = delete;
+  TestSkottieFrameDataProvider& operator=(const TestSkottieFrameDataProvider&) =
+      delete;
+  ~TestSkottieFrameDataProvider() override = default;
+
+  scoped_refptr<ImageAsset> LoadImageAsset(
+      base::StringPiece resource_id,
+      const base::FilePath& resource_path) override {
+    auto new_asset = base::MakeRefCounted<ImageAssetImpl>();
+    CHECK(current_assets_.emplace(std::string(resource_id), new_asset).second);
+    return new_asset;
+  }
+
+  ImageAssetImpl* GetLoadedImageAsset(const std::string& resource_id) {
+    auto iter = current_assets_.find(resource_id);
+    return iter == current_assets_.end() ? nullptr : iter->second.get();
+  }
+
+ private:
+  std::map<std::string, scoped_refptr<ImageAssetImpl>> current_assets_;
+};
+
 }  // namespace
 
 class AnimationTest : public testing::Test {
@@ -186,14 +271,46 @@
   }
 
  protected:
+  std::unique_ptr<gfx::Canvas> canvas_;
   std::unique_ptr<Animation> animation_;
   scoped_refptr<cc::SkottieWrapper> skottie_;
 
  private:
-  std::unique_ptr<gfx::Canvas> canvas_;
   base::SimpleTestTickClock test_clock_;
 };
 
+class AnimationWithImageAssetsTest : public AnimationTest {
+ protected:
+  AnimationWithImageAssetsTest()
+      : display_list_(base::MakeRefCounted<cc::DisplayItemList>(
+            cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)),
+        record_canvas_(display_list_.get(),
+                       SkRect::MakeIWH(cc::kLottieDataWith2AssetsWidth,
+                                       cc::kLottieDataWith2AssetsHeight)) {}
+
+  void SetUp() override {
+    canvas_ = std::make_unique<gfx::Canvas>(&record_canvas_, kCanvasImageScale);
+    skottie_ = cc::CreateSkottieFromString(cc::kLottieDataWith2Assets);
+    animation_ = std::make_unique<Animation>(skottie_, &frame_data_provider_);
+    asset_0_ = frame_data_provider_.GetLoadedImageAsset("image_0");
+    asset_1_ = frame_data_provider_.GetLoadedImageAsset("image_1");
+    ASSERT_THAT(asset_0_, NotNull());
+    ASSERT_THAT(asset_1_, NotNull());
+  }
+
+  cc::SkottieFrameData CreateHighQualityTestFrameData() {
+    return {
+        .image = cc::CreateDiscardablePaintImage(animation_->GetOriginalSize()),
+        .quality = cc::PaintFlags::FilterQuality::kHigh};
+  }
+
+  const scoped_refptr<cc::DisplayItemList> display_list_;
+  cc::RecordPaintCanvas record_canvas_;
+  TestSkottieFrameDataProvider frame_data_provider_;
+  TestSkottieFrameDataProvider::ImageAssetImpl* asset_0_;
+  TestSkottieFrameDataProvider::ImageAssetImpl* asset_1_;
+};
+
 TEST_F(AnimationTest, InitializationAndLoadingData) {
   skottie_ = cc::SkottieWrapper::CreateNonSerializable(
       base::as_bytes(base::make_span(kData, std::strlen(kData))));
@@ -829,4 +946,140 @@
   IsAllSameColor(SK_ColorBLUE, canvas.GetBitmap());
 }
 
+TEST_F(AnimationWithImageAssetsTest, PaintsAnimationImagesToCanvas) {
+  AdvanceClock(base::Milliseconds(300));
+
+  animation_->Start(Animation::Style::kLoop);
+
+  TestSkottieFrameDataProvider::ImageAssetImpl* asset_0 =
+      frame_data_provider_.GetLoadedImageAsset("image_0");
+  TestSkottieFrameDataProvider::ImageAssetImpl* asset_1 =
+      frame_data_provider_.GetLoadedImageAsset("image_1");
+  ASSERT_THAT(asset_0, NotNull());
+  ASSERT_THAT(asset_1, NotNull());
+
+  cc::SkottieFrameData frame_0 = CreateHighQualityTestFrameData();
+  cc::SkottieFrameData frame_1 = CreateHighQualityTestFrameData();
+  asset_0->set_current_frame_data(frame_0);
+  asset_1->set_current_frame_data(frame_1);
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+
+  sk_sp<cc::PaintRecord> paint_record = display_list_->ReleaseAsRecord();
+  ASSERT_THAT(paint_record, NotNull());
+  ASSERT_THAT(paint_record->size(), Eq(1u));
+  const cc::DrawSkottieOp* op =
+      paint_record->GetOpAtForTesting<cc::DrawSkottieOp>(0);
+  ASSERT_THAT(op, NotNull());
+  EXPECT_THAT(op->images, UnorderedElementsAre(Pair(
+                              cc::HashSkottieResourceId("image_0"), frame_0)));
+
+  AdvanceClock(animation_->GetAnimationDuration() * .75);
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+
+  paint_record = display_list_->ReleaseAsRecord();
+  ASSERT_THAT(paint_record, NotNull());
+  ASSERT_THAT(paint_record->size(), Eq(1u));
+  op = paint_record->GetOpAtForTesting<cc::DrawSkottieOp>(0);
+  ASSERT_THAT(op, NotNull());
+  EXPECT_THAT(op->images, UnorderedElementsAre(Pair(
+                              cc::HashSkottieResourceId("image_1"), frame_1)));
+}
+
+TEST_F(AnimationWithImageAssetsTest, SkipsNullAnimationImages) {
+  AdvanceClock(base::Milliseconds(300));
+
+  animation_->Start(Animation::Style::kLoop);
+
+  asset_0_->set_current_frame_data(CreateHighQualityTestFrameData());
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+  display_list_->ReleaseAsRecord();
+
+  AdvanceClock(animation_->GetAnimationDuration() / 4);
+
+  asset_0_->set_current_frame_data(absl::nullopt);
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+  sk_sp<cc::PaintRecord> paint_record = display_list_->ReleaseAsRecord();
+  ASSERT_THAT(paint_record, NotNull());
+  ASSERT_THAT(paint_record->size(), Eq(1u));
+  const cc::DrawSkottieOp* op =
+      paint_record->GetOpAtForTesting<cc::DrawSkottieOp>(0);
+  ASSERT_THAT(op, NotNull());
+  EXPECT_THAT(op->images, IsEmpty());
+}
+
+TEST_F(AnimationWithImageAssetsTest, LoadsCorrectFrameTimestamp) {
+  AdvanceClock(base::Milliseconds(300));
+
+  animation_->Start(Animation::Style::kLoop);
+
+  asset_0_->set_current_frame_data(CreateHighQualityTestFrameData());
+  asset_1_->set_current_frame_data(CreateHighQualityTestFrameData());
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+
+  ASSERT_TRUE(asset_0_->last_frame_t().has_value());
+  EXPECT_THAT(asset_0_->last_frame_t().value(), FloatEq(0));
+
+  base::TimeDelta three_quarter_duration =
+      animation_->GetAnimationDuration() * .75;
+  AdvanceClock(three_quarter_duration);
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+
+  // The timestamp is "relative to the image layer timeline origin" (see
+  // SkResources.h). The test animation used in this case has 2 layers for the
+  // first and second halves of the animation. So the 3/4 point of the animation
+  // is half way into the second layer, or 1/4 the duration of the whole
+  // animation.
+  base::TimeDelta half_duration = animation_->GetAnimationDuration() * .5;
+  ASSERT_TRUE(asset_1_->last_frame_t().has_value());
+  EXPECT_THAT(asset_1_->last_frame_t().value(),
+              FloatNear((three_quarter_duration - half_duration).InSecondsF(),
+                        kFrameTimestampToleranceSec));
+
+  AdvanceClock(half_duration);
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+
+  base::TimeDelta quarter_duration = animation_->GetAnimationDuration() / 4;
+  ASSERT_TRUE(asset_0_->last_frame_t().has_value());
+  EXPECT_THAT(
+      asset_0_->last_frame_t().value(),
+      FloatNear(quarter_duration.InSecondsF(), kFrameTimestampToleranceSec));
+}
+
+TEST_F(AnimationWithImageAssetsTest, LoadsCorrectImageScale) {
+  AdvanceClock(base::Milliseconds(300));
+
+  animation_->Start(Animation::Style::kLoop);
+
+  asset_0_->set_current_frame_data(CreateHighQualityTestFrameData());
+
+  display_list_->StartPaint();
+  animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+  display_list_->EndPaintOfUnpaired(gfx::Rect(animation_->GetOriginalSize()));
+
+  ASSERT_TRUE(asset_0_->last_frame_scale_factor().has_value());
+  EXPECT_THAT(asset_0_->last_frame_scale_factor().value(),
+              FloatEq(kCanvasImageScale));
+}
+
 }  // namespace lottie
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
index 2a7eafbe..f2f289c 100644
--- a/ui/ozone/platform/wayland/host/wayland_clipboard.cc
+++ b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -45,10 +45,9 @@
   // Synchronously retrieves the mime types list currently available to be read.
   virtual std::vector<std::string> ReadMimeTypes() = 0;
 
-  // Asynchronously reads clipboard content with |mime_type| format. The result
-  // data is expected to be delivered through |callback|.
-  virtual bool Read(const std::string& mime_type,
-                    ui::PlatformClipboard::RequestDataClosure callback) = 0;
+  // Synchronously reads and returns clipboard content with |mime_type| format.
+  // TODO(crbug.com/443355): Drop once Clipboard API becomes async.
+  virtual ui::PlatformClipboard::Data Read(const std::string& mime_type) = 0;
 
   // Synchronously stores and announces |data| as available from this clipboard.
   virtual void Write(const ui::PlatformClipboard::DataMap* data) = 0;
@@ -81,10 +80,8 @@
   ClipboardImpl(const ClipboardImpl&) = delete;
   ClipboardImpl& operator=(const ClipboardImpl&) = delete;
 
-  bool Read(const std::string& mime_type,
-            ui::PlatformClipboard::RequestDataClosure callback) final {
-    return GetDevice()->ReadSelectionData(GetMimeTypeForRequest(mime_type),
-                                          std::move(callback));
+  ui::PlatformClipboard::Data Read(const std::string& mime_type) final {
+    return GetDevice()->ReadSelectionData(GetMimeTypeForRequest(mime_type));
   }
 
   std::vector<std::string> ReadMimeTypes() final {
@@ -190,6 +187,7 @@
 }  // namespace wl
 
 namespace ui {
+
 WaylandClipboard::WaylandClipboard(WaylandConnection* connection,
                                    WaylandDataDeviceManager* manager)
     : connection_(connection),
@@ -217,10 +215,19 @@
     ClipboardBuffer buffer,
     const std::string& mime_type,
     PlatformClipboard::RequestDataClosure callback) {
+  PlatformClipboard::Data data;
   if (auto* clipboard = GetClipboard(buffer))
-    clipboard->Read(mime_type, std::move(callback));
-  else
-    std::move(callback).Run(nullptr);
+    data = clipboard->Read(mime_type);
+  std::move(callback).Run(data);
+}
+
+void WaylandClipboard::GetAvailableMimeTypes(
+    ClipboardBuffer buffer,
+    PlatformClipboard::GetMimeTypesClosure callback) {
+  std::vector<std::string> mime_types;
+  if (auto* clipboard = GetClipboard(buffer))
+    mime_types = clipboard->ReadMimeTypes();
+  std::move(callback).Run(mime_types);
 }
 
 bool WaylandClipboard::IsSelectionOwner(ClipboardBuffer buffer) {
@@ -236,15 +243,6 @@
     selection_clipboard->SetClipboardDataChangedCallback(data_changed_callback);
 }
 
-void WaylandClipboard::GetAvailableMimeTypes(
-    ClipboardBuffer buffer,
-    PlatformClipboard::GetMimeTypesClosure callback) {
-  std::vector<std::string> mime_types;
-  if (auto* clipboard = GetClipboard(buffer))
-    mime_types = clipboard->ReadMimeTypes();
-  std::move(callback).Run(mime_types);
-}
-
 bool WaylandClipboard::IsSelectionBufferAvailable() const {
   return (connection_->zwp_primary_selection_device_manager() != nullptr) ||
          (connection_->gtk_primary_selection_device_manager() != nullptr);
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc b/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
index fb7192b..fbfc16f 100644
--- a/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
+#include "base/test/bind.h"
 #include "base/test/mock_callback.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -23,6 +24,7 @@
 #include "ui/base/clipboard/clipboard_constants.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/ozone/platform/wayland/host/wayland_clipboard.h"
+#include "ui/ozone/platform/wayland/host/wayland_connection_test_api.h"
 #include "ui/ozone/platform/wayland/test/mock_surface.h"
 #include "ui/ozone/platform/wayland/test/test_data_device.h"
 #include "ui/ozone/platform/wayland/test/test_data_device_manager.h"
@@ -60,6 +62,20 @@
   void SetUp() override {
     WaylandTest::SetUp();
 
+    // As of now, WaylandClipboard::RequestClipboardData is implemented in a
+    // blocking way, which requires a roundtrip before attempting the data
+    // from the selection fd. As Wayland events polling is single-threaded for
+    // tests, WaylandConnection's roundtrip implementation must be hooked up
+    // here to make sure that the required test compositor calls are done,
+    // otherwise tests will enter in a dead lock.
+    // TODO(crbug.com/443355): Remove once Clipboard API becomes async.
+    WaylandConnectionTestApi(connection_.get())
+        .SetRoundtripClosure(base::BindLambdaForTesting([&]() {
+          wl_display_flush(connection_->display());
+          Sync();
+          base::ThreadPoolInstance::Get()->FlushForTesting();
+        }));
+
     clipboard_ = connection_->clipboard();
     ASSERT_TRUE(clipboard_);
   }
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 15f3d5a..e011b8b 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -282,6 +282,11 @@
 }
 
 void WaylandConnection::RoundTripQueue() {
+  if (roundtrip_closure_for_testing_) {
+    roundtrip_closure_for_testing_.Run();
+    return;
+  }
+
   DCHECK(event_queue_.get());
   wl_display_roundtrip_queue(display(), event_queue_.get());
 }
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
index 9674af80..2b0fa909 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/containers/flat_map.h"
 #include "base/time/time.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -456,6 +457,8 @@
   // Global Wayland interfaces available in the current session, with their
   // versions.
   std::vector<std::pair<std::string, uint32_t>> available_globals_;
+
+  base::RepeatingClosure roundtrip_closure_for_testing_;
 };
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_connection_test_api.h b/ui/ozone/platform/wayland/host/wayland_connection_test_api.h
index 24edbee..1013067 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection_test_api.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection_test_api.h
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
 
 namespace ui {
 
@@ -26,6 +27,10 @@
     impl_->zcr_cursor_shapes_ = std::move(obj);
   }
 
+  void SetRoundtripClosure(base::RepeatingClosure closure) {
+    impl_->roundtrip_closure_for_testing_ = closure;
+  }
+
  private:
   WaylandConnection* const impl_;
 };
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device_base.cc b/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
index 9356905..43044c5 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
@@ -10,12 +10,11 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/task/task_traits.h"
-#include "base/task/thread_pool.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 #include "ui/ozone/platform/wayland/host/wayland_data_offer_base.h"
 #include "ui/ozone/platform/wayland/host/wayland_serial_tracker.h"
+#include "wayland-client-core.h"
 
 namespace ui {
 
@@ -34,33 +33,23 @@
   return data_offer_->mime_types();
 }
 
-bool WaylandDataDeviceBase::ReadSelectionData(
-    const std::string& mime_type,
-    PlatformClipboard::RequestDataClosure callback) {
-  DCHECK(callback);
-  if (!data_offer_) {
-    std::move(callback).Run(nullptr);
-    return false;
-  }
+PlatformClipboard::Data WaylandDataDeviceBase::ReadSelectionData(
+    const std::string& mime_type) {
+  if (!data_offer_)
+    return {};
 
   base::ScopedFD fd = data_offer_->Receive(mime_type);
   if (!fd.is_valid()) {
     DPLOG(ERROR) << "Failed to open file descriptor.";
-    std::move(callback).Run(nullptr);
-    return false;
+    return {};
   }
 
-  connection_->ScheduleFlush();
+  // Do a roundtrip to ensure the above request reaches the server and the
+  // resulting events get processed. Otherwise, the source client won’t send any
+  // data, thus getting the owning thread stuck at the blocking read call below.
+  connection_->RoundTripQueue();
 
-  // Schedule data reading to be done asynchronously in the thread pool as it
-  // may take some time and blocking the UI thread for IO is undesirable.
-  // TODO(crbug.com/913422): Use USER_VISIBLE once Clipboard becomes async.
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()},
-      base::BindOnce(&WaylandDataDeviceBase::ReadFromFD, base::Unretained(this),
-                     std::move(fd)),
-      std::move(callback));
-  return true;
+  return ReadFromFD(std::move(fd));
 }
 
 void WaylandDataDeviceBase::ResetDataOffer() {
@@ -106,9 +95,9 @@
   DCHECK(!deferred_read_closure_.is_null());
 
   // The callback must be reset before invoking the closure because the latter
-  // may want to set another callback.  That typically happens when non-trivial
-  // data types are dropped; they have fallbacks to plain text so several
-  // roundtrips to data are chained.
+  // may want to set another callback.  That typically happens when
+  // non-trivial data types are dropped; they have fallbacks to plain text so
+  // several roundtrips to data are chained.
   deferred_read_callback_.reset();
 
   std::move(deferred_read_closure_).Run();
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device_base.h b/ui/ozone/platform/wayland/host/wayland_data_device_base.h
index 28ee14d..99c7449 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device_base.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_device_base.h
@@ -45,10 +45,9 @@
   // Returns MIME types given by the current data offer.
   const std::vector<std::string>& GetAvailableMimeTypes() const;
 
-  // Asynchronously reads selection data for the specified |mime_type| and
-  // delivers the result, if any, through |callback|.
-  bool ReadSelectionData(const std::string& mime_type,
-                         PlatformClipboard::RequestDataClosure callback);
+  // Synchronously reads and returns selection data with |mime_type| format.
+  // TODO(crbug.com/443355): Drop once Clipboard API becomes async.
+  PlatformClipboard::Data ReadSelectionData(const std::string& mime_type);
 
  protected:
   WaylandConnection* connection() const { return connection_; }
diff --git a/ui/views/controls/button/label_button.h b/ui/views/controls/button/label_button.h
index e5c0620..a73224b9 100644
--- a/ui/views/controls/button/label_button.h
+++ b/ui/views/controls/button/label_button.h
@@ -276,6 +276,7 @@
 VIEW_BUILDER_PROPERTY(gfx::HorizontalAlignment, HorizontalAlignment)
 VIEW_BUILDER_PROPERTY(gfx::Size, MinSize)
 VIEW_BUILDER_PROPERTY(gfx::Size, MaxSize)
+VIEW_BUILDER_PROPERTY(absl::optional<SkColor>, EnabledTextColors)
 VIEW_BUILDER_PROPERTY(bool, IsDefault)
 VIEW_BUILDER_PROPERTY(int, ImageLabelSpacing)
 VIEW_BUILDER_PROPERTY(bool, ImageCentered)
diff --git a/ui/views/layout/table_layout.cc b/ui/views/layout/table_layout.cc
index 9404e906..01e1f374 100644
--- a/ui/views/layout/table_layout.cc
+++ b/ui/views/layout/table_layout.cc
@@ -370,6 +370,12 @@
   return *this;
 }
 
+TableLayout& TableLayout::SetIncludeHidden(bool include_hidden) {
+  include_hidden_ = include_hidden;
+  OnLayoutChanged();
+  return *this;
+}
+
 ProposedLayout TableLayout::CalculateProposedLayout(
     const SizeBounds& size_bounds) const {
   ProposedLayout layout;
@@ -419,7 +425,7 @@
   size_t col = 0, row = 0;
   std::vector<ViewState*> row_spans;
   for (View* child : GetChildViewsInPaintOrder(host_view())) {
-    if (!IsChildIncludedInLayout(child))
+    if (!IsChildIncludedInLayout(child, include_hidden_))
       continue;
 
     // Move (col, row) to next open cell.
diff --git a/ui/views/layout/table_layout.h b/ui/views/layout/table_layout.h
index 783918d5..5c97f5a 100644
--- a/ui/views/layout/table_layout.h
+++ b/ui/views/layout/table_layout.h
@@ -131,6 +131,8 @@
 
   TableLayout& SetMinimumSize(const gfx::Size& size);
 
+  TableLayout& SetIncludeHidden(bool include_hidden);
+
  protected:
   ProposedLayout CalculateProposedLayout(
       const SizeBounds& size_bounds) const override;
@@ -200,6 +202,9 @@
 
   // ViewStates sorted based on column_span in ascending order.
   mutable std::vector<ViewState*> view_states_by_col_span_;
+
+  // Indicates whether hidden views are included.
+  bool include_hidden_ = false;
 };
 
 }  // namespace views
diff --git a/ui/views/layout/table_layout_view.cc b/ui/views/layout/table_layout_view.cc
index 3c23b544..89592edd 100644
--- a/ui/views/layout/table_layout_view.cc
+++ b/ui/views/layout/table_layout_view.cc
@@ -57,6 +57,11 @@
   return *this;
 }
 
+TableLayoutView& TableLayoutView::SetIncludeHidden(bool include_hidden) {
+  table_layout_->SetIncludeHidden(include_hidden);
+  return *this;
+}
+
 BEGIN_METADATA(TableLayoutView, View)
 END_METADATA
 
diff --git a/ui/views/layout/table_layout_view.h b/ui/views/layout/table_layout_view.h
index 4ee8579..ae7698a4 100644
--- a/ui/views/layout/table_layout_view.h
+++ b/ui/views/layout/table_layout_view.h
@@ -38,6 +38,7 @@
   TableLayoutView& LinkColumnSizes(std::vector<size_t> columns);
   TableLayoutView& SetLinkedColumnSizeLimit(int size_limit);
   TableLayoutView& SetMinimumSize(const gfx::Size& size);
+  TableLayoutView& SetIncludeHidden(bool include_hidden);
 
  private:
   TableLayout* table_layout_ =
@@ -56,8 +57,9 @@
 VIEW_BUILDER_METHOD(AddRows, size_t, float, int)
 VIEW_BUILDER_METHOD(AddPaddingRow, float, int)
 VIEW_BUILDER_METHOD(LinkColumnSizes, std::vector<size_t>)
-VIEW_BUILDER_METHOD(SetLinkedColumnSizeLimit, int)
-VIEW_BUILDER_METHOD(SetMinimumSize, gfx::Size)
+VIEW_BUILDER_PROPERTY(int, LinkedColumnSizeLimit)
+VIEW_BUILDER_PROPERTY(gfx::Size, MinimumSize)
+VIEW_BUILDER_PROPERTY(bool, IncludeHidden)
 END_VIEW_BUILDER
 
 }  // namespace views
diff --git a/ui/views/metadata/view_factory.h b/ui/views/metadata/view_factory.h
index b955308e..0bea438 100644
--- a/ui/views/metadata/view_factory.h
+++ b/ui/views/metadata/view_factory.h
@@ -272,7 +272,7 @@
     view_class##BuilderT& operator=(view_class##BuilderT&&) = default;        \
     ~view_class##BuilderT() override = default;
 
-#define VIEW_BUILDER_PROPERTY(property_type, property_name)                   \
+#define VIEW_BUILDER_PROPERTY2(property_type, property_name)                  \
   BuilderT& Set##property_name(                                               \
       ::ui::metadata::ArgType<property_type> value)& {                        \
     auto setter = std::make_unique<::views::internal::PropertySetter<         \
@@ -286,6 +286,25 @@
     return std::move(this->Set##property_name(std::move(value)));             \
   }
 
+#define VIEW_BUILDER_PROPERTY3(property_type, property_name, field_type)      \
+  BuilderT& Set##property_name(                                               \
+      ::ui::metadata::ArgType<property_type> value)& {                        \
+    auto setter = std::make_unique<::views::internal::PropertySetter<         \
+        ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
+        &ViewClass_::Set##property_name, field_type>>(std::move(value));      \
+    ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
+    return *static_cast<BuilderT*>(this);                                     \
+  }                                                                           \
+  BuilderT&& Set##property_name(                                              \
+      ::ui::metadata::ArgType<property_type> value)&& {                       \
+    return std::move(this->Set##property_name(std::move(value)));             \
+  }
+
+#define GET_VB_MACRO(_1, _2, _3, macro_name, ...) macro_name
+#define VIEW_BUILDER_PROPERTY(...)                                          \
+  GET_VB_MACRO(__VA_ARGS__, VIEW_BUILDER_PROPERTY3, VIEW_BUILDER_PROPERTY2) \
+  (__VA_ARGS__)
+
 #define VIEW_BUILDER_METHOD(method_name, ...)                                 \
   template <typename... Args>                                                 \
   BuilderT& method_name(Args&&... args)& {                                    \
diff --git a/ui/views/metadata/view_factory_internal.h b/ui/views/metadata/view_factory_internal.h
index 1da86b5..8b3bc76 100644
--- a/ui/views/metadata/view_factory_internal.h
+++ b/ui/views/metadata/view_factory_internal.h
@@ -47,7 +47,11 @@
   virtual void SetProperty(View* obj) = 0;
 };
 
-template <typename TClass, typename TValue, typename TSig, TSig Set>
+template <typename TClass,
+          typename TValue,
+          typename TSig,
+          TSig Set,
+          typename FType = typename std::remove_reference<TValue>::type>
 class PropertySetter : public PropertySetterBase {
  public:
   explicit PropertySetter(ui::metadata::ArgType<TValue> value)
@@ -61,7 +65,7 @@
   }
 
  private:
-  TValue value_;
+  FType value_;
 };
 
 template <typename TClass, typename TValue>
@@ -140,7 +144,7 @@
   }
 
  private:
-  using Parameters = std::tuple<Args...>;
+  using Parameters = std::tuple<typename std::remove_reference<Args>::type...>;
   Parameters args_;
 };
 
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h
index 1598bd7f..3ebb33d 100644
--- a/url/url_canon_stdstring.h
+++ b/url/url_canon_stdstring.h
@@ -81,30 +81,47 @@
   void SetUsernameStr(const CharT* str) { SetImpl(&ParentT::SetUsername, str); }
   void SetUsernameStr(StringPieceT str) { SetImpl(&ParentT::SetUsername, str); }
   void SetUsernameStr(const StringT&&) = delete;
+  using ParentT::ClearUsername;
 
   void SetPasswordStr(const CharT* str) { SetImpl(&ParentT::SetPassword, str); }
   void SetPasswordStr(StringPieceT str) { SetImpl(&ParentT::SetPassword, str); }
   void SetPasswordStr(const StringT&&) = delete;
+  using ParentT::ClearPassword;
 
   void SetHostStr(const CharT* str) { SetImpl(&ParentT::SetHost, str); }
   void SetHostStr(StringPieceT str) { SetImpl(&ParentT::SetHost, str); }
   void SetHostStr(const StringT&&) = delete;
+  using ParentT::ClearHost;
 
   void SetPortStr(const CharT* str) { SetImpl(&ParentT::SetPort, str); }
   void SetPortStr(StringPieceT str) { SetImpl(&ParentT::SetPort, str); }
   void SetPortStr(const StringT&&) = delete;
+  using ParentT::ClearPort;
 
   void SetPathStr(const CharT* str) { SetImpl(&ParentT::SetPath, str); }
   void SetPathStr(StringPieceT str) { SetImpl(&ParentT::SetPath, str); }
   void SetPathStr(const StringT&&) = delete;
+  using ParentT::ClearPath;
 
   void SetQueryStr(const CharT* str) { SetImpl(&ParentT::SetQuery, str); }
   void SetQueryStr(StringPieceT str) { SetImpl(&ParentT::SetQuery, str); }
   void SetQueryStr(const StringT&&) = delete;
+  using ParentT::ClearQuery;
 
   void SetRefStr(const CharT* str) { SetImpl(&ParentT::SetRef, str); }
   void SetRefStr(StringPieceT str) { SetImpl(&ParentT::SetRef, str); }
   void SetRefStr(const StringT&&) = delete;
+  using ParentT::ClearRef;
+
+ private:
+  using ParentT::SetHost;
+  using ParentT::SetPassword;
+  using ParentT::SetPath;
+  using ParentT::SetPort;
+  using ParentT::SetQuery;
+  using ParentT::SetRef;
+  using ParentT::SetScheme;
+  using ParentT::SetUsername;
 };
 
 }  // namespace url
diff --git a/weblayer/browser/weblayer_security_blocking_page_factory.cc b/weblayer/browser/weblayer_security_blocking_page_factory.cc
index 7b30e247..b44b17e 100644
--- a/weblayer/browser/weblayer_security_blocking_page_factory.cc
+++ b/weblayer/browser/weblayer_security_blocking_page_factory.cc
@@ -154,27 +154,6 @@
   return interstitial_page;
 }
 
-std::unique_ptr<LegacyTLSBlockingPage>
-WebLayerSecurityBlockingPageFactory::CreateLegacyTLSBlockingPage(
-    content::WebContents* web_contents,
-    int cert_error,
-    const GURL& request_url,
-    std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    const net::SSLInfo& ssl_info) {
-  auto controller_client = std::make_unique<SSLErrorControllerClient>(
-      web_contents, cert_error, ssl_info, request_url,
-      CreateMetricsHelperAndStartRecording(web_contents, request_url,
-                                           "legacy_tls", false),
-      CreateSettingsPageHelper());
-
-  auto interstitial_page = std::make_unique<LegacyTLSBlockingPage>(
-      web_contents, cert_error, request_url, std::move(ssl_cert_reporter),
-      /*can_show_enhanced_protection_message=*/false, ssl_info,
-      std::move(controller_client));
-
-  return interstitial_page;
-}
-
 std::unique_ptr<MITMSoftwareBlockingPage>
 WebLayerSecurityBlockingPageFactory::CreateMITMSoftwareBlockingPage(
     content::WebContents* web_contents,
diff --git a/weblayer/browser/weblayer_security_blocking_page_factory.h b/weblayer/browser/weblayer_security_blocking_page_factory.h
index 86d3b69b..342dee7 100644
--- a/weblayer/browser/weblayer_security_blocking_page_factory.h
+++ b/weblayer/browser/weblayer_security_blocking_page_factory.h
@@ -54,12 +54,6 @@
       const base::Time& time_triggered,
       ssl_errors::ClockState clock_state,
       std::unique_ptr<SSLCertReporter> ssl_cert_reporter) override;
-  std::unique_ptr<LegacyTLSBlockingPage> CreateLegacyTLSBlockingPage(
-      content::WebContents* web_contents,
-      int cert_error,
-      const GURL& request_url,
-      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-      const net::SSLInfo& ssl_info) override;
   std::unique_ptr<MITMSoftwareBlockingPage> CreateMITMSoftwareBlockingPage(
       content::WebContents* web_contents,
       int cert_error,
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn
index 5d4597f..72964702 100644
--- a/weblayer/test/BUILD.gn
+++ b/weblayer/test/BUILD.gn
@@ -95,7 +95,6 @@
     "//components/test/data",
     "//net/tools/testserver/",
     "//third_party/pywebsocket3/src/mod_pywebsocket/",
-    "//third_party/tlslite/",
   ]
 
   data_deps = [