diff --git a/DEPS b/DEPS
index dfa530b..425e4f4b 100644
--- a/DEPS
+++ b/DEPS
@@ -177,7 +177,7 @@
   # luci-go CIPD package version.
   # Make sure the revision is uploaded by infra-packagers builder.
   # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
-  'luci_go': 'git_revision:3e796d36914b6ddf5311374284e3ffa06c24fc7e',
+  'luci_go': 'git_revision:abd26383ec208bf080ee8585d1495e7f75483ec9',
 
   # This can be overridden, e.g. with custom_vars, to build clang from HEAD
   # instead of downloading the prebuilt pinned revision.
@@ -209,7 +209,7 @@
   # 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': '03e783020013caa8fd8fb070a6ea37bb2f756200',
+  'skia_revision': '6f4bacb9df54d7be6edee0140da595139fb820ca',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -221,7 +221,7 @@
   # 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': 'd0dc22fd07e40beb5a771840a8a0d43134aa20c4',
+  'angle_revision': 'be873929d707de54dd3d0fae31acdeea6ec8c8c2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -288,7 +288,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': 'a6df3ab32f4aafc308236619a04a99317dd22b06',
+  'devtools_frontend_revision': 'ad4964c542770fba75466e66ca63903d4e2f0722',
   # 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.
@@ -328,7 +328,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '1413b351fac11876fcead0a95f04deb17f5630a5',
+  'dawn_revision': '661928894ec9d4d0024e5444bc3ab86575679400',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -573,7 +573,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '2ae9094c8b917273b1c8bdbc16d53e0f9362eb88',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '22faa4d34a5ecc871cce0c9d115c3ca7b028f0da',
       'condition': 'checkout_ios',
   },
 
@@ -730,7 +730,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '8d-gGcc4KVhOnn2B-Od7eR421Q-sNZQ0U7dMrNz_VX4C',
+          'version': '5wEAJbMDQJnCxXbN6hMn66IR4akg1G25HQtc_8_7Vz0C',
       },
     ],
     'condition': 'checkout_android',
@@ -1547,7 +1547,7 @@
   'src/third_party/usrsctp/usrsctplib':
     Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '22ba62ffe79c3881581ab430368bf3764d9533eb',
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@83d509240cca255b5917bcb869f1d03e6325eb14',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@e00902ff0f362653dbfc2c6220b11ff8f91a5f20',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '732a76d9d3c70d6aa487216495eeb28518349c3a',
@@ -1611,7 +1611,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'BL1QYX6LBgah6_XEB3KHs9jZiFQtq2z8PUZRswCFvN8C',
+          'version': 'JItKnXhnS8XOC3pfEti_mAl6ez2Dgk_qSjs5wXeG5xEC',
         },
       ],
       'dep_type': 'cipd',
@@ -1635,7 +1635,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d86de93cc34524c6dfd3a2e52ff8eaec1bb7ecf4',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c48adaed513745039abef53b2ea5a0abd3057fc0',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/assistant/assistant_web_view_delegate_impl.cc b/ash/assistant/assistant_web_view_delegate_impl.cc
index d6a5d28..26a60574 100644
--- a/ash/assistant/assistant_web_view_delegate_impl.cc
+++ b/ash/assistant/assistant_web_view_delegate_impl.cc
@@ -38,6 +38,7 @@
       case views::CAPTION_BUTTON_ICON_MENU:
       case views::CAPTION_BUTTON_ICON_ZOOM:
       case views::CAPTION_BUTTON_ICON_LOCATION:
+      case views::CAPTION_BUTTON_ICON_CENTER:
       case views::CAPTION_BUTTON_ICON_COUNT:
         return false;
     }
diff --git a/ash/components/resources/BUILD.gn b/ash/components/resources/BUILD.gn
index d2698f9..2766f5a 100644
--- a/ash/components/resources/BUILD.gn
+++ b/ash/components/resources/BUILD.gn
@@ -23,31 +23,6 @@
   output_dir = "$root_gen_dir/ash"
 }
 
-# Resources used by chrome://file-manager
-if (!is_official_build) {
-  grit("file_manager_resources") {
-    # main.html is generated at build time.
-    enable_input_discovery_for_gn_analyze = false
-
-    source = "../../content/file_manager/resources/file_manager_resources.grd"
-
-    outputs = [
-      "grit/ash_file_manager_resources.h",
-      "grit/ash_file_manager_resources_map.cc",
-      "grit/ash_file_manager_resources_map.h",
-      "ash_file_manager_resources.pak",
-    ]
-    output_dir = "$root_gen_dir/ash"
-
-    deps = [
-      "//ash/content/file_manager/mojom:mojom_js",
-      "//ash/content/file_manager/resources:build",
-      "//ash/content/file_manager/resources:gen_main_html",
-      "//mojo/public/js:bindings_lite",
-    ]
-  }
-}
-
 grit("scanning_app_resources") {
   source = "../../content/scanning/resources/scanning_app_resources.grd"
 
diff --git a/ash/content/file_manager/BUILD.gn b/ash/content/file_manager/BUILD.gn
index 177bee4..55381e0 100644
--- a/ash/content/file_manager/BUILD.gn
+++ b/ash/content/file_manager/BUILD.gn
@@ -2,9 +2,17 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
+import("//chrome/common/features.gni")
+
 assert(is_chromeos, "File Manager is Chrome OS only")
 assert(!is_official_build, "File Manager is only built for unofficial builds")
 
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+  flags = [ "OPTIMIZE_WEBUI=$optimize_webui" ]
+}
+
 static_library("file_manager_ui") {
   sources = [
     "file_manager_page_handler.cc",
@@ -17,8 +25,9 @@
   ]
 
   deps = [
-    "//ash/components/resources:file_manager_resources",
+    ":buildflags",
     "//ash/content/file_manager/mojom",
+    "//ash/content/file_manager/resources:file_manager_swa_resources",
     "//base",
     "//content/public/browser",
     "//ui/file_manager:file_manager_gen_resources",
diff --git a/ash/content/file_manager/file_manager_ui.cc b/ash/content/file_manager/file_manager_ui.cc
index 0426cd93..44e44f3 100644
--- a/ash/content/file_manager/file_manager_ui.cc
+++ b/ash/content/file_manager/file_manager_ui.cc
@@ -4,12 +4,15 @@
 
 #include "ash/content/file_manager/file_manager_ui.h"
 
+#include "ash/content/file_manager/buildflags.h"
 #include "ash/content/file_manager/file_manager_page_handler.h"
+#include "ash/content/file_manager/resources/grit/file_manager_swa_resources.h"
+#include "ash/content/file_manager/resources/grit/file_manager_swa_resources_map.h"
 #include "ash/content/file_manager/url_constants.h"
-#include "ash/grit/ash_file_manager_resources.h"
-#include "ash/grit/ash_file_manager_resources_map.h"
 #include "base/memory/ptr_util.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
+#include "build/build_config.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -32,6 +35,15 @@
       // so we remove the leading file_manager/ to match the existing paths.
       base::ReplaceFirstSubstringAfterOffset(&path, 0, "file_manager/", "");
       source->AddResourcePath(path, entries[i].id);
+
+#if !BUILDFLAG(OPTIMIZE_WEBUI)
+      // When optmize_webui=false, the SWA loads individual JS files from the
+      // file_manager extension, so we add the same resource with the path
+      // relative from the SWA to the extension:
+      std::string path_from_swa(
+          base::StrCat({"ui/file_manager/", entries[i].path}));
+      source->AddResourcePath(path_from_swa, entries[i].id);
+#endif
     }
   }
 }
@@ -53,7 +65,7 @@
 
   // Add chrome://file-manager content.
   source->AddResourcePaths(
-      base::make_span(kAshFileManagerResources, kAshFileManagerResourcesSize));
+      base::make_span(kFileManagerSwaResources, kFileManagerSwaResourcesSize));
 
   AddFilesAppResources(source, kFileManagerResources,
                        kFileManagerResourcesSize);
diff --git a/ash/content/file_manager/resources/BUILD.gn b/ash/content/file_manager/resources/BUILD.gn
index 393aca9..4809b9f 100644
--- a/ash/content/file_manager/resources/BUILD.gn
+++ b/ash/content/file_manager/resources/BUILD.gn
@@ -3,8 +3,11 @@
 # found in the LICENSE file.
 
 import("//chrome/browser/resources/tools/optimize_webui.gni")
+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("//ui/webui/resources/tools/generate_grd.gni")
 
 preprocess_folder = "$target_gen_dir/preprocessed"
 mojom_webui_folder = "$root_gen_dir/mojom-webui/ash/content/file_manager/mojom"
@@ -64,6 +67,7 @@
 preprocess_if_expr("preprocess") {
   in_folder = "./"  #target_gen_dir
   out_folder = preprocess_folder
+  out_manifest = "$target_gen_dir/manifest_preprocess.json"
 
   in_files = [
     "browser_proxy.js",
@@ -84,6 +88,7 @@
   in_folder = mojom_webui_folder
   in_files = [ "file_manager.mojom-webui.js" ]
   out_folder = preprocess_folder
+  out_manifest = "$target_gen_dir/manifest_preprocess_mojo.json"
   deps = [ "//ash/content/file_manager/mojom:mojom_webui_js" ]
 }
 
@@ -105,3 +110,64 @@
     "//ui/webui/resources:preprocess",
   ]
 }
+
+generated_static_grdp = "$target_gen_dir/static_resources.grdp"
+
+generate_grd("build_static_grdp") {
+  out_grd = generated_static_grdp
+  grd_prefix = "file_manager_swa"
+
+  input_files_base_dir = rebase_path(".", "//")
+
+  input_files = [
+    "images/icon192.png",
+    "file_manager_fakes.js",
+  ]
+}
+
+grd_prefix = "file_manager_swa"
+generated_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
+
+generate_grd("build_grd") {
+  out_grd = generated_grd
+
+  grdp_files = [ generated_static_grdp ]
+
+  deps = [
+    ":build",
+    ":build_static_grdp",
+    ":gen_main_html",
+    ":preprocess",
+    ":preprocess_mojo",
+  ]
+  input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
+  input_files = [ "main.html" ]
+  manifest_files = [ "$target_gen_dir/manifest_preprocess_mojo.json" ]
+
+  if (optimize_webui) {
+    input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
+    input_files += [ "main.rollup.js" ]
+
+    resource_path_rewrites = [ "main.rollup.js|main.js" ]
+  } else {
+    manifest_files += [ "$target_gen_dir/manifest_preprocess.json" ]
+  }
+}
+
+grit("file_manager_swa_resources") {
+  defines = chrome_grit_defines
+
+  # These arguments are needed since the grd is generated at build time.
+  enable_input_discovery_for_gn_analyze = false
+
+  source = generated_grd
+  deps = [ ":build_grd" ]
+
+  outputs = [
+    "grit/file_manager_swa_resources.h",
+    "grit/file_manager_swa_resources_map.cc",
+    "grit/file_manager_swa_resources_map.h",
+    "file_manager_swa_resources.pak",
+  ]
+  output_dir = target_gen_dir
+}
diff --git a/ash/content/file_manager/resources/file_manager_resources.grd b/ash/content/file_manager/resources/file_manager_resources.grd
deleted file mode 100644
index ff69fd2..0000000
--- a/ash/content/file_manager/resources/file_manager_resources.grd
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/ash_file_manager_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/ash_file_manager_resources_map.cc"
-      type="resource_file_map_source" />
-    <output filename="grit/ash_file_manager_resources_map.h"
-      type="resource_map_header" />
-    <output filename="ash_file_manager_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <includes>
-      <if expr="is_official_build == false">
-        <!-- Privileged app host contents. -->
-        <include name="IDR_FILE_MANAGER_SWA_MOJO_JS" file="$root_gen_dir/mojom-webui/ash/content/file_manager/mojom/file_manager.mojom-webui.js" resource_path="file_manager.mojom-webui.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_BROWSER_PROXY_JS" file="browser_proxy.js" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_SCRIPT_LOADER_JS" file="script_loader.js" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_MAIN_HTML" file="${root_gen_dir}/ash/content/file_manager/resources/main.html" resource_path="main.html" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_FILE_MANAGER_FAKES_JS" file="file_manager_fakes.js" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_MAIN_ROLLUP_JS" file="${root_gen_dir}/ash/content/file_manager/resources/main.rollup.js" resource_path="main.rollup.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_MAIN_JS" file="main.js" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_SWA_ICON_192" file="images/icon192.png" type="BINDATA" />
-      </if>
-    </includes>
-  </release>
-</grit>
diff --git a/ash/content/file_manager/resources/gen_main_html.py b/ash/content/file_manager/resources/gen_main_html.py
index 731a95a..d4d287544 100755
--- a/ash/content/file_manager/resources/gen_main_html.py
+++ b/ash/content/file_manager/resources/gen_main_html.py
@@ -14,8 +14,7 @@
 import shutil
 import sys
 
-_SWA = '<script type="module"'\
-       ' src="chrome://file-manager/main.rollup.js"></script>'
+_SWA = '<script type="module" src="chrome://file-manager/main.js"></script>'
 
 def GenerateSwaMainHtml(source, target):
   """Copy source file to target, do SWA edits, then add BUILD time stamp."""
diff --git a/ash/content/file_manager/resources/main.js b/ash/content/file_manager/resources/main.js
index 7460e3e..828f126 100644
--- a/ash/content/file_manager/resources/main.js
+++ b/ash/content/file_manager/resources/main.js
@@ -45,15 +45,21 @@
   async run() {
     await new ScriptLoader('file_manager_fakes.js', {type: 'module'}).load();
 
-    // Temporarily remove window.cr while the foreground script bundle loads.
-    const origCr = window.cr;
-    delete window.cr;
+    // Temporarily remove window.cr.webUI* while the foreground script loads.
+    const origWebUIResponse = window.webUIResponse;
+    const origWebUIListenerCallback = window.webUIListenerCallback;
+    delete window.cr.webUIResponse;
+    delete window.cr.webUIListenerCallback;
+
     // Avoid double loading the LoadTimeData strings.
     window.loadTimeData.data_ = null;
 
     await new ScriptLoader('foreground/js/main.m.js', {type: 'module'}).load();
-    // Restore the window.cr object.
-    Object.assign(window.cr, origCr);
+
+    // Restore the window.cr.webUI* objects.
+    window.cr.webUIResponse = origWebUIResponse;
+    window.cr.webUIListenerCallback = origWebUIListenerCallback;
+
     console.debug('Files app UI loaded');
   }
 }
diff --git a/ash/content/shimless_rma/resources/fake_shimless_rma_service.js b/ash/content/shimless_rma/resources/fake_shimless_rma_service.js
index b32b11be..3c7cf8e 100644
--- a/ash/content/shimless_rma/resources/fake_shimless_rma_service.js
+++ b/ash/content/shimless_rma/resources/fake_shimless_rma_service.js
@@ -6,7 +6,7 @@
 import {FakeObservables} from 'chrome://resources/ash/common/fake_observables.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 
-import {CalibrationComponent, CalibrationObserver, Component, ComponentRepairState, ComponentType, ErrorObserver, HardwareWriteProtectionStateObserver, PowerCableStateObserver, ProvisioningObserver, ProvisioningStep, RmadErrorCode, RmaState, ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js';
+import {CalibrationComponent, CalibrationObserverRemote, Component, ComponentRepairState, ComponentType, ErrorObserverRemote, HardwareWriteProtectionStateObserverRemote, PowerCableStateObserverRemote, ProvisioningObserverRemote, ProvisioningStep, RmadErrorCode, RmaState, ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js';
 
 /** @implements {ShimlessRmaServiceInterface} */
 export class FakeShimlessRmaService {
@@ -512,7 +512,7 @@
 
   /**
    * Implements ShimlessRmaServiceInterface.ObserveError.
-   * @param {!ErrorObserver} remote
+   * @param {!ErrorObserverRemote} remote
    */
   observeError(remote) {
     this.observables_.observe('ErrorObserver_onError', (error) => {
@@ -523,9 +523,9 @@
 
   /**
    * Implements ShimlessRmaServiceInterface.ObserveCalibration.
-   * @param {!CalibrationObserver} remote
+   * @param {!CalibrationObserverRemote} remote
    */
-  observeCalibration(remote) {
+  observeCalibrationProgress(remote) {
     this.observables_.observe(
         'CalibrationObserver_onCalibrationUpdated', (component, progress) => {
           remote.onCalibrationUpdated(
@@ -536,9 +536,9 @@
 
   /**
    * Implements ShimlessRmaServiceInterface.ObserveProvisioning.
-   * @param {!ProvisioningObserver} remote
+   * @param {!ProvisioningObserverRemote} remote
    */
-  observeProvisioning(remote) {
+  observeProvisioningProgress(remote) {
     this.observables_.observe(
         'ProvisioningObserver_onProvisioningUpdated', (step, progress) => {
           remote.onProvisioningUpdated(
@@ -549,7 +549,7 @@
 
   /**
    * Implements ShimlessRmaServiceInterface.ObserveHardwareWriteProtectionState.
-   * @param {!HardwareWriteProtectionStateObserver} remote
+   * @param {!HardwareWriteProtectionStateObserverRemote} remote
    */
   observeHardwareWriteProtectionState(remote) {
     this.observables_.observe(
@@ -562,7 +562,7 @@
 
   /**
    * Implements ShimlessRmaServiceInterface.ObservePowerCableState.
-   * @param {!PowerCableStateObserver} remote
+   * @param {!PowerCableStateObserverRemote} remote
    */
   observePowerCableState(remote) {
     this.observables_.observe(
diff --git a/ash/content/shimless_rma/resources/shimless_rma_types.js b/ash/content/shimless_rma/resources/shimless_rma_types.js
index 8f992b1..48ac4f3 100644
--- a/ash/content/shimless_rma/resources/shimless_rma_types.js
+++ b/ash/content/shimless_rma/resources/shimless_rma_types.js
@@ -123,9 +123,8 @@
  */
 export let ProvisioningStep = {
   kProvisioningUnknown: 0,
-  kFrobWidget: 1,
-  kTwiddleSettings: 2,
-  kProvisioningComplete: 3,
+  kInProgress: 1,
+  kProvisioningComplete: 2,
   MIN_VALUE: 0,
   MAX_VALUE: 3,
 };
@@ -142,7 +141,7 @@
  * Type alias for ErrorObserver.
  * @typedef {{onError: !function(!RmadErrorCode)}}
  */
-export let ErrorObserver;
+export let ErrorObserverRemote;
 
 /**
  * Type alias for CalibrationProgressObserver.
@@ -150,7 +149,7 @@
  *   onCalibrationUpdated: !function(!CalibrationComponent, number)
  * }}
  */
-export let CalibrationObserver;
+export let CalibrationObserverRemote;
 
 /**
  * Type alias for ProvisioningProgressObserver.
@@ -158,7 +157,7 @@
  *   onProvisioningUpdated: !function(!ProvisioningStep, number)
  * }}
  */
-export let ProvisioningObserver;
+export let ProvisioningObserverRemote;
 
 /**
  * Type alias for HardwareWriteProtectionState.
@@ -166,7 +165,7 @@
  *   onHardwareWriteProtectionStateChanged: !function(boolean)
  * }}
  */
-export let HardwareWriteProtectionStateObserver;
+export let HardwareWriteProtectionStateObserverRemote;
 
 /**
  * Type alias for PowerCableState.
@@ -174,7 +173,7 @@
  *   onPowerCableStateChanged: !function(boolean)
  * }}
  */
-export let PowerCableStateObserver;
+export let PowerCableStateObserverRemote;
 
 /**
  * Type of ShimlessRmaServiceInterface.setStates function.
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc
index 5071b78..f0c288e8 100644
--- a/ash/frame/header_view.cc
+++ b/ash/frame/header_view.cc
@@ -75,6 +75,7 @@
       caption_button_container_);
 
   UpdateBackButton();
+  UpdateCenterButton();
 
   frame_header_->UpdateFrameColors();
   window_observation_.Observe(window);
@@ -140,6 +141,7 @@
   caption_button_container_->UpdateCaptionButtonState(true /*=animate*/);
 
   UpdateBackButton();
+  UpdateCenterButton();
 
   Layout();
 }
@@ -324,6 +326,19 @@
   }
 }
 
+void HeaderView::UpdateCenterButton() {
+  bool is_center_button_visible = caption_button_container_->model()->IsVisible(
+      views::CAPTION_BUTTON_ICON_CENTER);
+  auto* center_button = frame_header_->GetCenterButton();
+  if (!center_button)
+    return;
+  if (is_center_button_visible && !center_button->parent()) {
+    AddChildView(center_button);
+  } else if (!is_center_button_visible && center_button->parent()) {
+    RemoveChildView(center_button);
+  }
+}
+
 void HeaderView::UpdateCaptionButtonsVisibility() {
   if (!target_widget_)
     return;
diff --git a/ash/frame/header_view.h b/ash/frame/header_view.h
index 4310fe2..6579f6c 100644
--- a/ash/frame/header_view.h
+++ b/ash/frame/header_view.h
@@ -134,6 +134,7 @@
   void PaintHeaderContent(gfx::Canvas* canvas);
 
   void UpdateBackButton();
+  void UpdateCenterButton();
   void UpdateCaptionButtonsVisibility();
 
   // The widget that the caption buttons act on.
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb
index 86edcf7..1b797e4 100644
--- a/ash/strings/ash_strings_am.xtb
+++ b/ash/strings/ash_strings_am.xtb
@@ -700,7 +700,7 @@
 <translation id="6641720045729354415">የቀጥታ መግለጫ ጽሑፍን ይቀያይሩ። <ph name="STATE_TEXT" /></translation>
 <translation id="6650072551060208490"><ph name="ORIGIN_NAME" /> እርስዎ እንደሆኑ ማረጋገጥ ይፈልጋል</translation>
 <translation id="6650933572246256093">የብሉቱዝ መሣሪያ «<ph name="DEVICE_NAME" />» ለመጣመር ፍቃድ ይፈልጋል። እባክዎ ይህን የይለፍ ቁልፍ በዚህ መሣሪያ ላይ ያስገቡ፦ <ph name="PASSKEY" /></translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6665545700722362599">ድር ጣቢያዎች፣ መተግበሪያዎች እና ቅጥያዎች የአካባቢ አገልግሎቶችን፣ የመሣሪያውን ማይክሮፎን፣ ካሜራ እና ሌሎች ባህሪያትን የመጠቀም ፈቃድ ይስጧቸው</translation>
 <translation id="6667908387435388584">ከስልክዎ መገናኛ ነጥብ ጋር ያገናኙ፣ የመሣሪያዎ ድምጽ ይዝጉትና ያግኙት፣ እና በስልክዎ ላይ የተከፈቱ የቅርብ ጊዜ የChrome ትሮችን ይመልከቱ</translation>
 <translation id="6670153871843998651">ዴስክ 3</translation>
diff --git a/ash/strings/ash_strings_el.xtb b/ash/strings/ash_strings_el.xtb
index 503f482..a7d2ffc 100644
--- a/ash/strings/ash_strings_el.xtb
+++ b/ash/strings/ash_strings_el.xtb
@@ -700,7 +700,7 @@
 <translation id="6641720045729354415">Εναλλαγή Ζωντανών υπότιτλων. <ph name="STATE_TEXT" /></translation>
 <translation id="6650072551060208490">Το <ph name="ORIGIN_NAME" /> θέλει να επαληθεύσει την ταυτότητά σας.</translation>
 <translation id="6650933572246256093">Η συσκευή Bluetooth "<ph name="DEVICE_NAME" />" ζητά δικαιώματα σύζευξης. Καταχωρίστε αυτό το κλειδί πρόσβασης στη συγκεκριμένη συσκευή: <ph name="PASSKEY" /></translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6665545700722362599">Εκχωρήσει άδειες σε ιστοτόπους, εφαρμογές και επεκτάσεις για τη χρήση υπηρεσιών τοποθεσίας, του μικροφώνου ή της κάμερας της συσκευής ή άλλων λειτουργιών</translation>
 <translation id="6667908387435388584">Συνδεθείτε στο σημείο πρόσβασης Wi-Fi του τηλεφώνου σας, θέστε σε σίγαση και εντοπίστε τη συσκευή σας και δείτε τις πρόσφατες καρτέλες Chrome που είναι ανοικτές στο τηλέφωνό σας.</translation>
 <translation id="6670153871843998651">Γραφείο 3</translation>
diff --git a/base/allocator/allocator_shim_override_mac_default_zone.h b/base/allocator/allocator_shim_override_mac_default_zone.h
index 360e0fea..4cae6cb 100644
--- a/base/allocator/allocator_shim_override_mac_default_zone.h
+++ b/base/allocator/allocator_shim_override_mac_default_zone.h
@@ -15,6 +15,12 @@
 #include "base/bits.h"
 
 namespace base {
+
+// Defined in base/allocator/partition_allocator/partition_root.cc
+void PartitionAllocMallocHookOnBeforeForkInParent();
+void PartitionAllocMallocHookOnAfterForkInParent();
+void PartitionAllocMallocHookOnAfterForkInChild();
+
 namespace allocator {
 
 namespace {
@@ -54,18 +60,12 @@
 
 void MallocIntrospectionForceLock(malloc_zone_t* zone) {
   // Called before fork(2) to acquire the lock.
-  //
-  // PartitionAllocMallocInitOnce() in
-  // //base/allocator/partition_allocator/partition_root.cc has already
-  // registered a set of fork handlers, so it's safe to do nothing here.
+  PartitionAllocMallocHookOnBeforeForkInParent();
 }
 
 void MallocIntrospectionForceUnlock(malloc_zone_t* zone) {
   // Called in the parent process after fork(2) to release the lock.
-  //
-  // PartitionAllocMallocInitOnce() in
-  // //base/allocator/partition_allocator/partition_root.cc has already
-  // registered a set of fork handlers, so it's safe to do nothing here.
+  PartitionAllocMallocHookOnAfterForkInParent();
 }
 
 void MallocIntrospectionStatistics(malloc_zone_t* zone,
@@ -105,10 +105,7 @@
 
 void MallocIntrospectionReinitLock(malloc_zone_t* zone) {
   // Called in a child process after fork(2) to re-initialize the lock.
-  //
-  // PartitionAllocMallocInitOnce() in
-  // //base/allocator/partition_allocator/partition_root.cc has already
-  // registered a set of fork handlers, so it's safe to do nothing here.
+  PartitionAllocMallocHookOnAfterForkInChild();
 }
 
 void MallocIntrospectionPrintTask(task_t task,
@@ -227,7 +224,7 @@
   //   version >= 10: claimed_address is supported
   //   version >= 11: introspect.print_task is supported
   //   version >= 12: introspect.task_statistics is supported
-  g_mac_malloc_zone.version = 6;
+  g_mac_malloc_zone.version = 9;
   g_mac_malloc_zone.zone_name = "PartitionAlloc";
   g_mac_malloc_zone.introspect = &g_mac_malloc_introspection;
   g_mac_malloc_zone.size = MallocZoneSize;
diff --git a/base/allocator/partition_allocator/partition_root.cc b/base/allocator/partition_allocator/partition_root.cc
index adfe2604..f49c0ea 100644
--- a/base/allocator/partition_allocator/partition_root.cc
+++ b/base/allocator/partition_allocator/partition_root.cc
@@ -35,10 +35,10 @@
 
 namespace base {
 
-namespace {
-
 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
 
+namespace {
+
 #if defined(OS_APPLE) || defined(OS_LINUX)
 
 // NO_THREAD_SAFETY_ANALYSIS: acquires the lock and doesn't release it, by
@@ -102,7 +102,7 @@
   if (!g_global_init_called.compare_exchange_strong(expected, true))
     return;
 
-#if defined(OS_APPLE) || defined(OS_LINUX)
+#if defined(OS_LINUX)
   // When fork() is called, only the current thread continues to execute in the
   // child process. If the lock is held, but *not* by this thread when fork() is
   // called, we have a deadlock.
@@ -127,12 +127,27 @@
   int err =
       pthread_atfork(BeforeForkInParent, AfterForkInParent, AfterForkInChild);
   PA_CHECK(err == 0);
-#endif  // defined(OS_APPLE) || defined(OS_LINUX)
+#endif  // defined(OS_LINUX)
 }
-#endif  // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
 
 }  // namespace
 
+#if defined(OS_APPLE)
+void PartitionAllocMallocHookOnBeforeForkInParent() {
+  BeforeForkInParent();
+}
+
+void PartitionAllocMallocHookOnAfterForkInParent() {
+  AfterForkInParent();
+}
+
+void PartitionAllocMallocHookOnAfterForkInChild() {
+  AfterForkInChild();
+}
+#endif  // defined(OS_APPLE)
+
+#endif  // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
+
 namespace internal {
 
 template <bool thread_safe>
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 3f50e2d..b1ae5bed 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-4.20210602.3.1
+4.20210603.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 3f50e2d..b1ae5bed 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-4.20210602.3.1
+4.20210603.0.1
diff --git a/chrome/VERSION b/chrome/VERSION
index 0051329..cc52d189 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=93
 MINOR=0
-BUILD=4531
+BUILD=4532
 PATCH=0
diff --git a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
index 236f59a..55b8825 100644
--- a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
+++ b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
@@ -646,6 +646,16 @@
     <init>();
 }
 
+# File: obj/third_party/androidx/androidx_startup_startup_runtime_java/proguard.txt
+# This Proguard rule ensures that ComponentInitializers are are neither shrunk nor obfuscated.
+# This is because they are discovered and instantiated during application initialization.
+-keep class * extends androidx.startup.Initializer {
+    # Keep the public no-argument constructor while allowing other methods to be optimized.
+    <init>();
+}
+
+-assumenosideeffects class androidx.startup.StartupLogger
+
 # File: obj/third_party/androidx/androidx_transition_transition_java/proguard.txt
 # Copyright (C) 2017 The Android Open Source Project
 #
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
index 83c19ab..79f5cc3 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
@@ -17,6 +17,7 @@
 import org.chromium.chrome.browser.autofill_assistant.generic_ui.AssistantValue;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel.AddressModel;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel.ContactModel;
+import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel.LoginChoiceModel;
 import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel.PaymentInstrumentModel;
 import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSection.Delegate;
 import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSectionContainer;
@@ -180,9 +181,9 @@
             view.mShippingAddressSection.setListener(collectUserDataDelegate == null
                             ? null
                             : m -> collectUserDataDelegate.onShippingAddressChanged(m.mOption));
-            view.mLoginSection.setListener(collectUserDataDelegate != null
-                            ? collectUserDataDelegate::onLoginChoiceChanged
-                            : null);
+            view.mLoginSection.setListener(collectUserDataDelegate == null
+                            ? null
+                            : m -> collectUserDataDelegate.onLoginChoiceChanged(m.mOption));
             view.mDateRangeStartSection.setDelegate(dateStartDelegate);
             view.mDateRangeEndSection.setDelegate(dateEndDelegate);
             view.mPrependedSections.setDelegate(collectUserDataDelegate != null
@@ -290,8 +291,15 @@
             return true;
         } else if (propertyKey == AssistantCollectUserDataModel.AVAILABLE_LOGINS) {
             if (model.get(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE)) {
-                view.mLoginSection.onLoginsChanged(
-                        model.get(AssistantCollectUserDataModel.AVAILABLE_LOGINS));
+                List<AssistantLoginChoice> loginChoices =
+                        model.get(AssistantCollectUserDataModel.AVAILABLE_LOGINS);
+                if (loginChoices != null) {
+                    List<LoginChoiceModel> loginChoiceModels = new ArrayList<>();
+                    for (AssistantLoginChoice loginChoice : loginChoices) {
+                        loginChoiceModels.add(new LoginChoiceModel(loginChoice));
+                    }
+                    view.mLoginSection.onLoginsChanged(loginChoiceModels);
+                }
             }
             return true;
         } else if (propertyKey == AssistantCollectUserDataModel.DATE_RANGE_START_OPTIONS) {
@@ -460,37 +468,40 @@
         // These changes are sent by the controller, do not notify it when selecting the added item.
         // This prevents creating a loop.
         if (propertyKey == AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS) {
-            if (model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS)) {
-                AddressModel shippingAddress =
-                        model.get(AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS);
-                if (shippingAddress != null) {
-                    view.mShippingAddressSection.addOrUpdateItem(
-                            shippingAddress, /* select= */ true, /* notify= */ false);
-                }
-                // No need to reset selection if null, this will be handled by setItems().
+            if (!model.get(AssistantCollectUserDataModel.REQUEST_SHIPPING_ADDRESS)) {
+                return true;
             }
+            AddressModel shippingAddress =
+                    model.get(AssistantCollectUserDataModel.SELECTED_SHIPPING_ADDRESS);
+            if (shippingAddress != null) {
+                view.mShippingAddressSection.addOrUpdateItem(
+                        shippingAddress, /* select= */ true, /* notify= */ false);
+            }
+            // No need to reset selection if null, this will be handled by setItems().
             return true;
         } else if (propertyKey == AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT) {
-            if (model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
-                PaymentInstrumentModel paymentInstrument =
-                        model.get(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT);
-                if (paymentInstrument != null) {
-                    view.mPaymentMethodSection.addOrUpdateItem(
-                            paymentInstrument, /* select= */ true, /* notify= */ false);
-                }
-                // No need to reset selection if null, this will be handled by setItems().
+            if (!model.get(AssistantCollectUserDataModel.REQUEST_PAYMENT)) {
+                return true;
             }
+            PaymentInstrumentModel paymentInstrument =
+                    model.get(AssistantCollectUserDataModel.SELECTED_PAYMENT_INSTRUMENT);
+            if (paymentInstrument != null) {
+                view.mPaymentMethodSection.addOrUpdateItem(
+                        paymentInstrument, /* select= */ true, /* notify= */ false);
+            }
+            // No need to reset selection if null, this will be handled by setItems().
             return true;
         } else if (propertyKey == AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS) {
-            if (shouldShowContactDetails(model)) {
-                ContactModel contact =
-                        model.get(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS);
-                if (contact != null) {
-                    view.mContactDetailsSection.addOrUpdateItem(
-                            contact, /* select= */ true, /* notify= */ false);
-                }
-                // No need to reset selection if null, this will be handled by setItems().
+            if (!shouldShowContactDetails(model)) {
+                return true;
             }
+            ContactModel contact =
+                    model.get(AssistantCollectUserDataModel.SELECTED_CONTACT_DETAILS);
+            if (contact != null) {
+                view.mContactDetailsSection.addOrUpdateItem(
+                        contact, /* select= */ true, /* notify= */ false);
+            }
+            // No need to reset selection if null, this will be handled by setItems().
             return true;
         } else if (propertyKey == AssistantCollectUserDataModel.TERMS_STATUS) {
             int termsStatus = model.get(AssistantCollectUserDataModel.TERMS_STATUS);
@@ -498,9 +509,17 @@
             view.mTermsAsCheckboxSection.setTermsStatus(termsStatus);
             return true;
         } else if (propertyKey == AssistantCollectUserDataModel.SELECTED_LOGIN) {
-            view.mLoginSection.addOrUpdateItem(
-                    model.get(AssistantCollectUserDataModel.SELECTED_LOGIN), /* select= */ true,
-                    /* notify= */ false);
+            if (!model.get(AssistantCollectUserDataModel.REQUEST_LOGIN_CHOICE)) {
+                return true;
+            }
+            AssistantLoginChoice loginChoice =
+                    model.get(AssistantCollectUserDataModel.SELECTED_LOGIN);
+            if (loginChoice != null) {
+                view.mLoginSection.addOrUpdateItem(new LoginChoiceModel(loginChoice),
+                        /* select= */ true,
+                        /* notify= */ false);
+            }
+            // No need to reset selection if null, this will be handled by setItems().
             return true;
         }
         return false;
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java
index 130f0b8..643fbf8d3 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataModel.java
@@ -53,16 +53,11 @@
      * @param <T> The type of |EditableOption| that a concrete instance of this class is created
      * for, such as |AutofillContact|, |AutofillPaymentMethod|, etc.
      */
-    // TODO(b/180705720): Drop the "extends EditableOption" once AssistantLoginChoice has been
-    //  transitioned. Change AssistantCollectUserDataSection to <T extends OptionModel>. Remove
-    //  isComplete from this class.
-    public static class OptionModel<T extends EditableOption> extends EditableOption {
+    public static class OptionModel<T extends EditableOption> {
         public T mOption;
         public List<String> mErrors;
 
         public OptionModel(T option, List<String> errors) {
-            super(option.getIdentifier(), /* label= */ null, /* sublabel= */ null,
-                    /* tertiarylabel= */ null, /* icon= */ null);
             this.mOption = option;
             this.mErrors = errors;
         }
@@ -70,13 +65,6 @@
         public OptionModel(T option) {
             this(option, new ArrayList<>());
         }
-
-        @Override
-        public boolean isComplete() {
-            // Evaluate the option's completeness in terms of the editor's expectations. This does
-            // not take our own validation into account.
-            return this.mOption.isComplete();
-        }
     }
 
     /** Model wrapper for an {@code AutofillContact}. */
@@ -113,6 +101,13 @@
         }
     }
 
+    /** Model wrapper for an {@code AssistantLoginChoice}. */
+    public static class LoginChoiceModel extends OptionModel<AssistantLoginChoice> {
+        public LoginChoiceModel(AssistantLoginChoice loginChoice) {
+            super(loginChoice);
+        }
+    }
+
     public static final WritableObjectPropertyKey<AssistantCollectUserDataDelegate> DELEGATE =
             new WritableObjectPropertyKey<>();
 
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataSection.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataSection.java
index a36b409..8bec4920 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataSection.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataSection.java
@@ -20,7 +20,7 @@
 import org.chromium.chrome.browser.autofill_assistant.AssistantTagsForTesting;
 import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils;
 import org.chromium.chrome.browser.autofill_assistant.LayoutUtils;
-import org.chromium.components.autofill.EditableOption;
+import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel.OptionModel;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -31,7 +31,7 @@
  * @param <T> The type of |EditableOption| that a concrete instance of this class is created for,
  * such as |AutofillContact|, |AutofillPaymentMethod|, etc.
  */
-public abstract class AssistantCollectUserDataSection<T extends EditableOption> {
+public abstract class AssistantCollectUserDataSection<T extends OptionModel> {
     private class Item {
         View mFullView;
         T mOption;
@@ -301,7 +301,7 @@
                         return;
                     }
                     selectItem(item, /*notify=*/true);
-                    if (item.mOption.isComplete()) {
+                    if (item.mOption.mOption.isComplete()) {
                         // Workaround for Android bug: a layout transition may cause the newly
                         // checked radiobutton to not render properly.
                         mSectionExpander.post(() -> mSectionExpander.setExpanded(false));
@@ -325,8 +325,9 @@
         updateVisibility();
 
         if (mListener != null && notify) {
-            mListener.onResult(
-                    item.mOption != null && item.mOption.isComplete() ? item.mOption : null);
+            mListener.onResult(item.mOption != null && item.mOption.mOption.isComplete()
+                            ? item.mOption
+                            : null);
         }
     }
 
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantLoginSection.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantLoginSection.java
index 4cf04166..041fd14a 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantLoginSection.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantLoginSection.java
@@ -17,13 +17,14 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantCollectUserDataModel.LoginChoiceModel;
 
 import java.util.List;
 
 /**
  * The login details section of the Autofill Assistant payment request.
  */
-public class AssistantLoginSection extends AssistantCollectUserDataSection<AssistantLoginChoice> {
+public class AssistantLoginSection extends AssistantCollectUserDataSection<LoginChoiceModel> {
     AssistantLoginSection(Context context, ViewGroup parent) {
         super(context, parent, R.layout.autofill_assistant_login, R.layout.autofill_assistant_login,
                 context.getResources().getDimensionPixelSize(
@@ -33,20 +34,21 @@
     }
 
     @Override
-    protected void createOrEditItem(@NonNull AssistantLoginChoice oldItem) {
+    protected void createOrEditItem(@NonNull LoginChoiceModel oldItem) {
         assert oldItem != null;
-        assert oldItem.getInfoPopup() != null;
+        assert oldItem.mOption.getInfoPopup() != null;
 
-        oldItem.getInfoPopup().show(mContext);
+        oldItem.mOption.getInfoPopup().show(mContext);
     }
 
     @Override
-    protected void updateFullView(View fullView, AssistantLoginChoice option) {
-        updateSummaryView(fullView, option);
+    protected void updateFullView(View fullView, LoginChoiceModel model) {
+        updateSummaryView(fullView, model);
     }
 
     @Override
-    protected void updateSummaryView(View summaryView, AssistantLoginChoice option) {
+    protected void updateSummaryView(View summaryView, LoginChoiceModel model) {
+        AssistantLoginChoice option = model.mOption;
         TextView labelView = summaryView.findViewById(R.id.label);
         labelView.setText(option.getLabel());
         TextView sublabelView = summaryView.findViewById(R.id.sublabel);
@@ -59,19 +61,19 @@
     }
 
     @Override
-    protected boolean canEditOption(AssistantLoginChoice choice) {
-        return choice.getInfoPopup() != null;
+    protected boolean canEditOption(LoginChoiceModel model) {
+        return model.mOption.getInfoPopup() != null;
     }
 
     @Override
-    protected @DrawableRes int getEditButtonDrawable(AssistantLoginChoice choice) {
+    protected @DrawableRes int getEditButtonDrawable(LoginChoiceModel model) {
         return R.drawable.btn_info;
     }
 
     @Override
-    protected String getEditButtonContentDescription(AssistantLoginChoice choice) {
-        if (choice.getEditButtonContentDescription() != null) {
-            return choice.getEditButtonContentDescription();
+    protected String getEditButtonContentDescription(LoginChoiceModel model) {
+        if (model.mOption.getEditButtonContentDescription() != null) {
+            return model.mOption.getEditButtonContentDescription();
         } else {
             return mContext.getString(R.string.learn_more);
         }
@@ -79,24 +81,23 @@
 
     @Override
     protected boolean areEqual(
-            @Nullable AssistantLoginChoice optionA, @Nullable AssistantLoginChoice optionB) {
-        if (optionA == null || optionB == null) {
-            return optionA == optionB;
+            @Nullable LoginChoiceModel modelA, @Nullable LoginChoiceModel modelB) {
+        if (modelA == null || modelB == null) {
+            return modelA == modelB;
         }
         // Native ensures that each login choice has a unique identifier.
-        return TextUtils.equals(optionA.getIdentifier(), optionB.getIdentifier());
+        return TextUtils.equals(modelA.mOption.getIdentifier(), modelB.mOption.getIdentifier());
     }
 
     /**
      * The login options have changed externally. This will rebuild the UI with the new/changed
      * set of login options, while keeping the selected item if possible.
      */
-    void onLoginsChanged(List<AssistantLoginChoice> options) {
+    void onLoginsChanged(List<LoginChoiceModel> options) {
         int indexToSelect = -1;
         if (mSelectedOption != null) {
             for (int i = 0; i < getItems().size(); i++) {
-                if (TextUtils.equals(
-                            mSelectedOption.getIdentifier(), getItems().get(i).getIdentifier())) {
+                if (areEqual(mSelectedOption, getItems().get(i))) {
                     indexToSelect = i;
                     break;
                 }
@@ -108,7 +109,7 @@
         if (indexToSelect == -1) {
             int highestPriority = Integer.MAX_VALUE;
             for (int i = 0; i < options.size(); i++) {
-                int priority = options.get(i).getPriority();
+                int priority = options.get(i).mOption.getPriority();
                 if (priority < highestPriority) {
                     highestPriority = priority;
                     indexToSelect = i;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninChecker.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninChecker.java
index efac4c05..9546c78 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninChecker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninChecker.java
@@ -12,6 +12,7 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Log;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.signin.services.SigninManager;
@@ -157,11 +158,11 @@
                 };
                 boolean shouldWipeData = ChromeFeatureList.isEnabled(
                         ChromeFeatureList.WIPE_DATA_ON_CHILD_ACCOUNT_SIGNIN);
-                SyncUserDataWiper.wipeSyncUserDataIfRequired(shouldWipeData)
-                        .then((Void v)
-                                        -> mSigninManager.signinAndEnableSync(
-                                                SigninAccessPoint.FORCED_SIGNIN, account,
-                                                signInCallback));
+                SyncUserDataWiper.wipeSyncUserDataIfRequired(shouldWipeData).then((Void v) -> {
+                    RecordUserAction.record("Signin_Signin_WipeDataOnChildAccountSignin");
+                    mSigninManager.signinAndEnableSync(
+                            SigninAccessPoint.FORCED_SIGNIN, account, signInCallback);
+                });
                 return;
             }
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
index 2a823ad..adab00c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java
@@ -596,9 +596,7 @@
     @Override
     public void isAccountManaged(String email, final Callback<Boolean> callback) {
         assert email != null;
-        CoreAccountInfo account =
-                mIdentityManager.findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                        email);
+        CoreAccountInfo account = mIdentityManager.findExtendedAccountInfoByEmailAddress(email);
         assert account != null;
         SigninManagerImplJni.get().isAccountManaged(mNativeSigninManagerAndroid, account, callback);
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java
index 79980a5..c55e515d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninCheckerTest.java
@@ -26,6 +26,7 @@
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.FlakyTest;
+import org.chromium.base.test.util.UserActionTester;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -148,6 +149,7 @@
     @MediumTest
     public void signinWhenChildAccountIsTheOnlyAccount() {
         mActivityTestRule.startMainActivityOnBlankPage();
+        UserActionTester actionTester = new UserActionTester();
 
         final CoreAccountInfo expectedPrimaryAccount =
                 mAccountManagerTestRule.addAccountAndWaitForSeeding(CHILD_ACCOUNT_EMAIL);
@@ -157,12 +159,15 @@
                     mAccountManagerTestRule.getCurrentSignedInAccount());
         });
         Assert.assertEquals(2, SigninHelperProvider.get().getNumOfChildAccountChecksDoneForTests());
+        Assert.assertTrue(
+                actionTester.getActions().contains("Signin_Signin_WipeDataOnChildAccountSignin"));
     }
 
     @Test
     @MediumTest
     public void noSigninWhenChildAccountIsTheOnlyAccountButSigninIsNotAllowed() {
         mActivityTestRule.startMainActivityOnBlankPage();
+        UserActionTester actionTester = new UserActionTester();
         when(mExternalAuthUtilsMock.isGooglePlayServicesMissing(any())).thenReturn(true);
         ExternalAuthUtils.setInstanceForTesting(mExternalAuthUtilsMock);
 
@@ -174,6 +179,8 @@
             return SigninHelperProvider.get().getNumOfChildAccountChecksDoneForTests() == 2;
         });
         Assert.assertNull(mAccountManagerTestRule.getCurrentSignedInAccount());
+        Assert.assertFalse(
+                actionTester.getActions().contains("Signin_Signin_WipeDataOnChildAccountSignin"));
     }
 
     @Test
@@ -183,12 +190,15 @@
         mAccountManagerTestRule.addAccount(CHILD_ACCOUNT_EMAIL);
 
         mActivityTestRule.startMainActivityOnBlankPage();
+        UserActionTester actionTester = new UserActionTester();
 
         // The check should be done once at activity start-up
         CriteriaHelper.pollUiThread(() -> {
             return SigninHelperProvider.get().getNumOfChildAccountChecksDoneForTests() == 1;
         });
         Assert.assertNull(mAccountManagerTestRule.getCurrentSignedInAccount());
+        Assert.assertFalse(
+                actionTester.getActions().contains("Signin_Signin_WipeDataOnChildAccountSignin"));
     }
 
     @Test
@@ -198,11 +208,14 @@
         mAccountManagerTestRule.addAccount("the.second.account@gmail.com");
 
         mActivityTestRule.startMainActivityOnBlankPage();
+        UserActionTester actionTester = new UserActionTester();
 
         // The check should be done once at activity start-up
         CriteriaHelper.pollUiThread(() -> {
             return SigninHelperProvider.get().getNumOfChildAccountChecksDoneForTests() == 1;
         });
         Assert.assertNull(mAccountManagerTestRule.getCurrentSignedInAccount());
+        Assert.assertFalse(
+                actionTester.getActions().contains("Signin_Signin_WipeDataOnChildAccountSignin"));
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java
index a118132..fee9a7d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerImplTest.java
@@ -94,9 +94,8 @@
         })
                 .when(mAccountTrackerService)
                 .seedAccountsIfNeeded(any(Runnable.class));
-        when(mIdentityManagerNativeMock
-                        .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                                NATIVE_IDENTITY_MANAGER, ACCOUNT_INFO.getEmail()))
+        when(mIdentityManagerNativeMock.findExtendedAccountInfoByEmailAddress(
+                     NATIVE_IDENTITY_MANAGER, ACCOUNT_INFO.getEmail()))
                 .thenReturn(ACCOUNT_INFO);
 
         mSigninManager = (SigninManagerImpl) SigninManagerImpl.create(
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 96b61a5..8bdbb5f2 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-93.0.4529.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-93.0.4530.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 100eb78..1f84d79 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4426,6 +4426,19 @@
         The folder you selected contains sensitive files. Are you sure you want to grant "<ph name="APP_NAME">$1<ex>Text</ex></ph>" permanent write access to this folder?
       </message>
 
+      <!-- Direct Sockets connection dialog -->
+      <if expr="not is_android">
+        <message name="IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_TITLE_LABEL" desc="Name shown in the direct sockets connection dialog's title">
+          Connection Dialog
+        </message>
+        <message name="IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_ADDRESS_LABEL" desc="The remote host name that direct sockets will connect to">
+          Address
+        </message>
+        <message name="IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_PORT_LABEL" desc="The remote port number that direct sockets will connect to">
+          Port
+        </message>
+      </if>
+
       <!-- Extensions strings, which are not used by chrome://extensions. -->
       <if expr="enable_extensions">
         <message name="IDS_EXTENSIONS_LOAD_ERROR_ALERT_HEADING" desc="The title of the section that describes an extension load error.">
diff --git a/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_ADDRESS_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_ADDRESS_LABEL.png.sha1
new file mode 100644
index 0000000..189ed3f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_ADDRESS_LABEL.png.sha1
@@ -0,0 +1 @@
+a0d3a329339a79c0f140a8b895cc4343eb253481
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_PORT_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_PORT_LABEL.png.sha1
new file mode 100644
index 0000000..189ed3f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_PORT_LABEL.png.sha1
@@ -0,0 +1 @@
+a0d3a329339a79c0f140a8b895cc4343eb253481
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_TITLE_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_TITLE_LABEL.png.sha1
new file mode 100644
index 0000000..189ed3f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_TITLE_LABEL.png.sha1
@@ -0,0 +1 @@
+a0d3a329339a79c0f140a8b895cc4343eb253481
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 3a6bb12..fcebfb3 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -16,6 +16,9 @@
   <message name="IDS_SETTINGS_DISMISS" desc="Label to dismiss a shortcut reminder.">
     Dismiss
   </message>
+  <message name="IDS_SETTINGS_SHORTCUT_BANNER_DISMISSED" desc="The message spoken aloud by screen readers when the user dismisses a banner showing keyboard shortcuts.">
+    Keyboard shortcut notice dismissed
+  </message>
 
   <!--Main Page-->
   <message name="IDS_SETTINGS_SECONDARY_USER_BANNER" desc="Banner displayed in settings page when the user is secondary in a multi-profile session.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SHORTCUT_BANNER_DISMISSED.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SHORTCUT_BANNER_DISMISSED.png.sha1
new file mode 100644
index 0000000..90b53a4
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_SHORTCUT_BANNER_DISMISSED.png.sha1
@@ -0,0 +1 @@
+35e31d0a4aeb6eb667791d2912662cc420e9b874
\ No newline at end of file
diff --git a/chrome/app/resources/generated_resources_af.xtb b/chrome/app/resources/generated_resources_af.xtb
index 43b330a..767a1d8 100644
--- a/chrome/app/resources/generated_resources_af.xtb
+++ b/chrome/app/resources/generated_resources_af.xtb
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">JavaScript-geheue</translation>
 <translation id="7685087414635069102">PIN word vereis</translation>
 <translation id="768549422429443215">Voeg tale by of herrangskik lys.</translation>
-<translation id="7686424868232681412">Lacros is 'n eksperimentele blaaier. Gee kwessies aan met Hulp &gt; "Gee 'n kwessie aan …".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bevestig nuwe wagwoord</translation>
 <translation id="7690378713476594306">Kies uit lys</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index e2d93bd..43ea5ad 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -5185,7 +5185,7 @@
 <translation id="6654509035557065241">ተመራጭ አውታረ መረብ</translation>
 <translation id="6655190889273724601">የገንቢ ሁነት</translation>
 <translation id="6655458902729017087">መለያዎችን ደብቅ</translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6659213950629089752">ይህ ገጽ በ«<ph name="NAME" />» ቅጥያው ነው የጎላው</translation>
 <translation id="6659594942844771486">ትር</translation>
 <translation id="6660413144148052430">አካባቢ</translation>
@@ -6123,7 +6123,6 @@
 <translation id="7685049629764448582">ጃቫስክሪፕት ማህደረ ትውስታ</translation>
 <translation id="7685087414635069102">ፒን ያስፈልጋል</translation>
 <translation id="768549422429443215">ቋንቋዎችን ያክሉ ወይም ዝርዝርን ዳግም ያደራጁ።</translation>
-<translation id="7686424868232681412">Lacros የሙከራ አሳሽ ነው። እባክዎ ችግሮችን በሚከተሉት ሪፖርት ያድርጉ፦ እገዛ &gt; «ችግርን ሪፖርት አድርግ...»።</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">አዲስ የይለፍ ቃል ያረጋግጡ</translation>
 <translation id="7690378713476594306">ከዝርዝር ይምረጡ</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 4344493..706370b 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -6119,7 +6119,6 @@
 <translation id="7685049629764448582">‏ذاكرة JavaScript</translation>
 <translation id="7685087414635069102">رقم التعريف الشخصي مطلوب</translation>
 <translation id="768549422429443215">يمكنك إضافة اللغات أو إعادة ترتيب القائمة.</translation>
-<translation id="7686424868232681412">‏Lacros هو متصفِّح تجريبي. يُرجى الإبلاغ عن أي مشاكل من خلال الانتقال إلى: مساعدة &gt; "الإبلاغ عن مشكلة...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">تأكيد كلمة المرور الجديدة</translation>
 <translation id="7690378713476594306">اختيار من القائمة</translation>
diff --git a/chrome/app/resources/generated_resources_as.xtb b/chrome/app/resources/generated_resources_as.xtb
index 0c17e32f9..10aac1b 100644
--- a/chrome/app/resources/generated_resources_as.xtb
+++ b/chrome/app/resources/generated_resources_as.xtb
@@ -6117,7 +6117,6 @@
 <translation id="7685049629764448582">JavaScript মেম’ৰী</translation>
 <translation id="7685087414635069102">পিনৰ প্ৰয়োজন</translation>
 <translation id="768549422429443215">ভাষাবোৰ যোগ কৰক অথবা সূচীখনৰ ক্ৰম সলনি কৰক।</translation>
-<translation id="7686424868232681412">Lacros হৈছে এটা পৰীক্ষামূলক ব্ৰাউজাৰ। অনুগ্ৰহ কৰি ইয়াৰ জৰিয়তে সমস্যাৰ অভিযোগ দিয়ক: সহায় &gt; "সমস্যাৰ অভিযোগ দিয়ক…"।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">নতুন পাছৱর্ড নিশ্চিত কৰক</translation>
 <translation id="7690378713476594306">সূচীৰ পৰা বাছনি কৰক</translation>
diff --git a/chrome/app/resources/generated_resources_az.xtb b/chrome/app/resources/generated_resources_az.xtb
index 20b6bcf2..fd1a448 100644
--- a/chrome/app/resources/generated_resources_az.xtb
+++ b/chrome/app/resources/generated_resources_az.xtb
@@ -6110,7 +6110,6 @@
 <translation id="7685049629764448582">JavaScript yaddaşı</translation>
 <translation id="7685087414635069102">PIN tələb olunur</translation>
 <translation id="768549422429443215">Dillər əlavə edin və ya siyahını yenidən sıralayın.</translation>
-<translation id="7686424868232681412">Lacros eksperimental brauzerdir. Yardım &gt; "Problem barədə bildirin..." vasitəsilə problemlər barədə bildirin.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Yeni parolu təsdiq edin</translation>
 <translation id="7690378713476594306">Siyahıdan seçin</translation>
diff --git a/chrome/app/resources/generated_resources_be.xtb b/chrome/app/resources/generated_resources_be.xtb
index 1105d60..5eef047 100644
--- a/chrome/app/resources/generated_resources_be.xtb
+++ b/chrome/app/resources/generated_resources_be.xtb
@@ -6113,7 +6113,6 @@
 <translation id="7685049629764448582">Памяць JavaScript</translation>
 <translation id="7685087414635069102">Патрабуецца PIN-код</translation>
 <translation id="768549422429443215">Дадайце мовы або змяніце іх парадак у спісе.</translation>
-<translation id="7686424868232681412">Lacros — гэта эксперыментальны браўзер. Просім вас паведамляць пра праблемы праз меню "Даведка &gt; Паведаміць аб праблеме...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Пацвердзіце новы пароль</translation>
 <translation id="7690378713476594306">Выбраць са спіса</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index ddd149d48..b773ab9 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -678,6 +678,7 @@
 <translation id="1706625117072057435">Нива на мащаба</translation>
 <translation id="1708338024780164500">(Неактивно)</translation>
 <translation id="1708713382908678956"><ph name="NAME_PH" /> (идент. №: <ph name="ID_PH" />)</translation>
+<translation id="1708860176443612387">Експериментален браузър! Възможна е загуба на данни или компрометиране на поверителността или сигурността. Отворете „Помощ &gt; Подаване на сигнал за проблем...“, за да сигнализирате за проблеми.</translation>
 <translation id="1709106626015023981"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (стандартно)</translation>
 <translation id="1709217939274742847">Изберете пропуск, който да използвате за удостоверяване. <ph name="LINK_BEGIN" />Научете повече<ph name="LINK_END" /></translation>
 <translation id="1709972045049031556">Споделянето не е възможно</translation>
@@ -1096,6 +1097,7 @@
 <translation id="2144557304298909478">Разработване на приложения за Android в Linux</translation>
 <translation id="2146263598007866206">Сайтовете може автоматично да изтеглят сродни файлове, за да ви спестят време</translation>
 <translation id="2147151613919729065">За да изчистите историята в режим на гост, затворете всички прозорци в този режим.</translation>
+<translation id="2147218225094845757">Скриване на страничния панел</translation>
 <translation id="2148219725039824548">Възникна грешка при свързването на посочения дял. Той не бе намерен в мрежата.</translation>
 <translation id="2148756636027685713">Форматирането завърши</translation>
 <translation id="2148892889047469596">Предаване на раздела</translation>
@@ -3949,6 +3951,7 @@
 <translation id="5269977353971873915">Отпечатването не бе успешно</translation>
 <translation id="5275352920323889391">Куче</translation>
 <translation id="527605982717517565">Да се разреши на <ph name="HOST" /> винаги да изпълнява JavaScript</translation>
+<translation id="5277127016695466621">Показване на страничния панел</translation>
 <translation id="5278823018825269962">ID на състоянието</translation>
 <translation id="5280064835262749532">Актуализирайте идентификационните данни за <ph name="SHARE_PATH" /></translation>
 <translation id="5280243692621919988">Изчистване на „бисквитките“ и данните за сайтовете, когато затворите всички прозорци</translation>
@@ -6130,7 +6133,6 @@
 <translation id="7685049629764448582">Памет за JavaScript</translation>
 <translation id="7685087414635069102">Изисква се ПИН код</translation>
 <translation id="768549422429443215">Добавяне на езици или пренареждане на списъка.</translation>
-<translation id="7686424868232681412">Lacros е експериментален браузър. Отворете „Помощ &gt; Подаване на сигнал за проблем...“, за да сигнализирате за проблеми.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Потвърдете новата парола</translation>
 <translation id="7690378713476594306">Избиране от списъка</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 47f43951b..09051ab 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -3281,7 +3281,7 @@
 <translation id="4519935350946509010">কানেকশনে সমস্যা।</translation>
 <translation id="4520385623207007473">কুকিগুলি ব্যবহার করা হচ্ছে</translation>
 <translation id="452039078290142656"><ph name="VENDOR_NAME" /> থেকে অজানা ডিভাইসগুলি</translation>
-<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4522570452068850558">বিবরণগুলি</translation>
 <translation id="4522600456902129422">সাইটটিকে ক্লিপবোর্ড দেখার অনুমতি চালু রাখুন</translation>
 <translation id="4522890784888918985">বাচ্চার অ্যাকাউন্ট কাজ করে না</translation>
 <translation id="4524832533047962394">অপারেটিং সিস্টেমের এই ভার্সনটি প্রদত্ত নথিভুক্তকরণের মোড সমর্থন করে না। আপনি সর্বাধুনিক ভার্সনটি চালাচ্ছেন কিনা দেখুন।</translation>
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">জাভাস্ক্রিপ্ট মেমরি</translation>
 <translation id="7685087414635069102">পিন প্রয়োজন</translation>
 <translation id="768549422429443215">ভাষা যোগ করুন বা তালিকাটি আবার সাজান।</translation>
-<translation id="7686424868232681412">Lacros একটি পরীক্ষামূলক ব্রাউজার। এই ব্রাউজার সম্পর্কিত যেকোনও অভিযোগ জানাতে এখানে যান: সহায়তা &gt; "কোনও একটি সমস্যার বিষয়ে অভিযোগ জানান..."।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">নতুন পাসওয়ার্ড নিশ্চিত করুন</translation>
 <translation id="7690378713476594306">তালিকা থেকে বেছে নিন</translation>
diff --git a/chrome/app/resources/generated_resources_bs.xtb b/chrome/app/resources/generated_resources_bs.xtb
index c9fc486..fee66fb 100644
--- a/chrome/app/resources/generated_resources_bs.xtb
+++ b/chrome/app/resources/generated_resources_bs.xtb
@@ -6130,7 +6130,6 @@
 <translation id="7685049629764448582">JavaScript memorija</translation>
 <translation id="7685087414635069102">Potreban je PIN</translation>
 <translation id="768549422429443215">Dodajte jezike ili preuredite listu.</translation>
-<translation id="7686424868232681412">Lacros je eksperimentalni preglednik. Prijavite probleme u odjeljku: Pomoć &gt; "Prijavite problem...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrdite novu lozinku</translation>
 <translation id="7690378713476594306">Odaberite s liste</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index 01c64686..c6b6f7d 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -6117,7 +6117,6 @@
 <translation id="7685049629764448582">Memòria de JavaScript </translation>
 <translation id="7685087414635069102">PIN obligatori</translation>
 <translation id="768549422429443215">Afegeix idiomes o torna a ordenar la llista.</translation>
-<translation id="7686424868232681412">Lacros és un navegador experimental. Informa de qualsevol problema des d'Ajuda &gt; Informa d'un problema...</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirma la contrasenya nova</translation>
 <translation id="7690378713476594306">Tria de la llista</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 78418663..3f42e83 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -6112,7 +6112,6 @@
 <translation id="7685049629764448582">Paměť JavaScriptu</translation>
 <translation id="7685087414635069102">Je vyžadován kód PIN</translation>
 <translation id="768549422429443215">Přidejte jazyky nebo přeuspořádejte seznam.</translation>
-<translation id="7686424868232681412">Lacros je experimentální prohlížeč. Problémy hlaste v sekci Nápověda &gt; Nahlásit problém…</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrďte nové heslo</translation>
 <translation id="7690378713476594306">Vybrat ze seznamu</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 166e988..f717797 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">JavaScript-hukommelse</translation>
 <translation id="7685087414635069102">Der skal angives en pinkode</translation>
 <translation id="768549422429443215">Tilføj sprog, eller omorganiser listen.</translation>
-<translation id="7686424868232681412">Lacros er en eksperimentel browser. Du kan rapportere problemer ved at gå til Hjælp &gt; "Rapportér et problem...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bekræft den nye adgangskode</translation>
 <translation id="7690378713476594306">Vælg på listen</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index 7c9dd66..3cbd7286 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -6108,7 +6108,6 @@
 <translation id="7685049629764448582">JavaScript-Speicher</translation>
 <translation id="7685087414635069102">PIN erforderlich</translation>
 <translation id="768549422429443215">Sie können Sprachen hinzufügen oder die Liste neu anordnen.</translation>
-<translation id="7686424868232681412">Lacros ist ein experimenteller Browser. Melden Sie Probleme über „Hilfe“ &gt; „Problem melden…“.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Neues Passwort bestätigen</translation>
 <translation id="7690378713476594306">Aus Liste auswählen</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index 4edb384..e623eb8 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -5195,7 +5195,7 @@
 <translation id="6654509035557065241">Προτίμηση δικτύου</translation>
 <translation id="6655190889273724601">Λειτουργία για προγραμματιστές</translation>
 <translation id="6655458902729017087">Απόκρυψη λογαριασμών</translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6659213950629089752">Έγινε εστίαση σε αυτήν τη σελίδα από την επέκταση "<ph name="NAME" />"</translation>
 <translation id="6659594942844771486">Καρτέλα</translation>
 <translation id="6660413144148052430">τοποθεσία</translation>
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">Μνήμη JavaScript</translation>
 <translation id="7685087414635069102">Απαιτείται PIN</translation>
 <translation id="768549422429443215">Προσθέστε γλώσσες ή κάντε αναδιάταξη της λίστας.</translation>
-<translation id="7686424868232681412">Το Lacros είναι ένα πειραματικό πρόγραμμα περιήγησης. Αναφέρετε τυχόν προβλήματα στην ενότητα: Βοήθεια &gt; Αναφορά προβλήματος…</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Επιβεβαίωση νέου κωδικού πρόσβασης</translation>
 <translation id="7690378713476594306">Επιλογή από τη λίστα</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index deb1ef2c..25486ca3 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">JavaScript memory</translation>
 <translation id="7685087414635069102">PIN required</translation>
 <translation id="768549422429443215">Add languages or reorder list.</translation>
-<translation id="7686424868232681412">Lacros is an experimental browser. Please report issues with: Help &gt; 'Report an issue…'</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirm new password</translation>
 <translation id="7690378713476594306">Choose from list</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index 66ecca8..ae00325 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -6113,7 +6113,6 @@
 <translation id="7685049629764448582">Memoria de JavaScript</translation>
 <translation id="7685087414635069102">Se requiere el PIN</translation>
 <translation id="768549422429443215">Agrega idiomas o cambia el orden de la lista.</translation>
-<translation id="7686424868232681412">Lacros es un navegador experimental. Para informar problemas, usa la opción Ayuda &gt; "Informar un problema…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar contraseña nueva</translation>
 <translation id="7690378713476594306">Elegir de la lista</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index 6bd1e0b..ee5d1b89 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -6115,7 +6115,6 @@
 <translation id="7685049629764448582">Memoria de JavaScript</translation>
 <translation id="7685087414635069102">PIN necesario</translation>
 <translation id="768549422429443215">Añadir o reordenar idiomas</translation>
-<translation id="7686424868232681412">Lacros es un navegador experimental. Para informar de cualquier problema, ve a Ayuda &gt; Notificar un problema.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirma la nueva contraseña</translation>
 <translation id="7690378713476594306">Elegir una opción de la lista</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index 91c37e1..d511f93 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -6122,7 +6122,6 @@
 <translation id="7685049629764448582">JavaScripti mälu</translation>
 <translation id="7685087414635069102">PIN-kood on kohustuslik</translation>
 <translation id="768549422429443215">Saate keeli lisada või nende loendit ümber järjestada.</translation>
-<translation id="7686424868232681412">Lacros on katseline brauser. Teavitage probleemidest valikutega Abi &gt; „Probleemist teavitamine …”.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Kinnitage uus parool</translation>
 <translation id="7690378713476594306">Vali loendist</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb
index ece3354..330c064 100644
--- a/chrome/app/resources/generated_resources_eu.xtb
+++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -6115,7 +6115,6 @@
 <translation id="7685049629764448582">JavaScript memoria</translation>
 <translation id="7685087414635069102">PINa behar da</translation>
 <translation id="768549422429443215">Gehitu hizkuntzak edo aldatu zerrendako elementuen ordena.</translation>
-<translation id="7686424868232681412">Probako arakatzaile bat da Lacros. Arazoren bat aurkituz gero, jakinaraz ezazu hemen: Laguntza &gt; "Eman arazo baten berri…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Berretsi pasahitz berria</translation>
 <translation id="7690378713476594306">Aukeratu zerrendatik</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index e763d9f..7e28931d 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -6129,7 +6129,6 @@
 <translation id="7685049629764448582">حافطه جاوا اسکریپت</translation>
 <translation id="7685087414635069102">پین موردنیاز است</translation>
 <translation id="768549422429443215">افزودن زبان یا مرتب‌سازی مجدد فهرست.</translation>
-<translation id="7686424868232681412">‏Lacros مرورگری آزمایشی است. لطفاً مشکلات را ازطریق «راهنمایی &gt; گزارش مشکل…» گزارش کنید.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> <ph name="DEVICE_PATH" /></translation>
 <translation id="7690294790491645610">تأیید گذرواژه جدید</translation>
 <translation id="7690378713476594306">انتخاب از فهرست</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index c11a271..2c97ad2 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -6128,7 +6128,6 @@
 <translation id="7685049629764448582">JavaScriptin käyttämä muisti</translation>
 <translation id="7685087414635069102">PIN-koodi vaaditaan</translation>
 <translation id="768549422429443215">Lisää kieliä tai järjestä lista uudelleen.</translation>
-<translation id="7686424868232681412">Lacros on kokeellinen selain. Ilmoita ongelmista kohdassa Ohje &gt; "Ilmoita ongelmasta…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Vahvista uusi salasana</translation>
 <translation id="7690378713476594306">Valitse luettelosta</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index 9b24702..b668e6c4 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">Memorya sa JavaScript</translation>
 <translation id="7685087414635069102">Kailangan ng PIN</translation>
 <translation id="768549422429443215">Magdagdag ng mga wika o baguhin ang pagkakasunud-sunod ng listahan.</translation>
-<translation id="7686424868232681412">Isang pang-eksperimentong Browser ang Lacros. Pakiulat ang mga isyu sa: Tulong &gt; "Mag-ulat ng isyu...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Kumpirmahin ang bagong password</translation>
 <translation id="7690378713476594306">Pumili sa listahan</translation>
diff --git a/chrome/app/resources/generated_resources_fr-CA.xtb b/chrome/app/resources/generated_resources_fr-CA.xtb
index 40063e9b..808a9dd 100644
--- a/chrome/app/resources/generated_resources_fr-CA.xtb
+++ b/chrome/app/resources/generated_resources_fr-CA.xtb
@@ -6118,7 +6118,6 @@
 <translation id="7685049629764448582">Mémoire pour JavaScript</translation>
 <translation id="7685087414635069102">NIP requis</translation>
 <translation id="768549422429443215">Ajoutez des langues ou triez la liste de nouveau.</translation>
-<translation id="7686424868232681412">Lacros est un navigateur expérimental. Veuillez signaler tout problème en sélectionnant Aide &gt; « Signaler un problème… ».</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmez le nouveau mot de passe</translation>
 <translation id="7690378713476594306">Choisir dans la liste</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index 8a3d540a..2cd516f 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -6118,7 +6118,6 @@
 <translation id="7685049629764448582">Mémoire JavaScript </translation>
 <translation id="7685087414635069102">Veuillez saisir un code</translation>
 <translation id="768549422429443215">Ajoutez des langues ou réorganisez la liste.</translation>
-<translation id="7686424868232681412">Lacros est un navigateur expérimental. Si vous relevez un problème, sélectionnez Aide &gt; Signaler un problème.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmer le nouveau mot de passe</translation>
 <translation id="7690378713476594306">Choisir dans la liste</translation>
diff --git a/chrome/app/resources/generated_resources_gl.xtb b/chrome/app/resources/generated_resources_gl.xtb
index bd23d7fa6..130e791 100644
--- a/chrome/app/resources/generated_resources_gl.xtb
+++ b/chrome/app/resources/generated_resources_gl.xtb
@@ -6114,7 +6114,6 @@
 <translation id="7685049629764448582">Memoria JavaScript</translation>
 <translation id="7685087414635069102">PIN obrigatorio</translation>
 <translation id="768549422429443215">Engade idiomas ou reordena a lista.</translation>
-<translation id="7686424868232681412">Lacros é un navegador experimental. Se tes algún problema, indícanolo en Axuda &gt; Informar dun problema...</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar contrasinal novo</translation>
 <translation id="7690378713476594306">Escoller unha opción da lista</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index d0631b7..c93708b 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">JavaScript મેમરી</translation>
 <translation id="7685087414635069102">પિન જરૂરી છે</translation>
 <translation id="768549422429443215">ભાષાઓ ઉમેરો અથવા સૂચિને પુનઃક્રમાંકિત કરો.</translation>
-<translation id="7686424868232681412">Lacros, એક પ્રયોગાત્મક બ્રાઉઝર છે. આ સંબંધિત સમસ્યાની જાણ કરવા માટે, કૃપા કરીને અહીં જાઓ: સહાય &gt; "સમસ્યાની જાણ કરો…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">નવા પાસવર્ડની પુષ્ટિ કરો</translation>
 <translation id="7690378713476594306">સૂચિમાંથી પસંદ કરો</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index 9472039a7..9514567b 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -6131,7 +6131,6 @@
 <translation id="7685049629764448582">JavaScript मेमोरी</translation>
 <translation id="7685087414635069102">पिन की ज़रूरत है</translation>
 <translation id="768549422429443215">भाषाएं जोड़ें या सूची का क्रम बदलें.</translation>
-<translation id="7686424868232681412">Lacros ब्राउज़र को लेकर अभी प्रयोग चल रहा है. इससे जुड़ी किसी भी समस्या की शिकायत करने के लिए, कृपया यहां जाएं: सहायता &gt; "समस्या की शिकायत करें...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">नए पासवर्ड की पुष्टि करें</translation>
 <translation id="7690378713476594306">सूची में से चुनें</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index 2c405c6..fbc4edb 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -3268,7 +3268,7 @@
 <translation id="4519935350946509010">Pogreška veze.</translation>
 <translation id="4520385623207007473">Upotreba kolačića</translation>
 <translation id="452039078290142656">nepoznati uređaji dobavljača <ph name="VENDOR_NAME" /></translation>
-<translation id="4522570452068850558">Detalji</translation>
+<translation id="4522570452068850558">Pojedinosti</translation>
 <translation id="4522600456902129422">Nastavi dopuštati ovoj web-lokaciji uvid u međuspremnik</translation>
 <translation id="4522890784888918985">Podređeni računi nisu podržani</translation>
 <translation id="4524832533047962394">Ova verzija operativnog sustava ne podržava uneseni način prijave. Provjerite upotrebljavate li najnoviju verziju.</translation>
@@ -6118,7 +6118,6 @@
 <translation id="7685049629764448582">Memorija JavaScripta</translation>
 <translation id="7685087414635069102">Potreban je PIN</translation>
 <translation id="768549422429443215">Dodajte jezike ili promijenite redoslijed popisa.</translation>
-<translation id="7686424868232681412">Lacros je eksperimentalni preglednik. Poteškoće prijavite putem odjeljka Pomoć &gt; Prijavite poteškoću...</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrdite novu zaporku</translation>
 <translation id="7690378713476594306">Odaberi s popisa</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index ff94f35f..6f819863 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -6131,7 +6131,6 @@
 <translation id="7685049629764448582">JavaScript memória</translation>
 <translation id="7685087414635069102">PIN-kód megadása kötelező</translation>
 <translation id="768549422429443215">Hozzáadhat nyelveket és átrendezheti a listát.</translation>
-<translation id="7686424868232681412">A Lacros egy kísérleti böngésző. A hibákat a Súgó „Probléma bejelentése...” pontjában jelentheti be.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Új jelszó megerősítése</translation>
 <translation id="7690378713476594306">Választás listából</translation>
diff --git a/chrome/app/resources/generated_resources_hy.xtb b/chrome/app/resources/generated_resources_hy.xtb
index f62567f..3c118ad 100644
--- a/chrome/app/resources/generated_resources_hy.xtb
+++ b/chrome/app/resources/generated_resources_hy.xtb
@@ -6120,7 +6120,6 @@
 <translation id="7685049629764448582">JavaScript հիշողություն</translation>
 <translation id="7685087414635069102">Պահանջվում է PIN կոդ</translation>
 <translation id="768549422429443215">Ավելացրեք լեզուներ կամ վերադասավորեք ցանկը։</translation>
-<translation id="7686424868232681412">Lacros-ը փորձնական դիտարկիչ է։ Խնդիրների մասին կարող եք հաղորդել՝ սեղմելով Օգնություն &gt; «Հաղորդել խնդրի մասին»։</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Հաստատեք նոր գաղտնաբառը</translation>
 <translation id="7690378713476594306">Ընտրել ցանկից</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index f4d8d7a..98c74614b 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">Memori JavaScript</translation>
 <translation id="7685087414635069102">Perlu PIN</translation>
 <translation id="768549422429443215">Tambahkan bahasa atau urutkan ulang daftar.</translation>
-<translation id="7686424868232681412">Lacros adalah Browser eksperimental. Laporkan masalah melalui: Bantuan &gt; "Laporkan masalah ...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Konfirmasi sandi baru</translation>
 <translation id="7690378713476594306">Pilih dari daftar</translation>
diff --git a/chrome/app/resources/generated_resources_is.xtb b/chrome/app/resources/generated_resources_is.xtb
index 651bffc..662ad2c 100644
--- a/chrome/app/resources/generated_resources_is.xtb
+++ b/chrome/app/resources/generated_resources_is.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">JavaScript-minni</translation>
 <translation id="7685087414635069102">PIN-númers krafist</translation>
 <translation id="768549422429443215">Bæta við tungumálum eða endurraða lista.</translation>
-<translation id="7686424868232681412">Lacros er vafri á tilraunastigi. Tilkynntu vandamál með: Hjálp &gt; „Tilkynna vandamál…“</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Staðfestu nýtt aðgangsorð</translation>
 <translation id="7690378713476594306">Velja af lista</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index 13035706..9236051f 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">Memoria JavaScript</translation>
 <translation id="7685087414635069102">PIN obbligatorio</translation>
 <translation id="768549422429443215">Aggiungi lingue o cambia l'ordine dell'elenco.</translation>
-<translation id="7686424868232681412">Lacros è un browser sperimentale. Segnala eventuali problemi selezionando Guida &gt; "Segnala un problema".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Conferma nuova password</translation>
 <translation id="7690378713476594306">Scegli dall'elenco</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index debd728..84942c6 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">‏זיכרון JavaScript</translation>
 <translation id="7685087414635069102">נדרש קוד אימות</translation>
 <translation id="768549422429443215">הוספת שפות או שינוי סדר הרשימה.</translation>
-<translation id="7686424868232681412">‏Lacros הוא דפדפן ניסיוני. אפשר לדווח על בעיות דרך: 'עזרה' &gt; "דיווח על בעיה…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">אישור הסיסמה החדשה</translation>
 <translation id="7690378713476594306">בחירה מתוך רשימה</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 8d6af7f49..b98cf415 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">JavaScript メモリ</translation>
 <translation id="7685087414635069102">PIN が必要です</translation>
 <translation id="768549422429443215">言語を追加するか、リストを並べ替えます。</translation>
-<translation id="7686424868232681412">Lacros は試験運用版のブラウザです。問題が発生した場合は、[ヘルプ] &gt; [問題の報告...] からご報告ください。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" />(<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">新しいパスワードの確認入力</translation>
 <translation id="7690378713476594306">リストから選択</translation>
diff --git a/chrome/app/resources/generated_resources_ka.xtb b/chrome/app/resources/generated_resources_ka.xtb
index 118312d..e8fc4cc 100644
--- a/chrome/app/resources/generated_resources_ka.xtb
+++ b/chrome/app/resources/generated_resources_ka.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">JavaScript მეხსიერება</translation>
 <translation id="7685087414635069102">საჭიროა PIN-კოდი</translation>
 <translation id="768549422429443215">დაამატეთ ენები, ან შეცვალეთ სიის მიმდევრობა.</translation>
-<translation id="7686424868232681412">Lacros ექსპერიმენტული ბრაუზერია. პრობლემების შესატყობინებლად გადადით აქ: დახმარება &gt; „შეტყობინება პრობლემის შესახებ...“.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">დაადასტურეთ ახალი პაროლი</translation>
 <translation id="7690378713476594306">სიიდან არჩევა</translation>
diff --git a/chrome/app/resources/generated_resources_kk.xtb b/chrome/app/resources/generated_resources_kk.xtb
index ec500c1..e59307f 100644
--- a/chrome/app/resources/generated_resources_kk.xtb
+++ b/chrome/app/resources/generated_resources_kk.xtb
@@ -6112,7 +6112,6 @@
 <translation id="7685049629764448582">JavaScript жады</translation>
 <translation id="7685087414635069102">PIN коды қажет</translation>
 <translation id="768549422429443215">Тілдерді енгізіңіз немесе тізімнің ретін өзгертіңіз.</translation>
-<translation id="7686424868232681412">Lacros – эксперименттік браузер. Ондағы кез келген ақауды "Анықтама &gt; Ақау туралы хабарлау" тармағы арқылы көрсетіңіз.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Жаңа құпия сөзді қайталаңыз</translation>
 <translation id="7690378713476594306">Тізімнен таңдау</translation>
diff --git a/chrome/app/resources/generated_resources_km.xtb b/chrome/app/resources/generated_resources_km.xtb
index ffaa159a..3d9917e 100644
--- a/chrome/app/resources/generated_resources_km.xtb
+++ b/chrome/app/resources/generated_resources_km.xtb
@@ -682,6 +682,7 @@
 <translation id="1706625117072057435">កម្រិតពង្រីក</translation>
 <translation id="1708338024780164500">(គ្មានសកម្មភាព)</translation>
 <translation id="1708713382908678956"><ph name="NAME_PH" /> (លេខសម្គាល់៖ <ph name="ID_PH" />)</translation>
+<translation id="1708860176443612387">កម្មវិធីរុករកតាមអ៊ីនធឺណិត​សាកល្បង! អាចបាត់បង់ទិន្នន័យ ឬរងការវាយលុក​ដល់​ឯកជនភាព​ឬសុវត្ថិភាព។ សូមរាយការណ៍​អំពីបញ្ហា​តាមរយៈ៖ ជំនួយ &gt; "រាយការណ៍អំពីបញ្ហា..."។</translation>
 <translation id="1709106626015023981"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (ដើម)</translation>
 <translation id="1709217939274742847">សូមជ្រើសរើស​សំបុត្រ ដើម្បីប្រើសម្រាប់​ការផ្ទៀងផ្ទាត់។ <ph name="LINK_BEGIN" />ស្វែងយល់បន្ថែម<ph name="LINK_END" /></translation>
 <translation id="1709972045049031556">មិនអាច​ចែករំលែក​បានទេ</translation>
@@ -1100,6 +1101,7 @@
 <translation id="2144557304298909478">ការអភិវឌ្ឍកម្មវិធី Android នៅក្នុង Linux</translation>
 <translation id="2146263598007866206">គេហទំព័រអាចទាញយកឯកសារដែលពាក់ព័ន្ធរួមគ្នាដោយស្វ័យប្រវត្តិ ដើម្បីជួយសន្សំពេលរបស់អ្នក</translation>
 <translation id="2147151613919729065">ដើម្បីសម្អាតប្រវត្តិមុខងារភ្ញៀវ សូមបិទវិនដូភ្ញៀវទាំងអស់។</translation>
+<translation id="2147218225094845757">លាក់​ផ្ទាំង​ចំហៀង</translation>
 <translation id="2148219725039824548">មានបញ្ហា​ក្នុងការភ្ជាប់​ការចែក​រំលែក។ រកមិនឃើញ​ការចែក​រំលែក​ដែលបានបញ្ជាក់​នៅលើ​បណ្ដាញទេ។</translation>
 <translation id="2148756636027685713">ការសម្អាតបានបញ្ចប់</translation>
 <translation id="2148892889047469596">ខាសផ្ទាំង</translation>
@@ -3952,6 +3954,7 @@
 <translation id="5269977353971873915">ការបោះពុម្ពបានបរាជ័យ</translation>
 <translation id="5275352920323889391">ឆ្កែ</translation>
 <translation id="527605982717517565">អនុញ្ញាតឲ្យ JavaScript នៅលើ <ph name="HOST" /> ជានិច្ច</translation>
+<translation id="5277127016695466621">បង្ហាញ​ផ្ទាំង​ចំហៀង</translation>
 <translation id="5278823018825269962">លេខសម្គាល់​ស្ថានភាព</translation>
 <translation id="5280064835262749532">ធ្វើបច្ចុប្បន្នភាព​ព័ត៌មាន​ផ្ទៀងផ្ទាត់សម្រាប់ <ph name="SHARE_PATH" /></translation>
 <translation id="5280243692621919988">សម្អាត​ខូគី និង​ទិន្នន័យ​គេហទំព័រ នៅពេល​អ្នក​បិទ​វិនដូ​ទាំងអស់</translation>
@@ -6133,7 +6136,6 @@
 <translation id="7685049629764448582">មេម៉ូរី JavaScript</translation>
 <translation id="7685087414635069102">តម្រូវឱ្យមានកូដ PIN</translation>
 <translation id="768549422429443215">បញ្ចូលភាសា ឬ​តម្រៀបបញ្ជី​ឡើងវិញ។</translation>
-<translation id="7686424868232681412">Lacros គឺជាកម្មវិធីរុករក​តាមអ៊ីនធឺណិត​សាកល្បង។ សូមរាយការណ៍​អំពីបញ្ហា​តាមរយៈ៖ ជំនួយ &gt; "រាយការណ៍អំពីបញ្ហា..."។</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">បញ្ជាក់​ពាក្យ​សម្ងាត់​ថ្មី</translation>
 <translation id="7690378713476594306">ជ្រើសរើស​ពី​បញ្ជី</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index 551f052..34302cc 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -6127,7 +6127,6 @@
 <translation id="7685049629764448582">JavaScript ಸ್ಮರಣೆ</translation>
 <translation id="7685087414635069102">ಪಿನ್ ಅಗತ್ಯವಿದೆ</translation>
 <translation id="768549422429443215">ಭಾಷೆಗಳನ್ನು ಸೇರಿಸಿ ಅಥವಾ ಪಟ್ಟಿಯನ್ನು ಮರುಕ್ರಮಗೊಳಿಸಿ.</translation>
-<translation id="7686424868232681412">Lacros ಪ್ರಾಯೋಗಿಕ ಬ್ರೌಸರ್ ಆಗಿದೆ. ಯಾವುದೇ ಸಮಸ್ಯೆಗಳಿದ್ದರೆ, ಸಹಾಯ &gt; "ಸಮಸ್ಯೆಯನ್ನು ವರದಿ ಮಾಡಿ..." ನಲ್ಲಿ ವರದಿ ಮಾಡಿ.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ಹೊಸ ಪಾಸ್‌ವರ್ಡ್ ಖಚಿತಪಡಿಸಿ</translation>
 <translation id="7690378713476594306">ಪಟ್ಟಿಯಿಂದ ಆರಿಸಿ</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index e12b1e3..8dd967c 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -6129,7 +6129,6 @@
 <translation id="7685049629764448582">자바스크립트 메모리</translation>
 <translation id="7685087414635069102">PIN 필요</translation>
 <translation id="768549422429443215">언어 추가 또는 목록 재정렬</translation>
-<translation id="7686424868232681412">Lacros는 실험 단계의 브라우저입니다. 문제가 발생하면 도움말 &gt; '문제 신고…'에서 신고해 주세요.</translation>
 <translation id="7686938547853266130"><ph name="DEVICE_PATH" /> <ph name="FRIENDLY_NAME" /></translation>
 <translation id="7690294790491645610">새 비밀번호 확인</translation>
 <translation id="7690378713476594306">목록에서 선택</translation>
diff --git a/chrome/app/resources/generated_resources_ky.xtb b/chrome/app/resources/generated_resources_ky.xtb
index 5e0050f..07e93a5 100644
--- a/chrome/app/resources/generated_resources_ky.xtb
+++ b/chrome/app/resources/generated_resources_ky.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">JavaScript эстутуму</translation>
 <translation id="7685087414635069102">PIN код талап кылынат</translation>
 <translation id="768549422429443215">Тилдерди кошуңуз же тизмени иреттеңиз.</translation>
-<translation id="7686424868232681412">Lacros cерепчиси учурда сыналууда. Көйгөйлөрдү кабарлоо үчүн Жардам &gt; "Көйгөйдү кабарлоо..." бөлүмүнө өтүңүз.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Жаңы сырсөздү ырастаңыз</translation>
 <translation id="7690378713476594306">Тизмеден тандаңыз</translation>
diff --git a/chrome/app/resources/generated_resources_lo.xtb b/chrome/app/resources/generated_resources_lo.xtb
index e332e07..e80ba01 100644
--- a/chrome/app/resources/generated_resources_lo.xtb
+++ b/chrome/app/resources/generated_resources_lo.xtb
@@ -6129,7 +6129,6 @@
 <translation id="7685049629764448582">ຄວາມ​ຈໍາ JavaScript</translation>
 <translation id="7685087414635069102">ຈໍາເປັນຕ້ອງມີ PIN</translation>
 <translation id="768549422429443215">ເພີ່ມພາສາ ຫຼື ຈັດລຳດັບລາຍການໃໝ່.</translation>
-<translation id="7686424868232681412">Lacros ເປັນບຣາວເຊີການທົດລອງ. ກະລຸນາລາຍງານບັນຫາຕ່າງໆດ້ວຍ: ຊ່ວຍເຫຼືອ &gt; "ລາຍງານບັນຫາ...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ຢືນຢັນລະຫັດຜ່ານໃໝ່</translation>
 <translation id="7690378713476594306">ເລືອກຈາກລາຍການ</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index ae33ea1..6eebfb895 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -6136,7 +6136,6 @@
 <translation id="7685049629764448582">„JavaScript“ atmintis</translation>
 <translation id="7685087414635069102">Reikia PIN kodo</translation>
 <translation id="768549422429443215">Pridėkite kalbų arba pertvarkykite sąrašą.</translation>
-<translation id="7686424868232681412">„Lacros“ yra eksperimentinė naršyklė. Praneškite, jei kils problemų, skiltyje „Pagalba“ &gt; „Pranešti apie problemą...“</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Patvirtinkite naują slaptažodį</translation>
 <translation id="7690378713476594306">Pasirinkti iš sąrašo</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index 7c101b7..2e96af8 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -3268,7 +3268,7 @@
 <translation id="4519935350946509010">Savienojuma kļūda.</translation>
 <translation id="4520385623207007473">Izmantojamie sīkfaili</translation>
 <translation id="452039078290142656">nezināmas ierīces, ko piedāvā <ph name="VENDOR_NAME" /></translation>
-<translation id="4522570452068850558">Informācija</translation>
+<translation id="4522570452068850558">Dati</translation>
 <translation id="4522600456902129422">Turpināt atļaut šai vietnei skatīt starpliktuves saturu</translation>
 <translation id="4522890784888918985">Pakārtotie konti netiek atbalstīti</translation>
 <translation id="4524832533047962394">Nodrošinātais reģistrācijas režīms netiek atbalstīts šajā operētājsistēmas versijā. Izmantojiet jaunāko versiju.</translation>
@@ -6115,7 +6115,6 @@
 <translation id="7685049629764448582">JavaScript atmiņa</translation>
 <translation id="7685087414635069102">Jāievada PIN</translation>
 <translation id="768549422429443215">Pievienojiet valodas vai pārkārtojiet sarakstu.</translation>
-<translation id="7686424868232681412">Lacros ir eksperimentāla pārlūkprogramma. Lūdzu, ziņojiet par problēmām šeit: Palīdzība &gt; Ziņot par problēmu…</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Apstipriniet jauno paroli</translation>
 <translation id="7690378713476594306">Izvēlēties no saraksta</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb
index 12ab383d..a0af9a3 100644
--- a/chrome/app/resources/generated_resources_mk.xtb
+++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">Меморија на JavaScript</translation>
 <translation id="7685087414635069102">Потребен е PIN</translation>
 <translation id="768549422429443215">Додајте јазици или прередете го списокот.</translation>
-<translation id="7686424868232681412">Lacros е експериментален прелистувач. Ако наидете на проблем, пријавете го во „Помош &gt; Пријавете проблем…“</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Потврдете ја новата лозинка</translation>
 <translation id="7690378713476594306">Изберете од списокот</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index 6fdf799..c356c6bf 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">JavaScript മെമ്മറി</translation>
 <translation id="7685087414635069102">പിൻ ആവശ്യമാണ്</translation>
 <translation id="768549422429443215">ഭാഷകളോ പുനഃക്രമീകരണ ലിസ്‌റ്റോ ചേർക്കുക.</translation>
-<translation id="7686424868232681412">Lacros ഒരു പരീക്ഷണാത്മക ബ്രൗസറാണ്. സഹായം &gt; "പ്രശ്‌നം റിപ്പോർട്ട് ചെയ്യുക..." ഉപയോഗിച്ച് പ്രശ്‌നങ്ങൾ റിപ്പോർട്ട് ചെയ്യുക.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">പുതിയ പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക</translation>
 <translation id="7690378713476594306">ലിസ്റ്റിൽ നിന്ന് തിരഞ്ഞെടുക്കുക</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index 122aa6df..996d872 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -678,6 +678,7 @@
 <translation id="1706625117072057435">Томруулах түвшин</translation>
 <translation id="1708338024780164500">(Идэвхигүй)</translation>
 <translation id="1708713382908678956"><ph name="NAME_PH" /> (ID: <ph name="ID_PH" />)</translation>
+<translation id="1708860176443612387">Туршилтын хөтөч! Өгөгдөл алдах эсвэл нууцлал, аюулгүй байдал алдагдаж магадгүй. Асуудлыг дараахаар мэдээлнэ үү: Тусламж &gt; "Асуудал мэдээлэх...".</translation>
 <translation id="1709106626015023981"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (Төрөлх)</translation>
 <translation id="1709217939274742847">Нотолгоонд хэрэглэх тасалбарыг сонгоно уу. <ph name="LINK_BEGIN" />Нэмэлт мэдээлэл авах<ph name="LINK_END" /></translation>
 <translation id="1709972045049031556">Хуваалцах боломжгүй</translation>
@@ -1096,6 +1097,7 @@
 <translation id="2144557304298909478">Linux-н Андройд аппын хөгжүүлэлт</translation>
 <translation id="2146263598007866206">Сайтууд таны цагийг хэмнэхийн тулд холбоотой файлуудыг хамтад нь автоматаар татаж болзошгүй</translation>
 <translation id="2147151613919729065">Зочны горимын түүхийг арилгахын тулд Зочны бүх цонхыг хаана уу.</translation>
+<translation id="2147218225094845757">Хажуугийн самбарыг нуух</translation>
 <translation id="2148219725039824548">Хуваалцлыг залгаж чадсангүй. Сонгосон хуваалцал сүлжээнээс олдсонгүй.</translation>
 <translation id="2148756636027685713">Форматлаж дууссан</translation>
 <translation id="2148892889047469596">Цонх дамжуулах</translation>
@@ -3947,6 +3949,7 @@
 <translation id="5269977353971873915">Хэвлэх үйлдэл амжилтгүй болсон байна</translation>
 <translation id="5275352920323889391">Нохой</translation>
 <translation id="527605982717517565"><ph name="HOST" />-д байгаа JavaScript-ийг үргэлж зөвшөөрөх</translation>
+<translation id="5277127016695466621">Хажуугийн самбарыг харуулах</translation>
 <translation id="5278823018825269962">Төлөвийн Id</translation>
 <translation id="5280064835262749532"><ph name="SHARE_PATH" />-н мандат үнэмлэхийг шинэчлэх</translation>
 <translation id="5280243692621919988">Таныг бүх цонхыг хаахад күүки болон сайтын өгөгдлийг устгах</translation>
@@ -6127,7 +6130,6 @@
 <translation id="7685049629764448582">JavaScript санах ой</translation>
 <translation id="7685087414635069102">ПИН шаардлагатай</translation>
 <translation id="768549422429443215">Хэл нэмэх эсвэл жагсаалтыг дахин эрэмбэлнэ үү.</translation>
-<translation id="7686424868232681412">Lacros нь туршилтын хөтөч юм. Асуудлыг дараахаар мэдээлнэ үү: Тусламж &gt; "Асуудал мэдээлэх...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Шинэ нууц үг баталгаажуулна уу</translation>
 <translation id="7690378713476594306">Жагсаалтаас сонгох</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 2923779..b474c30 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -6130,7 +6130,6 @@
 <translation id="7685049629764448582">JavaScript मेमरी</translation>
 <translation id="7685087414635069102">पिन आवश्यक</translation>
 <translation id="768549422429443215">भाषा जोडा किंवा सूचीचा क्रम पुन्हा लावा.</translation>
-<translation id="7686424868232681412">Lacros हा प्रायोगिक ब्राउझर आहे. कृपया पुढील मार्ग वापरून समस्येची तक्रार करा: मदत &gt; "समस्येची तक्रार करा...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">नवीन पासवर्ड कन्फर्म करा</translation>
 <translation id="7690378713476594306">सूचीतून निवडा</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index b818d956..56078e7 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">Memori JavaScript</translation>
 <translation id="7685087414635069102">PIN diperlukan</translation>
 <translation id="768549422429443215">Tambah bahasa dan susun semula senarai.</translation>
-<translation id="7686424868232681412">Lacros merupakan Penyemak Imbas percubaan. Sila laporkan isu pada: Bantuan &gt; "Laporkan isu...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Sahkan kata laluan baharu</translation>
 <translation id="7690378713476594306">Pilih daripada senarai</translation>
diff --git a/chrome/app/resources/generated_resources_my.xtb b/chrome/app/resources/generated_resources_my.xtb
index 8511178..ea6c040 100644
--- a/chrome/app/resources/generated_resources_my.xtb
+++ b/chrome/app/resources/generated_resources_my.xtb
@@ -682,6 +682,7 @@
 <translation id="1706625117072057435">ဇူးမ်အဆင့်များ</translation>
 <translation id="1708338024780164500">(အသုံးမပြု)</translation>
 <translation id="1708713382908678956"><ph name="NAME_PH" /> (အိုင်ဒီ − <ph name="ID_PH" />)</translation>
+<translation id="1708860176443612387">စမ်းသပ်နေဆဲ ဘရောင်ဇာဖြစ်သည်။ ဒေတာဆုံးရှုံးနိုင်သည် သို့မဟုတ် ပုဂ္ဂိုလ်ရေး (သို့) လုံခြုံရေး ထိခိုက်နိုင်သည်။ ပြဿနာများ အကြောင်းကြားရန်- ‘အကူအညီ’ &gt; “ပြဿနာ အကြောင်းကြားရန်...” သို့သွားပါ။</translation>
 <translation id="1709106626015023981"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (မူလ)</translation>
 <translation id="1709217939274742847">အထောက်အထားစိစစ်ရာတွင် အသုံးပြုရန် လက်မှတ်တစ်ခု ရွေးပါ။ <ph name="LINK_BEGIN" />ပိုမိုလေ့လာရန်<ph name="LINK_END" /></translation>
 <translation id="1709972045049031556">မျှဝေ၍ မရပါ</translation>
@@ -1099,6 +1100,7 @@
 <translation id="2144557304298909478">Linux Android အက်ပ် ရေးဆွဲမှု</translation>
 <translation id="2146263598007866206">သင့်အတွက် အချိန်ကုန်သက်သာစေရန် သက်ဆိုင်ရာဖိုင်များကို ဝဘ်ဆိုက်များက အလိုအလျောက် ဒေါင်းလုဒ်လုပ်နိုင်သည်</translation>
 <translation id="2147151613919729065">‘ဧည့်သည်မုဒ်’ မှတ်တမ်း ရှင်းထုတ်ရန် ‘ဧည့်သည်ဝင်းဒိုး’ အားလုံးကို ပိတ်ပါ။</translation>
+<translation id="2147218225094845757">ဘေးအကန့် ဖျောက်ထားရန်</translation>
 <translation id="2148219725039824548">မျှဝေဖိုင်တွဲကို တင်ရာတွင် အမှားအယွင်းရှိသည်။ သတ်မှတ်ထားသည့် မျှဝေဖိုင်တွဲကို ကွန်ရက်ပေါ်တွင် မတွေ့ပါ။</translation>
 <translation id="2148756636027685713">ဖိုင်ပြန်လည်စီခြင်း ပြီးဆုံးပြီ။</translation>
 <translation id="2148892889047469596">ကာစ်တ် တဘ်</translation>
@@ -3950,6 +3952,7 @@
 <translation id="5269977353971873915">ပရင်ထုတ်ရန် မအောင်မြင်ပါ</translation>
 <translation id="5275352920323889391">ခွေး</translation>
 <translation id="527605982717517565"><ph name="HOST" /> တွင် အမြဲတမ်း JavaScript ခွင့်ပြုရန်</translation>
+<translation id="5277127016695466621">ဘေးအကန့် ပြသရန်</translation>
 <translation id="5278823018825269962">အခြေအနေ Id</translation>
 <translation id="5280064835262749532"><ph name="SHARE_PATH" /> အတွက် အထောက်အထားများ အပ်ဒိတ်လုပ်ခြင်း</translation>
 <translation id="5280243692621919988">ဝင်းဒိုးများအားလုံးကို သင်ပိတ်သည့်အခါ ကွတ်ကီးနှင့် ဝဘ်ဆိုက်ဒေတာများအားလုံးကို ရှင်းလင်းပါ</translation>
@@ -6128,7 +6131,6 @@
 <translation id="7685049629764448582">JavaScript မှတ်ဉာဏ်</translation>
 <translation id="7685087414635069102">ပင်နံပါတ် လိုအပ်သည်</translation>
 <translation id="768549422429443215">ဘာသာစကားများ ထည့်ပါ သို့မဟုတ် စာရင်းကို ပြန်စီပါ။</translation>
-<translation id="7686424868232681412">Lacros သည် စမ်းသပ် ‘ဘရောင်ဇာ’ ဖြစ်သည်။ ပြဿနာများ သတင်းပို့ရန် ‘အကူအညီ’ &gt; “ပြဿနာ သတင်းပို့ရန်...” သို့သွားပါ။</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">စကားဝှက်အသစ်ကို အတည်ပြုပါ</translation>
 <translation id="7690378713476594306">စာရင်းထဲမှ ရွေးရန်</translation>
diff --git a/chrome/app/resources/generated_resources_ne.xtb b/chrome/app/resources/generated_resources_ne.xtb
index fe1c9153..d6b02bb0 100644
--- a/chrome/app/resources/generated_resources_ne.xtb
+++ b/chrome/app/resources/generated_resources_ne.xtb
@@ -6098,7 +6098,6 @@
 <translation id="7685049629764448582">जाभास्क्रिप्ट स्मृ</translation>
 <translation id="7685087414635069102">पिन चाहिन्छ</translation>
 <translation id="768549422429443215">भाषाहरू थप्नुहोस् वा सूचीको क्रम मिलाउनुहोस्।</translation>
-<translation id="7686424868232681412">Lacros ब्राउजरको परीक्षणका क्रममा छ। कृपया यहाँ गई यस ब्राउजरमा देखिएका समस्याका बारेमा रिपोर्ट गर्नुहोस्: मद्दत &gt; "समस्याका बारेमा रिपोर्ट गर्नुहोस्..."।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">नयाँ पासवर्ड पुष्टि गर्नुहोस्</translation>
 <translation id="7690378713476594306">सूचीबाट छान्नुहोस्</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index 86a4511..a306c73 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -6113,7 +6113,6 @@
 <translation id="7685049629764448582">JavaScript-geheugen</translation>
 <translation id="7685087414635069102">Pincode vereist</translation>
 <translation id="768549422429443215">Voeg talen toe of sorteer de lijst opnieuw.</translation>
-<translation id="7686424868232681412">Lacros is een experimentele browser. Meld problemen via Hulp &gt; Een probleem melden.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Nieuw wachtwoord bevestigen</translation>
 <translation id="7690378713476594306">Selecteer een optie in de lijst</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index c91bd84..8bad808 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -6123,7 +6123,6 @@
 <translation id="7685049629764448582">JavaScript-minne</translation>
 <translation id="7685087414635069102">PIN-kode kreves</translation>
 <translation id="768549422429443215">Legg til språk eller endre rekkefølgen på listen.</translation>
-<translation id="7686424868232681412">Lacros er en nettleser på forsøksstadiet. Rapportér problemer via Hjelp &gt; «Rapportér et problem».</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bekreft det nye passordet</translation>
 <translation id="7690378713476594306">Velg fra listen</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb
index c07e2604..d096368 100644
--- a/chrome/app/resources/generated_resources_or.xtb
+++ b/chrome/app/resources/generated_resources_or.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">JavaScript ମେମୋରି</translation>
 <translation id="7685087414635069102">ପିନ୍ ଆବଶ୍ୟକ ଅଟେ</translation>
 <translation id="768549422429443215">ଭାଷାଗୁଡ଼ିକୁ ଯୋଗ କରନ୍ତୁ କିମ୍ବା ତାଲିକାକୁ ପୁନଃକ୍ରମରେ ରଖନ୍ତୁ।</translation>
-<translation id="7686424868232681412">Lacros ଏକ ପରୀକ୍ଷାମୂଳକ ବ୍ରାଉଜର୍ ଅଟେ। ଦୟାକରି ସମସ୍ୟାଗୁଡ଼ିକ ବିଷୟରେ ଏଠାରେ ରିପୋର୍ଟ କରନ୍ତୁ: ସହାୟତା &gt; "ଏକ ସମସ୍ୟା ବିଷୟରେ ରିପୋର୍ଟ କରନ୍ତୁ..."।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ନୂଆ ପାସ୍‌ୱାର୍ଡ ସୁନିଶ୍ଚିତ କରନ୍ତୁ</translation>
 <translation id="7690378713476594306">ତାଲିକାରୁ ବାଛନ୍ତୁ</translation>
diff --git a/chrome/app/resources/generated_resources_pa.xtb b/chrome/app/resources/generated_resources_pa.xtb
index a093903..25a52e9 100644
--- a/chrome/app/resources/generated_resources_pa.xtb
+++ b/chrome/app/resources/generated_resources_pa.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">JavaScript ਮੈਮਰੀ</translation>
 <translation id="7685087414635069102">ਪਿੰਨ ਲੋੜੀਂਦਾ ਹੈ</translation>
 <translation id="768549422429443215">ਭਾਸ਼ਾਵਾਂ ਸ਼ਾਮਲ ਕਰੋ ਜਾਂ ਸੂਚੀ ਨੂੰ ਮੁੜ-ਕ੍ਰਮਬੱਧ ਕਰੋ।</translation>
-<translation id="7686424868232681412">Lacros ਇੱਕ ਪ੍ਰਯੋਗਮਈ ਬ੍ਰਾਊਜ਼ਰ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਸਮੱਸਿਆਵਾਂ ਦੀ ਰਿਪੋਰਟ ਕਰਨ ਲਈ ਇੱਥੇ ਜਾਓ: ਮਦਦ &gt; "ਕਿਸੇ ਸਮੱਸਿਆ ਦੀ ਰਿਪੋਰਟ ਕਰੋ..."।</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ਨਵੇਂ ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</translation>
 <translation id="7690378713476594306">ਸੂਚੀ ਵਿੱਚੋਂ ਚੁਣੋ</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index de46595..7ec5f304 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -6110,7 +6110,6 @@
 <translation id="7685049629764448582">Pamięć JavaScript</translation>
 <translation id="7685087414635069102">Wymagany kod PIN</translation>
 <translation id="768549422429443215">Dodaj języki lub zmień kolejność na liście.</translation>
-<translation id="7686424868232681412">Lacros to przeglądarka eksperymentalna. Jeśli pojawią się problemy, zgłoś je, klikając Pomoc &gt; „Zgłoś problem…”.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potwierdź nowe hasło</translation>
 <translation id="7690378713476594306">Wybierz z listy</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index 20b5327..cad286a 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -6135,7 +6135,6 @@
 <translation id="7685049629764448582">Memória JavaScript</translation>
 <translation id="7685087414635069102">PIN necessário</translation>
 <translation id="768549422429443215">Adicionar idiomas ou reordenar lista.</translation>
-<translation id="7686424868232681412">O Lacros é um navegador experimental. Informe um problema em "Ajuda &gt; Informar um problema…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar nova senha</translation>
 <translation id="7690378713476594306">Escolher na lista</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index 73ef901..70c0bee0 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -6118,7 +6118,6 @@
 <translation id="7685049629764448582">Memória JavaScript</translation>
 <translation id="7685087414635069102">PIN necessário</translation>
 <translation id="768549422429443215">Adicione idiomas ou reordene a lista.</translation>
-<translation id="7686424868232681412">O Lacros é um navegador experimental. Comunique problemas em Ajuda &gt; "Comunicar um problema…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmar a nova palavra-passe</translation>
 <translation id="7690378713476594306">Escolher na lista</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 74a3a69..1fab5cc 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -559,7 +559,7 @@
 <translation id="1596286373007273895">Disponibil</translation>
 <translation id="1598233202702788831">Actualizările sunt dezactivate de administrator.</translation>
 <translation id="1600857548979126453">Accesează procesul de fundal al depanatorului de pagină</translation>
-<translation id="1601560923496285236">Aplicați</translation>
+<translation id="1601560923496285236">Aplică</translation>
 <translation id="1602085790802918092">Se pornește mașina virtuală</translation>
 <translation id="1603914832182249871">(Incognito)</translation>
 <translation id="1604432177629086300">Nu s-a putut printa. Verifică imprimanta și încearcă din nou.</translation>
@@ -6117,7 +6117,6 @@
 <translation id="7685049629764448582">Memorie JavaScript</translation>
 <translation id="7685087414635069102">PIN necesar</translation>
 <translation id="768549422429443215">Adaugă limbi sau reordonează lista.</translation>
-<translation id="7686424868232681412">Lacros este un browser experimental. Raportează problemele accesând Ajutor &gt; Raportează o problemă…</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Confirmă noua parolă</translation>
 <translation id="7690378713476594306">Alege din listă</translation>
@@ -6872,7 +6871,7 @@
 <translation id="8498395510292172881">Continuă să citești în Chrome</translation>
 <translation id="8499083585497694743">Activează sunetul microfonului</translation>
 <translation id="8502536196501630039">Ca să folosești aplicații din Google Play, trebuie mai întâi să restabilești aplicațiile. Este posibil ca unele date să se fi pierdut.</translation>
-<translation id="8503813439785031346">Nume utilizator</translation>
+<translation id="8503813439785031346">Nume de utilizator</translation>
 <translation id="8507227974644337342">Rezoluția ecranului</translation>
 <translation id="850875081535031620">Nu s-a găsit software dăunător</translation>
 <translation id="8509177919508253835">Resetează cheile de securitate și creează coduri PIN</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index c50139a..4567400 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -3267,7 +3267,7 @@
 <translation id="4519935350946509010">Ошибка подключения.</translation>
 <translation id="4520385623207007473">Использование файлов cookie</translation>
 <translation id="452039078290142656">неизвестные устройства от <ph name="VENDOR_NAME" /></translation>
-<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4522570452068850558">Детали</translation>
 <translation id="4522600456902129422">Оставить этому сайту доступ к буферу обмена</translation>
 <translation id="4522890784888918985">Дочерние аккаунты не поддерживаются.</translation>
 <translation id="4524832533047962394">Режим регистрации устройства не поддерживается этой версией операционной системы. Убедитесь, что вы используете последнюю версию, и повторите попытку.</translation>
@@ -6117,7 +6117,6 @@
 <translation id="7685049629764448582">Память JavaScript</translation>
 <translation id="7685087414635069102">Требуется PIN-код</translation>
 <translation id="768549422429443215">Добавьте языки или измените порядок их расположения.</translation>
-<translation id="7686424868232681412">Lacros – экспериментальный браузер. Чтобы сообщить о проблемах, связанных с ним, нажмите "Справка &gt; Сообщить о проблеме".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Введите новый пароль ещё раз</translation>
 <translation id="7690378713476594306">Выбрать из списка</translation>
diff --git a/chrome/app/resources/generated_resources_si.xtb b/chrome/app/resources/generated_resources_si.xtb
index 39a2cf2..958d3862 100644
--- a/chrome/app/resources/generated_resources_si.xtb
+++ b/chrome/app/resources/generated_resources_si.xtb
@@ -6119,7 +6119,6 @@
 <translation id="7685049629764448582">JavaScript මතකය</translation>
 <translation id="7685087414635069102">රහස් අංකය අවශ්‍යයි</translation>
 <translation id="768549422429443215">භාෂා එක් කරන්න හෝ ලැයිස්තුව යළි පෙළගස්වන්න.</translation>
-<translation id="7686424868232681412">Lacros යනු අත්හදා බැලීමේ බ්‍රව්සරයකි. කරුණාකර ගැටලු මෙලෙස වාර්තා කරන්න: උදවු &gt; "ගැටලුවක් වාර්තා කරන්න...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> <ph name="DEVICE_PATH" /></translation>
 <translation id="7690294790491645610">නව මුරපදය තහවුරු කරන්න</translation>
 <translation id="7690378713476594306">ලැයිස්තුවෙන් තෝරා ගන්න</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index efd804f..a575bab 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -6118,7 +6118,6 @@
 <translation id="7685049629764448582">Pamäť jazyka JavaScript</translation>
 <translation id="7685087414635069102">Vyžaduje sa kód PIN</translation>
 <translation id="768549422429443215">Pridajte jazyky alebo upravte poradie zoznamu.</translation>
-<translation id="7686424868232681412">Lacros je experimentálny prehliadač. Prípadné problémy nahláste v sekcii Pomocník &gt; Nahlásiť problém…</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrďte nové heslo</translation>
 <translation id="7690378713476594306">Vybrať v zozname</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index 94ff1e98..07f5c72 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -6137,7 +6137,6 @@
 <translation id="7685049629764448582">Pomnilnik za JavaScript</translation>
 <translation id="7685087414635069102">Zahtevana je koda PIN</translation>
 <translation id="768549422429443215">Dodajte jezike ali preuredite seznam.</translation>
-<translation id="7686424868232681412">Lacros je preizkusni brskalnik. Težave prijavite v Pomoč &gt; »Prijava težave …«.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potrdite novo geslo</translation>
 <translation id="7690378713476594306">Izbira s seznama</translation>
diff --git a/chrome/app/resources/generated_resources_sq.xtb b/chrome/app/resources/generated_resources_sq.xtb
index 1d1a18a5..bf6e830 100644
--- a/chrome/app/resources/generated_resources_sq.xtb
+++ b/chrome/app/resources/generated_resources_sq.xtb
@@ -6113,7 +6113,6 @@
 <translation id="7685049629764448582">Memoria e JavaScript</translation>
 <translation id="7685087414635069102">Kërkohet kodi PIN</translation>
 <translation id="768549422429443215">Shto gjuhën ose rendit përsëri listën.</translation>
-<translation id="7686424868232681412">Lacros është një shfletues eksperimental. Raporto problemet me: Ndihma &gt; "Raporto një problem...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Konfirmo fjalëkalimin e ri</translation>
 <translation id="7690378713476594306">Zgjidh nga lista</translation>
diff --git a/chrome/app/resources/generated_resources_sr-Latn.xtb b/chrome/app/resources/generated_resources_sr-Latn.xtb
index d1ce480..cb53520 100644
--- a/chrome/app/resources/generated_resources_sr-Latn.xtb
+++ b/chrome/app/resources/generated_resources_sr-Latn.xtb
@@ -6113,7 +6113,6 @@
 <translation id="7685049629764448582">JavaScript memorija</translation>
 <translation id="7685087414635069102">PIN je obavezan</translation>
 <translation id="768549422429443215">Dodajte jezike ili promenite redosled stavki na listi.</translation>
-<translation id="7686424868232681412">Lacros je eksperimentalni pregledač. Prijavite probleme preko opcije: Pomoć &gt; „Prijavite problem…“.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Potvrdite novu lozinku</translation>
 <translation id="7690378713476594306">Odaberite sa liste</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index 97766cc..87b45f4 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -6113,7 +6113,6 @@
 <translation id="7685049629764448582">JavaScript меморија</translation>
 <translation id="7685087414635069102">PIN је обавезан</translation>
 <translation id="768549422429443215">Додајте језике или промените редослед ставки на листи.</translation>
-<translation id="7686424868232681412">Lacros је експериментални прегледач. Пријавите проблеме преко опције: Помоћ &gt; „Пријавите проблем…“.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Потврдите нову лозинку</translation>
 <translation id="7690378713476594306">Одаберите са листе</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index c857bd7d..f8b5bb87 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -3282,7 +3282,7 @@
 <translation id="4519935350946509010">Anslutningsfel.</translation>
 <translation id="4520385623207007473">Cookies är aktiverade</translation>
 <translation id="452039078290142656">okända enheter från <ph name="VENDOR_NAME" /></translation>
-<translation id="4522570452068850558">Info</translation>
+<translation id="4522570452068850558">Detaljer</translation>
 <translation id="4522600456902129422">Ge den här webbplatsen tillgång till Urklipp även i fortsättningen</translation>
 <translation id="4522890784888918985">Barnkonton stöds inte</translation>
 <translation id="4524832533047962394">Det angivna registreringsläget stöds inte av den här versionen av operativsystemet. Kontrollera att du har den senaste versionen.</translation>
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">JavaScript-minne</translation>
 <translation id="7685087414635069102">Pinkod krävs</translation>
 <translation id="768549422429443215">Lägg till språk eller ändra ordning på listan.</translation>
-<translation id="7686424868232681412">Lacros är en experimentell webbläsare. Rapportera problem via Hjälp &gt; Rapportera ett problem …</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Bekräfta det nya lösenordet</translation>
 <translation id="7690378713476594306">Välj i lista</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index d1c2bdba..bd8c9ba0 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -6126,7 +6126,6 @@
 <translation id="7685049629764448582">Kumbukumbu ya JavaScript</translation>
 <translation id="7685087414635069102">PIN inahitajika</translation>
 <translation id="768549422429443215">Ongeza lugha au panga orodha upya.</translation>
-<translation id="7686424868232681412">Lacros ni Kivinjari kinachofanyiwa majaribio. Tafadhali ripoti matatizo kupitia sehemu ya: Usaidizi &gt; "Ripoti tatizo...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Thibitisha nenosiri jipya</translation>
 <translation id="7690378713476594306">Chagua kutoka kwenye orodha</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index 1572cede..2bba06a 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">JavaScript நினைவகம்</translation>
 <translation id="7685087414635069102">பின் தேவை</translation>
 <translation id="768549422429443215">மொழிகளைச் சேர்க்கவும் அல்லது பட்டியலை மாற்றியமைக்கவும்.</translation>
-<translation id="7686424868232681412">Lacros என்பது சோதனை உலாவியாகும். சிக்கல்கள் இருந்தால் உதவி &gt; "சிக்கலைப் புகாரளி..." என்பதற்குச் சென்று புகாரளிக்கவும்.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">புதிய கடவுச்சொல்லை உறுதிப்படுத்துக</translation>
 <translation id="7690378713476594306">பட்டியலில் இருந்து தேர்வு செய்யவும்</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 5cc7a2f..2347b62e 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -6131,7 +6131,6 @@
 <translation id="7685049629764448582">JavaScript మెమరీ</translation>
 <translation id="7685087414635069102">పిన్ అవసరం</translation>
 <translation id="768549422429443215">భాషలను జోడించండి లేదా జాబితా క్రమాన్ని మళ్లీ మార్చండి.</translation>
-<translation id="7686424868232681412">Lacros ప్రయోగాత్మక బ్రౌజర్. సహాయం &gt; "సమస్యను రిపోర్ట్ చేయి..."తో దయచేసి ఏవైనా సమస్యలను రిపోర్ట్ చేయండి.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">కొత్త పాస్‌వర్డ్‌ను నిర్ధారించండి</translation>
 <translation id="7690378713476594306">జాబితా నుండి ఎంచుకోండి</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index db9013be..d44f062e 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">หน่วยความจำ JavaScript</translation>
 <translation id="7685087414635069102">ต้องระบุ PIN</translation>
 <translation id="768549422429443215">เพิ่มภาษาหรือจัดเรียงรายการใหม่</translation>
-<translation id="7686424868232681412">Lacros เป็นเบราว์เซอร์ทดลอง โปรดรายงานปัญหาโดยไปที่ความช่วยเหลือ &gt; "รายงานปัญหา..."</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">ยืนยันรหัสผ่านใหม่</translation>
 <translation id="7690378713476594306">เลือกจากรายการ</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index 2195a3d..06d7a051 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -6115,7 +6115,6 @@
 <translation id="7685049629764448582">JavaScript belleği</translation>
 <translation id="7685087414635069102">PIN gerekli</translation>
 <translation id="768549422429443215">Dil ekleyin veya listeyi yeniden sıralayın</translation>
-<translation id="7686424868232681412">Lacros deneysel bir tarayıcıdır. Lütfen sorunları Yardım &gt; "Sorun bildir..." bölümünden bildirin.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Yeni şifreyi doğrula</translation>
 <translation id="7690378713476594306">Listeden seç</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index 0505d5d..20f717a 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -6135,7 +6135,6 @@
 <translation id="7685049629764448582">Пам'ять JavaScript</translation>
 <translation id="7685087414635069102">Потрібен PIN-код</translation>
 <translation id="768549422429443215">Додайте мови або змініть порядок у списку.</translation>
-<translation id="7686424868232681412">Lacros – це експериментальний веб-переглядач. Щоб повідомити про проблему, натисніть "Довідка" &gt; "Повідомити про проблему…".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Підтвердьте новий пароль</translation>
 <translation id="7690378713476594306">Вибрати зі списку</translation>
diff --git a/chrome/app/resources/generated_resources_ur.xtb b/chrome/app/resources/generated_resources_ur.xtb
index a7d0ff0..acce94a 100644
--- a/chrome/app/resources/generated_resources_ur.xtb
+++ b/chrome/app/resources/generated_resources_ur.xtb
@@ -6116,7 +6116,6 @@
 <translation id="7685049629764448582">‏JavaScript میموری</translation>
 <translation id="7685087414635069102">‏PIN درکار ہے</translation>
 <translation id="768549422429443215">زبانیں شامل کریں یا فہرست دوبارہ ترتیب دیں۔</translation>
-<translation id="7686424868232681412">‏Lacros ایک تجرباتی براؤزر ہے۔ براہ کرم مدد &gt; "مسئلے کی اطلاع دیں..." کے ساتھ مسائل کی اطلاع دیں۔</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">نئے پاس ورڈ کی توثیق کریں</translation>
 <translation id="7690378713476594306">فہرست سے منتخب کریں</translation>
diff --git a/chrome/app/resources/generated_resources_uz.xtb b/chrome/app/resources/generated_resources_uz.xtb
index 3b5c25f..31d0fab 100644
--- a/chrome/app/resources/generated_resources_uz.xtb
+++ b/chrome/app/resources/generated_resources_uz.xtb
@@ -670,6 +670,7 @@
 <translation id="1706625117072057435">Masshtab</translation>
 <translation id="1708338024780164500">(Nofaol)</translation>
 <translation id="1708713382908678956"><ph name="NAME_PH" /> (ID: <ph name="ID_PH" />)</translation>
+<translation id="1708860176443612387">Tajribaviy brauzer! Axborotlar oʻchib ketishi yoki himoyada nuqsonlar yuz berishi mumkin. Muammolar yuz bersa, Yordam &gt; “Muammo haqida xabar berish” orqali murojaat qiling.</translation>
 <translation id="1709106626015023981"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (asl)</translation>
 <translation id="1709217939274742847">Autentifikatsiya uchun chiptadan foydalanishni tanlang <ph name="LINK_BEGIN" />Batafsil<ph name="LINK_END" /></translation>
 <translation id="1709972045049031556">Yuborilmadi</translation>
@@ -1088,6 +1089,7 @@
 <translation id="2144557304298909478">Linux tizimida Android uchun ilovalar ishlab chiqish</translation>
 <translation id="2146263598007866206">Saytlar vaqtingizni tejash maqsadida tegishli fayllarni avtomatik ravishda birga yuklab olishi mumkin</translation>
 <translation id="2147151613919729065">Mehmon rejimi tarixini tozalash uchun barcha mehmon oynalarini yoping</translation>
+<translation id="2147218225094845757">Yon panelni yopish</translation>
 <translation id="2148219725039824548">Umumiy ruxsat berishda xatolik yuz berdi. Ko‘rsatilgan qurilma tarmoqda emas.</translation>
 <translation id="2148756636027685713">Formatlash yakunlandi</translation>
 <translation id="2148892889047469596">Tab translatsiyasi</translation>
@@ -3940,6 +3942,7 @@
 <translation id="5269977353971873915">Chop etib bo‘lmadi</translation>
 <translation id="5275352920323889391">Kuchuk</translation>
 <translation id="527605982717517565"><ph name="HOST" /> saytiga JavaScript ishga tushirishga har doim ruxsat berilsin</translation>
+<translation id="5277127016695466621">Yon panelni ochish</translation>
 <translation id="5278823018825269962">Holat identifikatori</translation>
 <translation id="5280064835262749532"><ph name="SHARE_PATH" /> uchun login va parolni yangilang</translation>
 <translation id="5280243692621919988">Barcha oynalar yopilganda cookie fayllari va sayt maʼlumotlari tozalansin</translation>
@@ -6120,7 +6123,6 @@
 <translation id="7685049629764448582">JavaScript xotira</translation>
 <translation id="7685087414635069102">PIN kodni kiritish zarur</translation>
 <translation id="768549422429443215">Tillar kiritish yoki roʻyxatni qayta tartiblash.</translation>
-<translation id="7686424868232681412">Lacros – tajribaviy brauzer. Muammolar yuz bersa, Yordam &gt; “Muammo haqida xabar berish” orqali murojaat qiling.</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Yangi parolni tasdiqlang.</translation>
 <translation id="7690378713476594306">Ro‘yxatdan tanlash</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index 2d5e324..0dc295ea 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -6132,7 +6132,6 @@
 <translation id="7685049629764448582">Bộ nhớ cho JavaScript</translation>
 <translation id="7685087414635069102">Cần có mã PIN</translation>
 <translation id="768549422429443215">Thêm ngôn ngữ hoặc sắp xếp lại danh sách.</translation>
-<translation id="7686424868232681412">Lacros là một trình duyệt thử nghiệm. Vui lòng báo cáo sự cố bằng cách chuyển đến mục Trợ giúp &gt; "Báo cáo sự cố...".</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Xác nhận mật khẩu mới</translation>
 <translation id="7690378713476594306">Chọn từ danh sách</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index a6460335..e6d0ad1 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -3261,7 +3261,7 @@
 <translation id="4519935350946509010">建立连接时出错。</translation>
 <translation id="4520385623207007473">正在使用的 Cookie</translation>
 <translation id="452039078290142656">来自<ph name="VENDOR_NAME" />的未知设备</translation>
-<translation id="4522570452068850558">详细信息</translation>
+<translation id="4522570452068850558">详情</translation>
 <translation id="4522600456902129422">继续允许此网站查看剪贴板</translation>
 <translation id="4522890784888918985">子帐号不受支持</translation>
 <translation id="4524832533047962394">此版本的操作系统不支持所提供的注册模式。请确保您运行的是最新版本。</translation>
@@ -6111,7 +6111,6 @@
 <translation id="7685049629764448582">JavaScript 使用的内存</translation>
 <translation id="7685087414635069102">必须输入 PIN 码</translation>
 <translation id="768549422429443215">添加语言或将列表中的语言重新排列。</translation>
-<translation id="7686424868232681412">Lacros 是一款实验性浏览器。若要报告问题,请使用“帮助”&gt;“报告问题…”。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">再次输入新密码</translation>
 <translation id="7690378713476594306">从列表中选择</translation>
diff --git a/chrome/app/resources/generated_resources_zh-HK.xtb b/chrome/app/resources/generated_resources_zh-HK.xtb
index 9304fa3..13d39c31 100644
--- a/chrome/app/resources/generated_resources_zh-HK.xtb
+++ b/chrome/app/resources/generated_resources_zh-HK.xtb
@@ -6131,7 +6131,6 @@
 <translation id="7685049629764448582">JavaScript 記憶體使用量</translation>
 <translation id="7685087414635069102">必須提供 PIN</translation>
 <translation id="768549422429443215">新增語言或重新排列清單。</translation>
-<translation id="7686424868232681412">Lacros 是實驗版瀏覽器。請按一下 [說明] &gt; [報告問題…] 以報告問題。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">確認新密碼</translation>
 <translation id="7690378713476594306">從清單中選擇</translation>
@@ -6886,7 +6885,7 @@
 <translation id="8498395510292172881">在 Chrome 中繼續閱讀</translation>
 <translation id="8499083585497694743">將麥克風取消靜音</translation>
 <translation id="8502536196501630039">如要使用從 Google Play 下載的應用程式,請先還原您的應用程式。此操作可能會導致部分資料遺失。</translation>
-<translation id="8503813439785031346">使用者名稱</translation>
+<translation id="8503813439785031346">用戶名稱</translation>
 <translation id="8507227974644337342">螢幕解像度</translation>
 <translation id="850875081535031620">未發現任何有害軟件</translation>
 <translation id="8509177919508253835">重設安全密鑰並建立 PIN</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index 5f3ceb5..25653720 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -3265,7 +3265,7 @@
 <translation id="4519935350946509010">連線錯誤。</translation>
 <translation id="4520385623207007473">使用中的 Cookie</translation>
 <translation id="452039078290142656">由 <ph name="VENDOR_NAME" /> 製造的不明裝置</translation>
-<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4522570452068850558">詳細資料</translation>
 <translation id="4522600456902129422">繼續允許這個網站讀取剪貼簿</translation>
 <translation id="4522890784888918985">不支援子帳戶</translation>
 <translation id="4524832533047962394">這個版本的作業系統不支援目前提供的註冊模式。請確認你使用的是最新版本。</translation>
@@ -6115,7 +6115,6 @@
 <translation id="7685049629764448582">JavaScript 記憶體使用量</translation>
 <translation id="7685087414635069102">請輸入 PIN 碼</translation>
 <translation id="768549422429443215">新增語言或重新排列清單。</translation>
-<translation id="7686424868232681412">Lacros 是實驗性瀏覽器。如有問題,請依序按一下 [說明] &gt; [回報問題...] 進行回報。</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">確認新密碼</translation>
 <translation id="7690378713476594306">從清單中選擇</translation>
diff --git a/chrome/app/resources/generated_resources_zu.xtb b/chrome/app/resources/generated_resources_zu.xtb
index 4bd731a..10d785b 100644
--- a/chrome/app/resources/generated_resources_zu.xtb
+++ b/chrome/app/resources/generated_resources_zu.xtb
@@ -6133,7 +6133,6 @@
 <translation id="7685049629764448582">Imemori ye-JavaScript</translation>
 <translation id="7685087414635069102">I-PIN iyadingeka</translation>
 <translation id="768549422429443215">Engeza izilimi noma oda kabusha uhlu.</translation>
-<translation id="7686424868232681412">I-Lacros Isiphequluli sokuhlolwa. Sicela ubike izinkinga ngokuthi: Usizo &gt; "Bika inkinga..."</translation>
 <translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
 <translation id="7690294790491645610">Qinisekisa iphasiwedi entsha</translation>
 <translation id="7690378713476594306">Khetha kusuka kuhlu</translation>
diff --git a/chrome/browser/apps/app_service/app_service_proxy_desktop.cc b/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
index a5700402..32ea65f0 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_desktop.cc
@@ -84,4 +84,12 @@
   return false;
 }
 
+void AppServiceProxy::Shutdown() {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (web_apps_publisher_host_) {
+    web_apps_publisher_host_->Shutdown();
+  }
+#endif
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_service_proxy_desktop.h b/chrome/browser/apps/app_service/app_service_proxy_desktop.h
index a735780..30ed5c8 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_desktop.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_desktop.h
@@ -52,6 +52,9 @@
   void Initialize() override;
   bool MaybeShowLaunchPreventionDialog(const apps::AppUpdate& update) override;
 
+  // KeyedService overrides:
+  void Shutdown() override;
+
   std::unique_ptr<web_app::WebApps> web_apps_;
   std::unique_ptr<ExtensionApps> extension_apps_;
 
diff --git a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
index 7f20d2a..927bd0b2 100644
--- a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
+++ b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
@@ -412,12 +412,8 @@
   }
 }
 
-#if defined(OS_MAC)
 // http://crbug.com/502516
 #define MAYBE_TestFullscreen DISABLED_TestFullscreen
-#else
-#define MAYBE_TestFullscreen TestFullscreen
-#endif
 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestFullscreen) {
   ASSERT_TRUE(RunAppWindowInteractiveTest("testFullscreen")) << message_;
 }
diff --git a/chrome/browser/ash/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/ash/arc/accessibility/ax_tree_source_arc.cc
index 31dcf19..7e9027ce 100644
--- a/chrome/browser/ash/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/ash/arc/accessibility/ax_tree_source_arc.cc
@@ -21,6 +21,7 @@
 #include "extensions/browser/api/automation_internal/automation_event_router.h"
 #include "extensions/common/extension_messages.h"
 #include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_tree_source_checker.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace arc {
@@ -269,14 +270,38 @@
 
   update_ids.push_back(node_id_to_clear);
 
+  {
+    // TODO(crbug/1211039): This block is added temporary to debug
+    // http://crbug/1211039. Once the issue is resolved, this block should be
+    // removed.
+    std::string error_string;
+    ui::AXTreeSourceChecker<AccessibilityInfoDataWrapper*> checker(this);
+    if (!checker.CheckAndGetErrorString(&error_string)) {
+      LOG(ERROR) << "Failed to validate the tree source\n"
+                 << "Event: " << events[0].ToString() << "\n"
+                 << "window size: " << event_data.window_data->size() << ", "
+                 << "node size: " << event_data.node_data.size() << "\n"
+                 << "Error: " << error_string;
+    }
+  }
+
   std::vector<ui::AXTreeUpdate> updates;
   for (const int32_t update_root : update_ids) {
     ui::AXTreeUpdate update;
     update.node_id_to_clear = update_root;
     current_tree_serializer_->InvalidateSubtree(GetFromId(update_root));
-    current_tree_serializer_->SerializeChanges(GetFromId(update_root), &update);
+    if (!current_tree_serializer_->SerializeChanges(GetFromId(update_root),
+                                                    &update)) {
+      std::string error_string;
+      ui::AXTreeSourceChecker<AccessibilityInfoDataWrapper*> checker(this);
+      checker.CheckAndGetErrorString(&error_string);
 
-    updates.push_back(std::move(update));
+      LOG(ERROR) << "Unable to serialize accessibility event\n"
+                 << "Error: " << error_string << "\n"
+                 << "Update: " << update.ToString();
+    } else {
+      updates.push_back(std::move(update));
+    }
   }
 
   GetAutomationEventRouter()->DispatchAccessibilityEvents(
diff --git a/chrome/browser/ash/arc/arc_util.cc b/chrome/browser/ash/arc/arc_util.cc
index c5aff8d0..22872755 100644
--- a/chrome/browser/ash/arc/arc_util.cc
+++ b/chrome/browser/ash/arc/arc_util.cc
@@ -424,7 +424,7 @@
   // Check if Chrome OS OOBE flow is currently showing.
   // TODO(b/65861628): Redesign the OptIn flow since there is no longer reason
   // to have two different OptIn flows.
-  if (!chromeos::LoginDisplayHost::default_host())
+  if (!ash::LoginDisplayHost::default_host())
     return false;
 
   // Use the legacy logic for first sign-in OOBE OptIn flow. Make sure the user
diff --git a/chrome/browser/ash/arc/arc_util_unittest.cc b/chrome/browser/ash/arc/arc_util_unittest.cc
index 00e62c6..51bd715 100644
--- a/chrome/browser/ash/arc/arc_util_unittest.cc
+++ b/chrome/browser/ash/arc/arc_util_unittest.cc
@@ -772,11 +772,10 @@
 
  protected:
   void CreateLoginDisplayHost() {
-    fake_login_display_host_ =
-        std::make_unique<chromeos::FakeLoginDisplayHost>();
+    fake_login_display_host_ = std::make_unique<ash::FakeLoginDisplayHost>();
   }
 
-  chromeos::FakeLoginDisplayHost* login_display_host() {
+  ash::FakeLoginDisplayHost* login_display_host() {
     return fake_login_display_host_.get();
   }
 
@@ -784,7 +783,7 @@
 
  private:
   std::unique_ptr<chromeos::OobeConfiguration> oobe_configuration_;
-  std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
+  std::unique_ptr<ash::FakeLoginDisplayHost> fake_login_display_host_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcOobeTest);
 };
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 7396a135f..b626ad59 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
@@ -339,12 +339,11 @@
   }
 
   void CreateLoginDisplayHost() {
-    fake_login_display_host_ =
-        std::make_unique<chromeos::FakeLoginDisplayHost>();
+    fake_login_display_host_ = std::make_unique<ash::FakeLoginDisplayHost>();
   }
 
  private:
-  std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
+  std::unique_ptr<ash::FakeLoginDisplayHost> fake_login_display_host_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcProvisionNotificationServiceOobeTest);
 };
diff --git a/chrome/browser/ash/arc/optin/arc_terms_of_service_oobe_negotiator.cc b/chrome/browser/ash/arc/optin/arc_terms_of_service_oobe_negotiator.cc
index 9bc2ba4..02e64d5 100644
--- a/chrome/browser/ash/arc/optin/arc_terms_of_service_oobe_negotiator.cc
+++ b/chrome/browser/ash/arc/optin/arc_terms_of_service_oobe_negotiator.cc
@@ -21,7 +21,7 @@
   if (g_view_for_testing)
     return g_view_for_testing;
 
-  chromeos::LoginDisplayHost* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = ash::LoginDisplayHost::default_host();
   DCHECK(host);
   DCHECK(host->GetOobeUI());
   return host->GetOobeUI()->GetView<chromeos::ArcTermsOfServiceScreenHandler>();
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 8f23750d..f5fb575 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
@@ -133,8 +133,7 @@
 
  protected:
   void CreateLoginDisplayHost() {
-    fake_login_display_host_ =
-        std::make_unique<chromeos::FakeLoginDisplayHost>();
+    fake_login_display_host_ = std::make_unique<ash::FakeLoginDisplayHost>();
   }
 
  private:
@@ -145,7 +144,7 @@
       identity_test_env_profile_adaptor_;
   std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<ArcSessionManager> arc_session_manager_;
-  std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
+  std::unique_ptr<ash::FakeLoginDisplayHost> fake_login_display_host_;
   std::unique_ptr<ArcPlayStoreEnabledPreferenceHandler> preference_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcPlayStoreEnabledPreferenceHandlerTest);
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 c8d5bb39..3623ab73 100644
--- a/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
+++ b/chrome/browser/ash/arc/session/arc_session_manager_unittest.cc
@@ -1352,11 +1352,10 @@
 
  private:
   void CreateLoginDisplayHost() {
-    fake_login_display_host_ =
-        std::make_unique<chromeos::FakeLoginDisplayHost>();
+    fake_login_display_host_ = std::make_unique<ash::FakeLoginDisplayHost>();
   }
 
-  std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
+  std::unique_ptr<ash::FakeLoginDisplayHost> fake_login_display_host_;
 };
 
 TEST_P(ArcSessionManagerPolicyTest, SkippingTerms) {
@@ -1611,11 +1610,10 @@
   }
 
   void CreateLoginDisplayHost() {
-    fake_login_display_host_ =
-        std::make_unique<chromeos::FakeLoginDisplayHost>();
+    fake_login_display_host_ = std::make_unique<ash::FakeLoginDisplayHost>();
   }
 
-  chromeos::FakeLoginDisplayHost* login_display_host() {
+  ash::FakeLoginDisplayHost* login_display_host() {
     return fake_login_display_host_.get();
   }
 
@@ -1648,7 +1646,7 @@
 
   base::ObserverList<chromeos::ArcTermsOfServiceScreenViewObserver>::Unchecked
       observer_list_;
-  std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
+  std::unique_ptr<ash::FakeLoginDisplayHost> fake_login_display_host_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcSessionOobeOptInNegotiatorTest);
 };
diff --git a/chrome/browser/ash/borealis/borealis_context.cc b/chrome/browser/ash/borealis/borealis_context.cc
index 4017239f..5b27154 100644
--- a/chrome/browser/ash/borealis/borealis_context.cc
+++ b/chrome/browser/ash/borealis/borealis_context.cc
@@ -4,10 +4,17 @@
 
 #include "chrome/browser/ash/borealis/borealis_context.h"
 
+#include <memory>
+
 #include "ash/public/cpp/new_window_delegate.h"
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "chrome/browser/ash/borealis/borealis_disk_manager_impl.h"
 #include "chrome/browser/ash/borealis/borealis_engagement_metrics.h"
 #include "chrome/browser/ash/borealis/borealis_game_mode_controller.h"
@@ -22,6 +29,29 @@
 
 namespace borealis {
 
+namespace {
+
+// Similar to a delayed callback, but can be cancelled by deleting.
+class ScopedDelayedCallback {
+ public:
+  explicit ScopedDelayedCallback(base::OnceClosure callback,
+                                 base::TimeDelta delay)
+      : weak_factory_(this) {
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&ScopedDelayedCallback::OnComplete,
+                       weak_factory_.GetWeakPtr(), std::move(callback)),
+        delay);
+  }
+
+ private:
+  void OnComplete(base::OnceClosure callback) { std::move(callback).Run(); }
+
+  base::WeakPtrFactory<ScopedDelayedCallback> weak_factory_;
+};
+
+}  // namespace
+
 class BorealisLifetimeObserver
     : public BorealisWindowManager::AppWindowLifetimeObserver {
  public:
@@ -43,6 +73,10 @@
         .ShutdownWithDelay();
   }
 
+  void OnAppStarted(const std::string& app_id) override {
+    app_delayers_.erase(app_id);
+  }
+
   void OnAppFinished(const std::string& app_id,
                      aura::Window* last_window) override {
     // Launch post-game survey.
@@ -51,8 +85,14 @@
         guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_),
         app_id, base::UTF16ToUTF8(last_window->GetTitle()));
     if (url.is_valid()) {
-      ash::NewWindowDelegate::GetInstance()->NewTabWithUrl(
-          url, /*from_user_interaction=*/true);
+      // Unretained is safe here since we transitively own the
+      // ScopedDelayedCallback's weak factory.
+      app_delayers_.emplace(
+          app_id,
+          std::make_unique<ScopedDelayedCallback>(
+              base::BindOnce(&BorealisLifetimeObserver::OnDelayComplete,
+                             base::Unretained(this), std::move(url), app_id),
+              base::TimeDelta::FromSeconds(5)));
     }
   }
 
@@ -62,10 +102,18 @@
   }
 
  private:
+  void OnDelayComplete(GURL gurl, std::string app_id) {
+    app_delayers_.erase(app_id);
+    ash::NewWindowDelegate::GetInstance()->NewTabWithUrl(
+        gurl, /*from_user_interaction=*/true);
+  }
+
   Profile* const profile_;
   base::ScopedObservation<BorealisWindowManager,
                           BorealisWindowManager::AppWindowLifetimeObserver>
       observation_;
+  base::flat_map<std::string, std::unique_ptr<ScopedDelayedCallback>>
+      app_delayers_;
 };
 
 BorealisContext::~BorealisContext() = default;
diff --git a/chrome/browser/ash/borealis/borealis_context_manager_impl.cc b/chrome/browser/ash/borealis/borealis_context_manager_impl.cc
index bafdf518..046bc78e 100644
--- a/chrome/browser/ash/borealis/borealis_context_manager_impl.cc
+++ b/chrome/browser/ash/borealis/borealis_context_manager_impl.cc
@@ -206,7 +206,6 @@
   task_queue.push(std::make_unique<StartBorealisVm>());
   task_queue.push(
       std::make_unique<AwaitBorealisStartup>(profile_, kBorealisVmName));
-  task_queue.push(std::make_unique<AwaitBorealisWindowOrLaunchApp>(profile_));
   return task_queue;
 }
 
diff --git a/chrome/browser/ash/borealis/borealis_task.cc b/chrome/browser/ash/borealis/borealis_task.cc
index 6a48be41..9f3b699c 100644
--- a/chrome/browser/ash/borealis/borealis_task.cc
+++ b/chrome/browser/ash/borealis/borealis_task.cc
@@ -12,11 +12,8 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "chrome/browser/ash/borealis/borealis_app_launcher.h"
 #include "chrome/browser/ash/borealis/borealis_context.h"
-#include "chrome/browser/ash/borealis/borealis_service.h"
 #include "chrome/browser/ash/borealis/borealis_util.h"
-#include "chrome/browser/ash/borealis/borealis_window_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/dbus/concierge/concierge_service.pb.h"
@@ -160,7 +157,6 @@
 AwaitBorealisStartup::AwaitBorealisStartup(Profile* profile,
                                            std::string vm_name)
     : watcher_(profile, vm_name) {}
-
 AwaitBorealisStartup::~AwaitBorealisStartup() = default;
 
 void AwaitBorealisStartup::RunInternal(BorealisContext* context) {
@@ -184,52 +180,4 @@
   context->set_container_name(container.value());
   Complete(BorealisStartupResult::kSuccess, "");
 }
-
-AwaitBorealisWindowOrLaunchApp::AwaitBorealisWindowOrLaunchApp(Profile* profile)
-    : window_observation_(this) {
-  window_observation_.Observe(
-      &BorealisService::GetForProfile(profile)->WindowManager());
-}
-
-AwaitBorealisWindowOrLaunchApp::~AwaitBorealisWindowOrLaunchApp() = default;
-
-void AwaitBorealisWindowOrLaunchApp::RunInternal(BorealisContext* context) {
-  // Technically the launch can race with startup, but this is very unlikely and
-  // at worst only causes the same problem we see currently, so we won't bother
-  // protecting against it.
-  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&AwaitBorealisWindowOrLaunchApp::WindowDidNotAppear,
-                     weak_factory_.GetWeakPtr(), context),
-      timeout_);
-}
-
-void AwaitBorealisWindowOrLaunchApp::WindowDidNotAppear(
-    BorealisContext* context) {
-  BorealisAppLauncher::Launch(
-      *context, kBorealisMainAppId,
-      base::BindOnce(&AwaitBorealisWindowOrLaunchApp::OnAppLaunched,
-                     weak_factory_.GetWeakPtr()));
-}
-
-void AwaitBorealisWindowOrLaunchApp::OnAppLaunched(
-    BorealisAppLauncher::LaunchResult result) {
-  // If launch succeeds we wait for OnSessionStarted to signal completion
-  if (result == BorealisAppLauncher::LaunchResult::kSuccess)
-    return;
-  Complete(BorealisStartupResult::kAwaitBorealisStartupFailed,
-           "Failed to launch app on startup (code " +
-               base::NumberToString(static_cast<int>(result)) + ")");
-}
-
-void AwaitBorealisWindowOrLaunchApp::OnSessionStarted() {
-  Complete(BorealisStartupResult::kSuccess, "");
-}
-
-void AwaitBorealisWindowOrLaunchApp::OnWindowManagerDeleted(
-    BorealisWindowManager* window_manager) {
-  DCHECK(window_observation_.IsObservingSource(window_manager));
-  window_observation_.Reset();
-}
-
 }  // namespace borealis
diff --git a/chrome/browser/ash/borealis/borealis_task.h b/chrome/browser/ash/borealis/borealis_task.h
index 139531fe..2df0903 100644
--- a/chrome/browser/ash/borealis/borealis_task.h
+++ b/chrome/browser/ash/borealis/borealis_task.h
@@ -6,16 +6,12 @@
 #define CHROME_BROWSER_ASH_BOREALIS_BOREALIS_TASK_H_
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ash/borealis/borealis_app_launcher.h"
 #include "chrome/browser/ash/borealis/borealis_context_manager.h"
 #include "chrome/browser/ash/borealis/borealis_launch_watcher.h"
 #include "chrome/browser/ash/borealis/borealis_metrics.h"
-#include "chrome/browser/ash/borealis/borealis_window_manager.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/dlcservice/dlcservice_client.h"
 
-class Profile;
-
 namespace borealis {
 
 class BorealisContext;
@@ -102,39 +98,6 @@
   base::WeakPtrFactory<AwaitBorealisStartup> weak_factory_{this};
 };
 
-// Waits to see if a borealis window launches (as a result of startup). If one
-// does not appear, launches a certain borealis app.
-//
-// TODO(b/171668019): remove this stage once we've factored launch of the
-// "certain app" into the necessary pieces (i.e. post-install) AND we've upreved
-// borealis s.t. it doesn't try to launch the app itself.
-class AwaitBorealisWindowOrLaunchApp
-    : public BorealisTask,
-      public BorealisWindowManager::AppWindowLifetimeObserver {
- public:
-  explicit AwaitBorealisWindowOrLaunchApp(Profile* profile);
-  ~AwaitBorealisWindowOrLaunchApp() override;
-  void RunInternal(BorealisContext* context) override;
-
- private:
-  // Called by a timer if no window appears.
-  void WindowDidNotAppear(BorealisContext* context);
-
-  // Called with the status of the attempted app launch (if the window didn't
-  // appear by itself).
-  void OnAppLaunched(BorealisAppLauncher::LaunchResult result);
-
-  // BorealisWindowManager::AppWindowLifetimeObserver overrides.
-  void OnSessionStarted() override;
-  void OnWindowManagerDeleted(BorealisWindowManager* window_manager) override;
-
-  base::ScopedObservation<BorealisWindowManager,
-                          BorealisWindowManager::AppWindowLifetimeObserver>
-      window_observation_;
-  base::TimeDelta timeout_ = base::TimeDelta::FromSeconds(10);
-  base::WeakPtrFactory<AwaitBorealisWindowOrLaunchApp> weak_factory_{this};
-};
-
 }  // namespace borealis
 
 #endif  // CHROME_BROWSER_ASH_BOREALIS_BOREALIS_TASK_H_
diff --git a/chrome/browser/ash/login/app_mode/kiosk_browsertest.cc b/chrome/browser/ash/login/app_mode/kiosk_browsertest.cc
index e01015a8..1d1637b 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_browsertest.cc
@@ -1114,9 +1114,8 @@
 IN_PROC_BROWSER_TEST_F(KioskTest, AutolaunchWarningCancel) {
   EnableConsumerKioskMode();
 
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  WizardController::SkipPostLoginScreensForTesting();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
 
   // Start login screen after configuring auto launch app since the warning
@@ -1141,9 +1140,8 @@
 IN_PROC_BROWSER_TEST_F(KioskTest, DISABLED_AutolaunchWarningConfirm) {
   EnableConsumerKioskMode();
 
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  WizardController::SkipPostLoginScreensForTesting();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
 
   // Start login screen after configuring auto launch app since the warning
@@ -1174,9 +1172,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableCancel) {
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  WizardController::SkipPostLoginScreensForTesting();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
 
   // Check Kiosk mode status.
@@ -1203,9 +1200,8 @@
 
 IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableConfirmed) {
   // Start UI, find menu entry for this app and launch it.
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  WizardController::SkipPostLoginScreensForTesting();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
 
   // Check Kiosk mode status.
@@ -1233,9 +1229,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(KioskTest, KioskEnableAfter2ndSigninScreen) {
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  WizardController::SkipPostLoginScreensForTesting();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
 
   // Check Kiosk mode status.
@@ -1303,9 +1298,8 @@
   EnableConsumerKioskMode();
 
   // Wait for and confirm the auto-launch warning.
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  WizardController::SkipPostLoginScreensForTesting();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
   wizard_controller->AdvanceToScreen(WelcomeView::kScreenId);
   ReloadAutolaunchKioskApps();
@@ -2779,7 +2773,7 @@
   // Set kiosk app to autolaunch.
   EnableConsumerKioskMode();
   WizardController::SkipPostLoginScreensForTesting();
-  WizardController* wizard_controller = WizardController::default_controller();
+  auto* wizard_controller = WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
 
   // Start login screen after configuring auto launch app since the warning
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
index 8be515b..755f037 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/extensions/policy_handlers.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
+#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "components/policy/core/browser/policy_error_map.h"
@@ -34,9 +35,9 @@
 #include "components/policy/policy_constants.h"
 #include "content/public/browser/network_service_instance.h"
 
-namespace chromeos {
-
+namespace ash {
 namespace {
+
 // Web Kiosk splash screen minimum show time.
 constexpr base::TimeDelta kKioskSplashScreenMinTime =
     base::TimeDelta::FromSeconds(10);
@@ -750,4 +751,4 @@
   return controller;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
index 05dac06..a0b9b39 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller.h
@@ -10,11 +10,11 @@
 #include "chrome/browser/ash/app_mode/kiosk_profile_loader.h"
 #include "chrome/browser/extensions/forced_extensions/force_installed_tracker.h"
 #include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
+// TODO(https://crbug.com/1164001): use forward declaration.
+#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 
-namespace chromeos {
-
+namespace ash {
 class LoginDisplayHost;
-class OobeUI;
 
 // Controller for the kiosk launch process, responsible for loading the kiosk
 // profile, and updating the splash screen UI.
@@ -207,7 +207,13 @@
   base::WeakPtrFactory<KioskLaunchController> weak_ptr_factory_{this};
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace chromeos {
+using ::ash::KioskLaunchController;
+}
 
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_browsertest.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_browsertest.cc
index 9f24fb49..3a5d555a 100644
--- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_browsertest.cc
@@ -29,9 +29,9 @@
 #include "extensions/common/extension_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using testing::_;
+namespace ash {
 
-namespace chromeos {
+using ::testing::_;
 
 const char kExtensionId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
 const char kExtensionName[] = "extension_name";
@@ -475,4 +475,5 @@
                          testing::Values(KioskAppType::kArcApp,
                                          KioskAppType::kChromeApp,
                                          KioskAppType::kWebApp));
-}  // namespace chromeos
+
+}  // namespace ash
diff --git a/chrome/browser/ash/login/ash_hud_login_browsertest.cc b/chrome/browser/ash/login/ash_hud_login_browsertest.cc
index 9d4f9b74..6a0ba742 100644
--- a/chrome/browser/ash/login/ash_hud_login_browsertest.cc
+++ b/chrome/browser/ash/login/ash_hud_login_browsertest.cc
@@ -565,7 +565,7 @@
   }
 
   void Login() {
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    WizardController::SkipPostLoginScreensForTesting();
 
     auto context = LoginManagerMixin::CreateDefaultUserContext(
         login_manager_mixin_.users()[0]);
diff --git a/chrome/browser/ash/login/configuration_keys.h b/chrome/browser/ash/login/configuration_keys.h
index f406024..dfbdb8a4 100644
--- a/chrome/browser/ash/login/configuration_keys.h
+++ b/chrome/browser/ash/login/configuration_keys.h
@@ -65,12 +65,16 @@
 // source migration is finished.
 namespace ash {
 namespace configuration {
+using ::chromeos::configuration::kDeviceRequisition;
 using ::chromeos::configuration::kEnableDemoMode;
 using ::chromeos::configuration::kEnrollmentAssetId;
 using ::chromeos::configuration::kEnrollmentAutoAttributes;
 using ::chromeos::configuration::kEnrollmentLocation;
+using ::chromeos::configuration::kEnrollmentToken;
+using ::chromeos::configuration::kRestoreAfterRollback;
 using ::chromeos::configuration::kSkipHIDDetection;
 using ::chromeos::configuration::kUpdateSkipUpdate;
+using ::chromeos::configuration::kWizardAutoEnroll;
 }  // namespace configuration
 }  // namespace ash
 
diff --git a/chrome/browser/ash/login/enrollment/enrollment_screen.h b/chrome/browser/ash/login/enrollment/enrollment_screen.h
index 93f6391..3aab32ab 100644
--- a/chrome/browser/ash/login/enrollment/enrollment_screen.h
+++ b/chrome/browser/ash/login/enrollment/enrollment_screen.h
@@ -225,4 +225,10 @@
 using ::ash::EnrollmentScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::EnrollmentScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_ENROLLMENT_ENROLLMENT_SCREEN_H_
diff --git a/chrome/browser/ash/login/existing_user_controller_browsertest.cc b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
index 0e04588..2c81382 100644
--- a/chrome/browser/ash/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
@@ -1331,7 +1331,7 @@
   }
 
   void Login(const LoginManagerMixin::TestUserInfo& test_user) {
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    WizardController::SkipPostLoginScreensForTesting();
 
     auto context = LoginManagerMixin::CreateDefaultUserContext(test_user);
     login_manager_mixin_.LoginAndWaitForActiveSession(context);
diff --git a/chrome/browser/ash/login/hwid_checker.h b/chrome/browser/ash/login/hwid_checker.h
index cbdf1ac..1fa621b 100644
--- a/chrome/browser/ash/login/hwid_checker.h
+++ b/chrome/browser/ash/login/hwid_checker.h
@@ -17,4 +17,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::IsMachineHWIDCorrect;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_HWID_CHECKER_H_
diff --git a/chrome/browser/ash/login/login_pref_names.h b/chrome/browser/ash/login/login_pref_names.h
index 091da9d..7fc3519 100644
--- a/chrome/browser/ash/login/login_pref_names.h
+++ b/chrome/browser/ash/login/login_pref_names.h
@@ -38,6 +38,7 @@
 using ::chromeos::prefs::kOobeMarketingOptInChoice;
 using ::chromeos::prefs::kOobeMarketingOptInScreenFinished;
 using ::chromeos::prefs::kOobeOnboardingTime;
+using ::chromeos::prefs::kOobeScreenPending;
 }
 }  // namespace ash
 
diff --git a/chrome/browser/ash/login/login_ui_browsertest.cc b/chrome/browser/ash/login/login_ui_browsertest.cc
index d98d283..5ff9e5a 100644
--- a/chrome/browser/ash/login/login_ui_browsertest.cc
+++ b/chrome/browser/ash/login/login_ui_browsertest.cc
@@ -177,7 +177,7 @@
   DisplayPasswordButtonTest() : LoginManagerTest() {}
 
   void LoginAndLock(const LoginManagerMixin::TestUserInfo& test_user) {
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    WizardController::SkipPostLoginScreensForTesting();
 
     auto context = LoginManagerMixin::CreateDefaultUserContext(test_user);
     login_manager_mixin_.LoginAndWaitForActiveSession(context);
@@ -318,7 +318,7 @@
     if (user_policy_mixin)
       user_policy_mixin->RequestPolicyUpdate();
 
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    WizardController::SkipPostLoginScreensForTesting();
 
     auto context = LoginManagerMixin::CreateDefaultUserContext(test_user);
     login_manager_mixin_.LoginAndWaitForActiveSession(context);
@@ -528,7 +528,7 @@
 };
 
 IN_PROC_BROWSER_TEST_P(SshWarningTest, VisibilityOnGaia) {
-  chromeos::WizardController::default_controller()->SkipToLoginForTesting();
+  WizardController::default_controller()->SkipToLoginForTesting();
   OobeScreenWaiter(GaiaView::kScreenId).Wait();
   test::UIPath ssh_warning = {"gaia-signin", "signin-frame-dialog",
                               "sshWarning"};
@@ -540,7 +540,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(SshWarningTest, VisibilityOnEnrollment) {
-  chromeos::WizardController::default_controller()->SkipToLoginForTesting();
+  WizardController::default_controller()->SkipToLoginForTesting();
   OobeScreenWaiter(GaiaView::kScreenId).Wait();
 
   LoginDisplayHost::default_host()->HandleAccelerator(
diff --git a/chrome/browser/ash/login/login_wizard.h b/chrome/browser/ash/login/login_wizard.h
index 03b9577..cdda44e2 100644
--- a/chrome/browser/ash/login/login_wizard.h
+++ b/chrome/browser/ash/login/login_wizard.h
@@ -18,4 +18,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::SwitchWebUItoMojo;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_LOGIN_WIZARD_H_
diff --git a/chrome/browser/ash/login/reset_browsertest.cc b/chrome/browser/ash/login/reset_browsertest.cc
index bc61575..a642745 100644
--- a/chrome/browser/ash/login/reset_browsertest.cc
+++ b/chrome/browser/ash/login/reset_browsertest.cc
@@ -122,7 +122,7 @@
 
   // Simulates reset screen request from views based login.
   void InvokeResetScreen() {
-    chromeos::LoginDisplayHost::default_host()->HandleAccelerator(
+    LoginDisplayHost::default_host()->HandleAccelerator(
         ash::LoginAcceleratorAction::kShowResetScreen);
     OobeScreenWaiter(ResetView::kScreenId).Wait();
     test::OobeJS()
diff --git a/chrome/browser/ash/login/screens/base_screen.h b/chrome/browser/ash/login/screens/base_screen.h
index 3d86135c..7f5da781 100644
--- a/chrome/browser/ash/login/screens/base_screen.h
+++ b/chrome/browser/ash/login/screens/base_screen.h
@@ -95,4 +95,10 @@
 using ::chromeos::BaseScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::BaseScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_BASE_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/demo_preferences_screen.h b/chrome/browser/ash/login/screens/demo_preferences_screen.h
index 633843a..0f998d1 100644
--- a/chrome/browser/ash/login/screens/demo_preferences_screen.h
+++ b/chrome/browser/ash/login/screens/demo_preferences_screen.h
@@ -83,4 +83,10 @@
 using ::ash::DemoPreferencesScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::DemoPreferencesScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_DEMO_PREFERENCES_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/eula_screen.h b/chrome/browser/ash/login/screens/eula_screen.h
index 70df5a55..342e999 100644
--- a/chrome/browser/ash/login/screens/eula_screen.h
+++ b/chrome/browser/ash/login/screens/eula_screen.h
@@ -107,4 +107,10 @@
 using ::ash::EulaScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::EulaScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_EULA_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/hid_detection_screen.h b/chrome/browser/ash/login/screens/hid_detection_screen.h
index 7a727acc..76b9db7 100644
--- a/chrome/browser/ash/login/screens/hid_detection_screen.h
+++ b/chrome/browser/ash/login/screens/hid_detection_screen.h
@@ -288,4 +288,10 @@
 using ::ash::HIDDetectionScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::HIDDetectionScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_HID_DETECTION_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/kiosk_autolaunch_screen.h b/chrome/browser/ash/login/screens/kiosk_autolaunch_screen.h
index 176aef04..e2d0148 100644
--- a/chrome/browser/ash/login/screens/kiosk_autolaunch_screen.h
+++ b/chrome/browser/ash/login/screens/kiosk_autolaunch_screen.h
@@ -56,4 +56,10 @@
 using ::ash::KioskAutolaunchScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::KioskAutolaunchScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_KIOSK_AUTOLAUNCH_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/network_screen.h b/chrome/browser/ash/login/screens/network_screen.h
index d4179bd..b01e63e3 100644
--- a/chrome/browser/ash/login/screens/network_screen.h
+++ b/chrome/browser/ash/login/screens/network_screen.h
@@ -145,4 +145,10 @@
 using ::ash::NetworkScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::NetworkScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_NETWORK_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/os_install_screen.h b/chrome/browser/ash/login/screens/os_install_screen.h
index ffbc3b7e..239e477 100644
--- a/chrome/browser/ash/login/screens/os_install_screen.h
+++ b/chrome/browser/ash/login/screens/os_install_screen.h
@@ -30,4 +30,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::OsInstallScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_OS_INSTALL_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/signin_fatal_error_screen.h b/chrome/browser/ash/login/screens/signin_fatal_error_screen.h
index b7597e8..5692713 100644
--- a/chrome/browser/ash/login/screens/signin_fatal_error_screen.h
+++ b/chrome/browser/ash/login/screens/signin_fatal_error_screen.h
@@ -76,4 +76,10 @@
 using ::ash::SignInFatalErrorScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::SignInFatalErrorScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_SIGNIN_FATAL_ERROR_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc b/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc
index 1fab3dc..565c257 100644
--- a/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/update_required_screen_browsertest.cc
@@ -94,7 +94,7 @@
 constexpr char kDemoEolMessage[] = "Please return your device.";
 
 chromeos::OobeUI* GetOobeUI() {
-  auto* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = LoginDisplayHost::default_host();
   return host ? host->GetOobeUI() : nullptr;
 }
 
diff --git a/chrome/browser/ash/login/screens/update_screen.h b/chrome/browser/ash/login/screens/update_screen.h
index 42535493..d299c83 100644
--- a/chrome/browser/ash/login/screens/update_screen.h
+++ b/chrome/browser/ash/login/screens/update_screen.h
@@ -239,4 +239,10 @@
 using ::ash::UpdateScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::UpdateScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_UPDATE_SCREEN_H_
diff --git a/chrome/browser/ash/login/screens/update_screen_browsertest.cc b/chrome/browser/ash/login/screens/update_screen_browsertest.cc
index c2077870..f9470ac 100644
--- a/chrome/browser/ash/login/screens/update_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/update_screen_browsertest.cc
@@ -98,7 +98,7 @@
 }
 
 chromeos::OobeUI* GetOobeUI() {
-  auto* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = LoginDisplayHost::default_host();
   return host ? host->GetOobeUI() : nullptr;
 }
 
diff --git a/chrome/browser/ash/login/screens/welcome_screen.h b/chrome/browser/ash/login/screens/welcome_screen.h
index 3585660..ae4602f 100644
--- a/chrome/browser/ash/login/screens/welcome_screen.h
+++ b/chrome/browser/ash/login/screens/welcome_screen.h
@@ -198,4 +198,10 @@
 using ::ash::WelcomeScreen;
 }
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::WelcomeScreen;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_SCREENS_WELCOME_SCREEN_H_
diff --git a/chrome/browser/ash/login/session/user_session_manager.h b/chrome/browser/ash/login/session/user_session_manager.h
index b9d4c36..6c7fcba 100644
--- a/chrome/browser/ash/login/session/user_session_manager.h
+++ b/chrome/browser/ash/login/session/user_session_manager.h
@@ -31,8 +31,6 @@
 #include "chrome/browser/ash/login/signin/token_handle_util.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
 #include "chrome/browser/ash/login/ui/input_events_blocker.h"
-// TODO(https://crbug.com/1164001): move to forward declaration.
-#include "chrome/browser/ash/login/ui/login_display_host.h"
 #include "chrome/browser/ash/net/secure_dns_manager.h"
 #include "chrome/browser/ash/release_notes/release_notes_notification.h"
 // TODO(https://crbug.com/1164001): move to forward declaration.
@@ -67,7 +65,7 @@
 }  // namespace user_manager
 
 namespace ash {
-
+class LoginDisplayHost;
 class OnboardingUserActivityCounter;
 
 namespace test {
diff --git a/chrome/browser/ash/login/test/kiosk_test_helpers.h b/chrome/browser/ash/login/test/kiosk_test_helpers.h
index 6430f66..69612e2 100644
--- a/chrome/browser/ash/login/test/kiosk_test_helpers.h
+++ b/chrome/browser/ash/login/test/kiosk_test_helpers.h
@@ -78,6 +78,7 @@
 // TODO(https://crbug.com/1164001): remove when moved to chrome/browser/ash/.
 namespace ash {
 using ::chromeos::KioskSessionInitializedWaiter;
+using ::chromeos::ScopedCanConfigureNetwork;
 using ::chromeos::ScopedDeviceSettings;
 }
 
diff --git a/chrome/browser/ash/login/ui/fake_login_display_host.cc b/chrome/browser/ash/login/ui/fake_login_display_host.cc
index 63f9239..a9b8e2e 100644
--- a/chrome/browser/ash/login/ui/fake_login_display_host.cc
+++ b/chrome/browser/ash/login/ui/fake_login_display_host.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/ash/login/wizard_controller.h"
 #include "components/session_manager/core/session_manager.h"
 
-namespace chromeos {
+namespace ash {
 
 class FakeLoginDisplayHost::FakeBaseScreen : public BaseScreen {
  public:
@@ -116,7 +116,7 @@
 
 void FakeLoginDisplayHost::SetShelfButtonsEnabled(bool enabled) {}
 
-void FakeLoginDisplayHost::UpdateOobeDialogState(ash::OobeDialogState state) {}
+void FakeLoginDisplayHost::UpdateOobeDialogState(OobeDialogState state) {}
 
 void FakeLoginDisplayHost::CancelPasswordChangedFlow() {}
 
@@ -124,8 +124,7 @@
 
 void FakeLoginDisplayHost::ResyncUserData() {}
 
-bool FakeLoginDisplayHost::HandleAccelerator(
-    ash::LoginAcceleratorAction action) {
+bool FakeLoginDisplayHost::HandleAccelerator(LoginAcceleratorAction action) {
   return false;
 }
 
@@ -150,4 +149,4 @@
   return nullptr;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/login/ui/fake_login_display_host.h b/chrome/browser/ash/login/ui/fake_login_display_host.h
index 2a56ceb..36d9485 100644
--- a/chrome/browser/ash/login/ui/fake_login_display_host.h
+++ b/chrome/browser/ash/login/ui/fake_login_display_host.h
@@ -17,14 +17,14 @@
 class SessionManager;
 }
 
-namespace chromeos {
+namespace ash {
 
 class FakeLoginDisplayHost : public LoginDisplayHost {
  public:
   FakeLoginDisplayHost();
   ~FakeLoginDisplayHost() override;
 
-  // chromeos::LoginDisplayHost:
+  // LoginDisplayHost:
   LoginDisplay* GetLoginDisplay() override;
   ExistingUserController* GetExistingUserController() override;
   gfx::NativeWindow GetNativeWindow() const override;
@@ -57,11 +57,11 @@
   void ShowGaiaDialog(const AccountId& prefilled_account) override;
   void HideOobeDialog() override;
   void SetShelfButtonsEnabled(bool enabled) override;
-  void UpdateOobeDialogState(ash::OobeDialogState state) override;
+  void UpdateOobeDialogState(OobeDialogState state) override;
   void CancelPasswordChangedFlow() override;
   void MigrateUserData(const std::string& old_password) override;
   void ResyncUserData() override;
-  bool HandleAccelerator(ash::LoginAcceleratorAction action) override;
+  bool HandleAccelerator(LoginAcceleratorAction action) override;
   void HandleDisplayCaptivePortal() override;
   void UpdateAddUserButtonStatus() override;
   void RequestSystemInfoUpdate() override;
@@ -82,6 +82,12 @@
   DISALLOW_COPY_AND_ASSIGN(FakeLoginDisplayHost);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace chromeos {
+using ::ash::FakeLoginDisplayHost;
+}
 
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_FAKE_LOGIN_DISPLAY_HOST_H_
diff --git a/chrome/browser/ash/login/ui/kiosk_app_menu_controller.cc b/chrome/browser/ash/login/ui/kiosk_app_menu_controller.cc
index 85cf2c9..e8a06e25 100644
--- a/chrome/browser/ash/login/ui/kiosk_app_menu_controller.cc
+++ b/chrome/browser/ash/login/ui/kiosk_app_menu_controller.cc
@@ -89,7 +89,7 @@
 }
 
 void KioskAppMenuController::LaunchApp(const ash::KioskAppMenuEntry& app) {
-  auto* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = LoginDisplayHost::default_host();
   if (!app.account_id.is_valid())
     return;
 
diff --git a/chrome/browser/ash/login/ui/login_display.h b/chrome/browser/ash/login/ui/login_display.h
index 269b901..82572048 100644
--- a/chrome/browser/ash/login/ui/login_display.h
+++ b/chrome/browser/ash/login/ui/login_display.h
@@ -97,4 +97,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::LoginDisplay;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_LOGIN_DISPLAY_H_
diff --git a/chrome/browser/ash/login/ui/login_display_host.cc b/chrome/browser/ash/login/ui/login_display_host.cc
index 3225120..fb25bbb 100644
--- a/chrome/browser/ash/login/ui/login_display_host.cc
+++ b/chrome/browser/ash/login/ui/login_display_host.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ash/login/ui/login_display_host.h"
 
-namespace chromeos {
+namespace ash {
 
 // static
 LoginDisplayHost* LoginDisplayHost::default_host_ = nullptr;
@@ -18,4 +18,4 @@
   default_host_ = nullptr;
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/login/ui/login_display_host.h b/chrome/browser/ash/login/ui/login_display_host.h
index 66f19412..517cd87 100644
--- a/chrome/browser/ash/login/ui/login_display_host.h
+++ b/chrome/browser/ash/login/ui/login_display_host.h
@@ -13,23 +13,22 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list_types.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-// TODO(https://crbug.com/1164001): move KioskAppId to forward declaration
-// when moved to chrome/browser/ash/.
-#include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/ash/customization/customization_document.h"
+// TODO(https://crbug.com/1164001): use forward declaration.
+#include "chrome/browser/ash/login/existing_user_controller.h"
 #include "chrome/browser/ash/login/oobe_screen.h"
 #include "chrome/browser/ash/login/ui/login_display.h"
 #include "chrome/browser/ash/login/ui/signin_ui.h"
+// TODO(https://crbug.com/1164001): use forward declaration.
+#include "chrome/browser/ash/login/ui/webui_login_view.h"
+// TODO(https://crbug.com/1164001): use forward declaration.
+#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "components/user_manager/user_type.h"
 
 #include "ui/gfx/native_widget_types.h"
 
 class AccountId;
 
-namespace ash {
-enum class OobeDialogState;
-}
-
 namespace content {
 class WebContents;
 }
@@ -38,13 +37,11 @@
 class Rect;
 }  // namespace gfx
 
-namespace chromeos {
-
+namespace ash {
+class KioskAppId;
 class KioskLaunchController;
-class ExistingUserController;
-class OobeUI;
-class WebUILoginView;
 class WizardController;
+enum class OobeDialogState;
 
 // An interface that defines an out-of-box-experience (OOBE) or login screen
 // host. It contains code specific to the login UI implementation.
@@ -155,7 +152,7 @@
   virtual void SetShelfButtonsEnabled(bool enabled) = 0;
 
   // Update the state of the oobe dialog.
-  virtual void UpdateOobeDialogState(ash::OobeDialogState state) = 0;
+  virtual void UpdateOobeDialogState(OobeDialogState state) = 0;
 
   // Confirms sign in by provided credentials in `user_context`.
   // Used for new user login via GAIA extension.
@@ -199,7 +196,7 @@
 
   // Handles an accelerator action.
   // Returns `true` if the accelerator was handled.
-  virtual bool HandleAccelerator(ash::LoginAcceleratorAction action) = 0;
+  virtual bool HandleAccelerator(LoginAcceleratorAction action) = 0;
 
   // Handles a request to show the captive portal web dialog. For webui, the
   // dialog is displayed immediately. For views, the dialog is displayed as soon
@@ -237,11 +234,11 @@
   DISALLOW_COPY_AND_ASSIGN(LoginDisplayHost);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 // TODO(https://crbug.com/1164001): remove when moved to ash.
-namespace ash {
-using ::chromeos::LoginDisplayHost;
+namespace chromeos {
+using ::ash::LoginDisplayHost;
 }
 
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_LOGIN_DISPLAY_HOST_H_
diff --git a/chrome/browser/ash/login/ui/login_display_host_common.h b/chrome/browser/ash/login/ui/login_display_host_common.h
index 0aba442..1d549af 100644
--- a/chrome/browser/ash/login/ui/login_display_host_common.h
+++ b/chrome/browser/ash/login/ui/login_display_host_common.h
@@ -10,6 +10,8 @@
 #include <vector>
 
 #include "ash/public/cpp/login_accelerators.h"
+// TODO(https://crbug.com/1164001): use forward declaration.
+#include "chrome/browser/ash/login/app_mode/kiosk_launch_controller.h"
 #include "chrome/browser/ash/login/ui/kiosk_app_menu_controller.h"
 #include "chrome/browser/ash/login/ui/login_display_host.h"
 #include "chrome/browser/ash/login/ui/signin_ui.h"
diff --git a/chrome/browser/ash/login/ui/login_display_host_mojo.h b/chrome/browser/ash/login/ui/login_display_host_mojo.h
index f3168232..af328f5 100644
--- a/chrome/browser/ash/login/ui/login_display_host_mojo.h
+++ b/chrome/browser/ash/login/ui/login_display_host_mojo.h
@@ -19,6 +19,8 @@
 #include "chrome/browser/ash/login/security_token_pin_dialog_host_ash_impl.h"
 #include "chrome/browser/ash/login/ui/login_display_host_common.h"
 #include "chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.h"
+// TODO(https://crbug.com/1164001): use forward declaration.
+#include "chrome/browser/ash/login/wizard_controller.h"
 #include "chrome/browser/ui/ash/login_screen_client_impl.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.cc b/chrome/browser/ash/login/ui/login_display_host_webui.cc
index c9c5c07..d887fa4c 100644
--- a/chrome/browser/ash/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/ash/login/ui/login_display_host_webui.cc
@@ -193,7 +193,7 @@
 }
 
 void MaybeShowDeviceDisabledScreen() {
-  DCHECK(chromeos::LoginDisplayHost::default_host());
+  DCHECK(LoginDisplayHost::default_host());
   if (!g_browser_process->platform_part()->device_disabling_manager()) {
     // Device disabled check will be done in the DeviceDisablingManager.
     return;
@@ -202,7 +202,7 @@
   if (!system::DeviceDisablingManager::IsDeviceDisabledDuringNormalOperation())
     return;
 
-  chromeos::LoginDisplayHost::default_host()->StartWizard(
+  LoginDisplayHost::default_host()->StartWizard(
       DeviceDisabledScreenView::kScreenId);
 }
 
@@ -238,15 +238,14 @@
 
   // Create the LoginDisplayHost. Use the views-based implementation only for
   // the sign-in screen.
-  chromeos::LoginDisplayHost* display_host = nullptr;
-  if (chromeos::LoginDisplayHost::default_host()) {
+  LoginDisplayHost* display_host = nullptr;
+  if (LoginDisplayHost::default_host()) {
     // Tests may have already allocated an instance for us to use.
-    display_host = chromeos::LoginDisplayHost::default_host();
+    display_host = LoginDisplayHost::default_host();
   } else if (ShouldShowSigninScreen(first_screen)) {
-    display_host =
-        new chromeos::LoginDisplayHostMojo(DisplayedScreen::SIGN_IN_SCREEN);
+    display_host = new LoginDisplayHostMojo(DisplayedScreen::SIGN_IN_SCREEN);
   } else {
-    display_host = new chromeos::LoginDisplayHostWebUI();
+    display_host = new LoginDisplayHostWebUI();
   }
 
   // Restore system timezone.
@@ -278,7 +277,7 @@
   // This step requires the session manager to have been initialized and login
   // display host to be created.
   DCHECK(session_manager::SessionManager::Get());
-  DCHECK(chromeos::LoginDisplayHost::default_host());
+  DCHECK(LoginDisplayHost::default_host());
   WallpaperControllerClientImpl::Get()->SetInitialWallpaper();
   // TODO(crbug.com/1105387): Part of initial screen logic.
   MaybeShowDeviceDisabledScreen();
diff --git a/chrome/browser/ash/login/ui/login_web_dialog.cc b/chrome/browser/ash/login/ui/login_web_dialog.cc
index 3ba49ef..88316aa 100644
--- a/chrome/browser/ash/login/ui/login_web_dialog.cc
+++ b/chrome/browser/ash/login/ui/login_web_dialog.cc
@@ -57,10 +57,8 @@
       delegate_(delegate),
       title_(title),
       url_(url) {
-  if (!parent_window_ && chromeos::LoginDisplayHost::default_host()) {
-    parent_window_ =
-        chromeos::LoginDisplayHost::default_host()->GetNativeWindow();
-  }
+  if (!parent_window_ && LoginDisplayHost::default_host())
+    parent_window_ = LoginDisplayHost::default_host()->GetNativeWindow();
   LOG_IF(WARNING, !parent_window)
       << "No parent window. Dialog sizes could be wrong";
 }
diff --git a/chrome/browser/ash/login/ui/mock_login_display.h b/chrome/browser/ash/login/ui/mock_login_display.h
index 8bc546ad..05e3a90 100644
--- a/chrome/browser/ash/login/ui/mock_login_display.h
+++ b/chrome/browser/ash/login/ui/mock_login_display.h
@@ -30,4 +30,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::MockLoginDisplay;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_MOCK_LOGIN_DISPLAY_H_
diff --git a/chrome/browser/ash/login/ui/mock_login_display_host.cc b/chrome/browser/ash/login/ui/mock_login_display_host.cc
index 4b1386d3..55fd633 100644
--- a/chrome/browser/ash/login/ui/mock_login_display_host.cc
+++ b/chrome/browser/ash/login/ui/mock_login_display_host.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/ash/login/ui/mock_login_display_host.h"
 
-namespace chromeos {
+namespace ash {
 
 MockLoginDisplayHost::MockLoginDisplayHost() {}
 
 MockLoginDisplayHost::~MockLoginDisplayHost() {}
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/login/ui/mock_login_display_host.h b/chrome/browser/ash/login/ui/mock_login_display_host.h
index d4f9182..00f0367 100644
--- a/chrome/browser/ash/login/ui/mock_login_display_host.h
+++ b/chrome/browser/ash/login/ui/mock_login_display_host.h
@@ -11,12 +11,14 @@
 #include "base/macros.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_types.h"
 #include "chrome/browser/ash/login/ui/login_display_host.h"
+// TODO(https://crbug.com/1164001): move to forward declaration
+#include "chrome/browser/ash/login/ui/webui_login_view.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "components/user_manager/user_type.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-namespace chromeos {
+namespace ash {
 
 class MockLoginDisplayHost : public LoginDisplayHost {
  public:
@@ -60,10 +62,7 @@
   MOCK_METHOD(void, ShowGaiaDialog, (const AccountId&), (override));
   MOCK_METHOD(void, HideOobeDialog, (), (override));
   MOCK_METHOD(void, SetShelfButtonsEnabled, (bool), (override));
-  MOCK_METHOD(void,
-              UpdateOobeDialogState,
-              (ash::OobeDialogState state),
-              (override));
+  MOCK_METHOD(void, UpdateOobeDialogState, (OobeDialogState state), (override));
 
   MOCK_METHOD(void, CompleteLogin, (const UserContext&), (override));
   MOCK_METHOD(void, OnGaiaScreenReady, (), (override));
@@ -83,7 +82,7 @@
   MOCK_METHOD(void, ResyncUserData, (), (override));
   MOCK_METHOD(bool,
               HandleAccelerator,
-              (ash::LoginAcceleratorAction action),
+              (LoginAcceleratorAction action),
               (override));
   MOCK_METHOD(void, HandleDisplayCaptivePortal, (), (override));
   MOCK_METHOD(void, UpdateAddUserButtonStatus, (), (override));
@@ -98,6 +97,12 @@
   DISALLOW_COPY_AND_ASSIGN(MockLoginDisplayHost);
 };
 
-}  // namespace chromeos
+}  // namespace ash
+
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace chromeos {
+using ::ash::MockLoginDisplayHost;
+}
 
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_MOCK_LOGIN_DISPLAY_HOST_H_
diff --git a/chrome/browser/ash/login/ui/signin_ui.h b/chrome/browser/ash/login/ui/signin_ui.h
index beedf092..06db6c4 100644
--- a/chrome/browser/ash/login/ui/signin_ui.h
+++ b/chrome/browser/ash/login/ui/signin_ui.h
@@ -71,6 +71,7 @@
 // source migration is finished.
 namespace ash {
 using ::chromeos::SigninError;
+using ::chromeos::SigninUI;
 }
 
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_SIGNIN_UI_H_
diff --git a/chrome/browser/ash/login/ui/webui_login_view.h b/chrome/browser/ash/login/ui/webui_login_view.h
index e7bf928..31a3a42 100644
--- a/chrome/browser/ash/login/ui/webui_login_view.h
+++ b/chrome/browser/ash/login/ui/webui_login_view.h
@@ -208,4 +208,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::WebUILoginView;
+}
+
 #endif  // CHROME_BROWSER_ASH_LOGIN_UI_WEBUI_LOGIN_VIEW_H_
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
index 4d075550..a6930f5 100644
--- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -1317,8 +1317,9 @@
 
 void ChromeUserManagerImpl::RemoveReportingUser(const AccountId& account_id) {
   ListPrefUpdate users_update(GetLocalState(), ::prefs::kReportingUsers);
-  users_update->Remove(
-      base::Value(FullyCanonicalize(account_id.GetUserEmail())), NULL);
+  users_update->EraseListIter(
+      std::find(users_update->GetList().begin(), users_update->GetList().end(),
+                base::Value(FullyCanonicalize(account_id.GetUserEmail()))));
 }
 
 const AccountId& ChromeUserManagerImpl::GetGuestAccountId() const {
diff --git a/chrome/browser/ash/login/users/supervised_user_manager_impl.cc b/chrome/browser/ash/login/users/supervised_user_manager_impl.cc
index 33b1c51..c3429a9 100644
--- a/chrome/browser/ash/login/users/supervised_user_manager_impl.cc
+++ b/chrome/browser/ash/login/users/supervised_user_manager_impl.cc
@@ -244,7 +244,7 @@
     const std::string& user_id) {
   PrefService* prefs = g_browser_process->local_state();
   ListPrefUpdate prefs_new_users_update(prefs, kSupervisedUsersFirstRun);
-  prefs_new_users_update->Remove(base::Value(user_id), NULL);
+  prefs_new_users_update->EraseListValue(base::Value(user_id));
 
   CleanPref(user_id, kSupervisedUserSyncId);
   CleanPref(user_id, kSupervisedUserManagers);
@@ -267,7 +267,7 @@
 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) {
   ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(),
                                         kSupervisedUsersFirstRun);
-  return prefs_new_users_update->Remove(base::Value(user_id), NULL);
+  return prefs_new_users_update->EraseListValue(base::Value(user_id));
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index 564cfc1..a6e7660 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -194,10 +194,11 @@
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/accelerators/accelerator.h"
 
-using content::BrowserThread;
-
+namespace ash {
 namespace {
 
+using ::content::BrowserThread;
+
 bool g_using_zero_delays = false;
 
 // Total timezone resolving process timeout.
@@ -242,10 +243,10 @@
 // The HID detection screen is only allowed for form factors without built-in
 // inputs: Chromebases, Chromebits, and Chromeboxes (crbug.com/965765).
 bool CanShowHIDDetectionScreen() {
-  switch (chromeos::GetDeviceType()) {
-    case chromeos::DeviceType::kChromebase:
-    case chromeos::DeviceType::kChromebit:
-    case chromeos::DeviceType::kChromebox:
+  switch (GetDeviceType()) {
+    case DeviceType::kChromebase:
+    case DeviceType::kChromebit:
+    case DeviceType::kChromebox:
       return true;
     default:
       return false;
@@ -329,12 +330,12 @@
   histogram_with_reason->AddTime(step_time);
 }
 
-chromeos::LoginDisplayHost* GetLoginDisplayHost() {
-  return chromeos::LoginDisplayHost::default_host();
+LoginDisplayHost* GetLoginDisplayHost() {
+  return LoginDisplayHost::default_host();
 }
 
 chromeos::OobeUI* GetOobeUI() {
-  auto* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = LoginDisplayHost::default_host();
   return host ? host->GetOobeUI() : nullptr;
 }
 
@@ -353,8 +354,6 @@
 
 }  // namespace
 
-namespace chromeos {
-
 // static
 const int WizardController::kMinAudibleOutputVolumePercent = 10;
 
@@ -373,7 +372,7 @@
 
 // static
 WizardController* WizardController::default_controller() {
-  auto* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = LoginDisplayHost::default_host();
   return host ? host->GetWizardController() : nullptr;
 }
 
@@ -490,7 +489,7 @@
   }
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kOobeSkipToLogin)) {
+          switches::kOobeSkipToLogin)) {
     SkipToLoginForTesting();
   }
 }
@@ -1637,7 +1636,7 @@
 void WizardController::InitiateOOBEUpdate() {
   // If this is a Cellular First device, instruct UpdateEngine to allow
   // updates over cellular data connections.
-  if (chromeos::switches::IsCellularFirstDevice()) {
+  if (switches::IsCellularFirstDevice()) {
     DBusThreadManager::Get()
         ->GetUpdateEngineClient()
         ->SetUpdateOverCellularPermission(
@@ -1908,7 +1907,7 @@
   }
 }
 
-bool WizardController::HandleAccelerator(ash::LoginAcceleratorAction action) {
+bool WizardController::HandleAccelerator(LoginAcceleratorAction action) {
   if (current_screen_) {
     if (current_screen_->HandleAccelerator(action))
       return true;
@@ -2138,7 +2137,7 @@
   if (!timezone->timeZoneId.empty()) {
     VLOG(1) << "Resolve TimeZone: setting timezone to '" << timezone->timeZoneId
             << "'";
-    chromeos::system::SetSystemAndSigninScreenTimezone(timezone->timeZoneId);
+    system::SetSystemAndSigninScreenTimezone(timezone->timeZoneId);
   }
 }
 
@@ -2257,4 +2256,4 @@
   return auto_enrollment_controller_.get();
 }
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/login/wizard_controller.h b/chrome/browser/ash/login/wizard_controller.h
index 5fc0ce44..fe6018f 100644
--- a/chrome/browser/ash/login/wizard_controller.h
+++ b/chrome/browser/ash/login/wizard_controller.h
@@ -25,10 +25,14 @@
 #include "chrome/browser/ash/login/demo_mode/demo_setup_controller.h"
 #include "chrome/browser/ash/login/enrollment/auto_enrollment_controller.h"
 #include "chrome/browser/ash/login/enrollment/enrollment_screen.h"
+// TODO(https://crbug.com/1164001): move to forward declaration
+#include "chrome/browser/ash/login/helper.h"
 #include "chrome/browser/ash/login/screen_manager.h"
 #include "chrome/browser/ash/login/screens/active_directory_login_screen.h"
 #include "chrome/browser/ash/login/screens/arc_terms_of_service_screen.h"
 #include "chrome/browser/ash/login/screens/assistant_optin_flow_screen.h"
+// TODO(https://crbug.com/1164001): move to forward declaration
+#include "chrome/browser/ash/login/screens/base_screen.h"
 #include "chrome/browser/ash/login/screens/demo_preferences_screen.h"
 #include "chrome/browser/ash/login/screens/demo_setup_screen.h"
 #include "chrome/browser/ash/login/screens/edu_coexistence_login_screen.h"
@@ -60,24 +64,21 @@
 #include "chrome/browser/ash/login/screens/update_screen.h"
 #include "chrome/browser/ash/login/screens/user_creation_screen.h"
 #include "chrome/browser/ash/login/screens/welcome_screen.h"
-// TODO(https://crbug.com/1164001): move LoginDisplayHost to forward
-// declaration when moved to chrome/browser/ash/.
-#include "chrome/browser/ash/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/policy/enrollment_config.h"
+// TODO(https://crbug.com/1164001): move to forward declaration.
+#include "chromeos/geolocation/geoposition.h"
+// TODO(https://crbug.com/1164001): move to forward declaration.
+#include "chromeos/geolocation/simple_geolocation_provider.h"
+// TODO(https://crbug.com/1164001): move to forward declaration.
+#include "chromeos/timezone/timezone_provider.h"
+// TODO(https://crbug.com/1164001): move to forward declaration.
+#include "chromeos/timezone/timezone_request.h"
 #include "components/account_id/account_id.h"
 
 class PrefService;
 
-namespace chromeos {
-
-namespace login {
-class NetworkStateHelper;
-}  // namespace login
-
-struct Geoposition;
-class SimpleGeolocationProvider;
-class TimeZoneProvider;
-struct TimeZoneResponseData;
+namespace ash {
+class ErrorScreen;
 
 // Class that manages control flow between wizard screens. Wizard controller
 // interacts with screen controllers to move the user between screens.
@@ -527,10 +528,12 @@
   DISALLOW_COPY_AND_ASSIGN(WizardController);
 };
 
-}  // namespace chromeos
+}  // namespace ash
 
 // TODO(https://crbug.com/1164001): remove after //chrome/browser/chromeos
 // source migration is finished.
-using ::chromeos::WizardController;
+namespace chromeos {
+using ::ash::WizardController;
+}
 
 #endif  // CHROME_BROWSER_ASH_LOGIN_WIZARD_CONTROLLER_H_
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc
index 76eee26..97124ca 100644
--- a/chrome/browser/ash/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -112,19 +112,13 @@
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
 
+namespace ash {
+namespace {
+
 using ::testing::_;
-using ::testing::AtLeast;
-using ::testing::Exactly;
-using ::testing::Invoke;
 using ::testing::IsNull;
 using ::testing::Mock;
-using ::testing::Not;
 using ::testing::NotNull;
-using ::testing::Return;
-
-namespace chromeos {
-
-namespace {
 
 const char kGeolocationResponseBody[] =
     "{\n"
@@ -679,7 +673,7 @@
           }
         }));
 
-    ASSERT_TRUE(ash::LoginScreenTestApi::IsLoginShelfShown());
+    ASSERT_TRUE(LoginScreenTestApi::IsLoginShelfShown());
 
     EXPECT_CALL(*mock_welcome_screen_, HideImpl()).Times(1);
     EXPECT_CALL(*mock_eula_screen_, ShowImpl()).Times(1);
@@ -692,7 +686,7 @@
 
     CheckCurrentScreen(EulaView::kScreenId);
     // Login shelf should still be visible.
-    EXPECT_TRUE(ash::LoginScreenTestApi::IsLoginShelfShown());
+    EXPECT_TRUE(LoginScreenTestApi::IsLoginShelfShown());
 
     EXPECT_CALL(*mock_eula_screen_, HideImpl()).Times(1);
     EXPECT_CALL(*mock_update_screen_, ShowImpl()).Times(1);
@@ -1920,11 +1914,11 @@
   WizardController* const wizard_controller =
       WizardController::default_controller();
   ASSERT_TRUE(wizard_controller != nullptr);
-  EXPECT_EQ(1, ash::LoginScreenTestApi::GetUsersCount());
+  EXPECT_EQ(1, LoginScreenTestApi::GetUsersCount());
 
   // Check reset screen is visible on startup.
   OobeScreenWaiter(ResetView::kScreenId).Wait();
-  EXPECT_TRUE(ash::LoginScreenTestApi::IsOobeDialogVisible());
+  EXPECT_TRUE(LoginScreenTestApi::IsOobeDialogVisible());
 
   // Showing update required screen should fail due to lower priority than reset
   // screen.
@@ -2810,4 +2804,4 @@
 
 // TODO(khorimoto): Add tests for MultiDevice Setup UI.
 
-}  // namespace chromeos
+}  // namespace ash
diff --git a/chrome/browser/ash/ownership/owner_settings_service_ash.cc b/chrome/browser/ash/ownership/owner_settings_service_ash.cc
index 6577349..0ceb957b 100644
--- a/chrome/browser/ash/ownership/owner_settings_service_ash.cc
+++ b/chrome/browser/ash/ownership/owner_settings_service_ash.cc
@@ -336,11 +336,11 @@
   const base::Value* old_value = CrosSettings::Get()->GetPref(setting);
   if (old_value && !old_value->is_list())
     return false;
-  std::unique_ptr<base::ListValue> new_value(
-      old_value ? static_cast<const base::ListValue*>(old_value)->DeepCopy()
-                : new base::ListValue());
-  new_value->Remove(value, nullptr);
-  return Set(setting, *new_value);
+  base::Value new_value(base::Value::Type::LIST);
+  if (old_value)
+    new_value = old_value->Clone();
+  new_value.EraseListValue(value);
+  return Set(setting, std::move(new_value));
 }
 
 bool OwnerSettingsServiceAsh::CommitTentativeDeviceSettings(
diff --git a/chrome/browser/ash/web_applications/file_manager_web_app_info.cc b/chrome/browser/ash/web_applications/file_manager_web_app_info.cc
index 47e057c..bbf1d8e 100644
--- a/chrome/browser/ash/web_applications/file_manager_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/file_manager_web_app_info.cc
@@ -6,8 +6,8 @@
 
 #include <string>
 
+#include "ash/content/file_manager/resources/grit/file_manager_swa_resources.h"
 #include "ash/content/file_manager/url_constants.h"
-#include "ash/grit/ash_file_manager_resources.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/web_applications/system_web_app_install_utils.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
@@ -21,8 +21,8 @@
   // TODO(majewski): Fetch from a resource.
   info->title = u"File Manager";
   web_app::CreateIconInfoForSystemWebApp(
-      info->start_url, {{"icon192.png", 192, IDR_FILE_MANAGER_SWA_ICON_192}},
-      *info);
+      info->start_url,
+      {{"icon192.png", 192, IDR_FILE_MANAGER_SWA_IMAGES_ICON192_PNG}}, *info);
   info->theme_color = 0xFF4285F4;
   info->background_color = 0xFFFFFFFF;
   info->display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index c2169a0c..7c17e55c 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -497,6 +497,7 @@
 #include "chrome/browser/serial/chrome_serial_delegate.h"
 #include "chrome/browser/task_manager/task_manager_interface.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -5226,6 +5227,26 @@
   return AuthenticatorRequestScheduler::CreateRequestDelegate(
       render_frame_host);
 }
+
+void ChromeContentBrowserClient::ShowDirectSocketsConnectionDialog(
+    content::RenderFrameHost* owner,
+    const std::string& address,
+    base::OnceCallback<void(bool, const std::string&, const std::string&)>
+        callback) {
+  auto* contents = content::WebContents::FromRenderFrameHost(owner);
+  if (!contents)
+    return;
+
+  auto* browser = chrome::FindBrowserWithWebContents(contents);
+  if (!browser ||
+      browser->tab_strip_model()->GetActiveWebContents() != contents) {
+    std::move(callback).Run(false, std::string(), std::string());
+    return;
+  }
+
+  chrome::ShowDirectSocketsConnectionDialog(browser, address,
+                                            std::move(callback));
+}
 #endif
 
 std::unique_ptr<net::ClientCertStore>
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index b0d91a2..0dd59b0 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -566,6 +566,11 @@
   std::unique_ptr<content::AuthenticatorRequestClientDelegate>
   GetWebAuthenticationRequestDelegate(
       content::RenderFrameHost* render_frame_host) override;
+  void ShowDirectSocketsConnectionDialog(
+      content::RenderFrameHost* owner,
+      const std::string& address,
+      base::OnceCallback<void(bool, const std::string&, const std::string&)>
+          callback) override;
 #endif
   bool ShowPaymentHandlerWindow(
       content::BrowserContext* browser_context,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 1834781..2d58c48 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3239,8 +3239,8 @@
 
   if (!is_official_build) {
     deps += [
-      "//ash/components/resources:file_manager_resources_grit",
       "//ash/content/file_manager:file_manager_ui",
+      "//ash/content/file_manager/resources:file_manager_swa_resources_grit",
       "//chromeos/components/demo_mode_app_ui",
       "//chromeos/components/sample_system_web_app_ui",
       "//chromeos/components/telemetry_extension_ui",
@@ -3997,6 +3997,7 @@
     "fileapi/recent_disk_source_unittest.cc",
     "fileapi/recent_model_unittest.cc",
     "fileapi/test/fake_recent_source.cc",
+    "full_restore/arc_ghost_window_view_unittest.cc",
     "full_restore/arc_window_utils_unittest.cc",
     "full_restore/full_restore_prefs_unittest.cc",
     "full_restore/full_restore_service_unittest.cc",
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index f209b70..f4b3cc8e 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -263,7 +263,7 @@
   // Do not attempt to open File Manager while the login is in progress or
   // the screen is locked or running in kiosk app mode and make sure the file
   // manager is opened only for the active user.
-  if (chromeos::LoginDisplayHost::default_host() ||
+  if (ash::LoginDisplayHost::default_host() ||
       chromeos::ScreenLocker::default_screen_locker() ||
       chrome::IsRunningInForcedAppMode() ||
       profile != ProfileManager::GetActiveUserProfile()) {
@@ -924,16 +924,44 @@
           path, &mount_name, &file_system_name, &full_path))
     return;
 
-  for (const auto& extension_id : GetEventListenerExtensionIds(
-           profile_, file_manager_private::OnCrostiniChanged::kEventName)) {
+  const std::string event_name(
+      file_manager_private::OnCrostiniChanged::kEventName);
+  const extensions::EventListenerMap::ListenerList& listeners =
+      extensions::EventRouter::Get(profile_)
+          ->listeners()
+          .GetEventListenersByName(event_name);
+
+  // We handle two types of listeners, those with extension IDs and those with
+  // listener URL. For listeners with extension IDs we use direct dispatch. For
+  // listeners with listener URL we use a broadcast.
+  std::set<std::string> extension_ids;
+  std::set<url::Origin> origins;
+  for (auto const& listener : listeners) {
+    if (!listener->extension_id().empty()) {
+      extension_ids.insert(listener->extension_id());
+    } else if (listener->listener_url().is_valid()) {
+      origins.insert(url::Origin::Create(listener->listener_url()));
+    }
+  }
+
+  for (const std::string& extension_id : extension_ids) {
+    url::Origin origin = url::Origin::Create(
+        extensions::Extension::GetBaseURLFromExtensionId(extension_id));
     file_manager_private::CrostiniEvent event;
-    PopulateCrostiniEvent(event, event_type, vm_name, extension_id, mount_name,
+    PopulateCrostiniEvent(event, event_type, vm_name, origin, mount_name,
                           file_system_name, full_path);
     DispatchEventToExtension(
         profile_, extension_id,
         extensions::events::FILE_MANAGER_PRIVATE_ON_CROSTINI_CHANGED,
-        file_manager_private::OnCrostiniChanged::kEventName,
-        file_manager_private::OnCrostiniChanged::Create(event));
+        event_name, file_manager_private::OnCrostiniChanged::Create(event));
+  }
+  for (const url::Origin& origin : origins) {
+    file_manager_private::CrostiniEvent event;
+    PopulateCrostiniEvent(event, event_type, vm_name, origin, mount_name,
+                          file_system_name, full_path);
+    BroadcastEvent(
+        profile_, extensions::events::FILE_MANAGER_PRIVATE_ON_CROSTINI_CHANGED,
+        event_name, file_manager_private::OnCrostiniChanged::Create(event));
   }
 }
 
@@ -942,7 +970,7 @@
     file_manager_private::CrostiniEvent& event,
     file_manager_private::CrostiniEventType event_type,
     const std::string& vm_name,
-    const std::string& extension_id,
+    const url::Origin& origin,
     const std::string& mount_name,
     const std::string& file_system_name,
     const std::string& full_path) {
@@ -951,9 +979,7 @@
   file_manager_private::CrostiniEvent::EntriesType entry;
   entry.additional_properties.SetString(
       "fileSystemRoot",
-      storage::GetExternalFileSystemRootURIString(
-          extensions::Extension::GetBaseURLFromExtensionId(extension_id),
-          mount_name));
+      storage::GetExternalFileSystemRootURIString(origin.GetURL(), mount_name));
   entry.additional_properties.SetString("fileSystemName", file_system_name);
   entry.additional_properties.SetString("fileFullPath", full_path);
   entry.additional_properties.SetBoolean("fileIsDirectory", true);
@@ -1017,18 +1043,14 @@
 }
 
 void EventRouter::DropFailedPluginVmDirectoryNotShared() {
-  for (const auto& extension_id : GetEventListenerExtensionIds(
-           profile_, file_manager_private::OnCrostiniChanged::kEventName)) {
-    file_manager_private::CrostiniEvent event;
-    event.vm_name = plugin_vm::kPluginVmName;
-    event.event_type = file_manager_private::
-        CROSTINI_EVENT_TYPE_DROP_FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED;
-    DispatchEventToExtension(
-        profile_, extension_id,
-        extensions::events::FILE_MANAGER_PRIVATE_ON_CROSTINI_CHANGED,
-        file_manager_private::OnCrostiniChanged::kEventName,
-        file_manager_private::OnCrostiniChanged::Create(event));
-  }
+  file_manager_private::CrostiniEvent event;
+  event.vm_name = plugin_vm::kPluginVmName;
+  event.event_type = file_manager_private::
+      CROSTINI_EVENT_TYPE_DROP_FAILED_PLUGIN_VM_DIRECTORY_NOT_SHARED;
+  BroadcastEvent(profile_,
+                 extensions::events::FILE_MANAGER_PRIVATE_ON_CROSTINI_CHANGED,
+                 file_manager_private::OnCrostiniChanged::kEventName,
+                 file_manager_private::OnCrostiniChanged::Create(event));
 }
 
 void EventRouter::DisplayDriveConfirmDialog(
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h
index d788239..1d07ca27 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -225,7 +225,7 @@
       extensions::api::file_manager_private::CrostiniEvent& event,
       extensions::api::file_manager_private::CrostiniEventType event_type,
       const std::string& vm_name,
-      const std::string& extension_id,
+      const url::Origin& origin,
       const std::string& mount_name,
       const std::string& file_system_name,
       const std::string& full_path);
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc
index 5cf79de..7dea1e3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router_unittest.cc
@@ -4,28 +4,54 @@
 
 #include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
 #include "base/values.h"
+#include "extensions/common/extension.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
 
 namespace file_manager {
 
 TEST(EventRouterTest, PopulateCrostiniEvent) {
-  extensions::api::file_manager_private::CrostiniEvent event;
+  extensions::api::file_manager_private::CrostiniEvent ext_event;
+  url::Origin ext_origin = url::Origin::Create(
+      extensions::Extension::GetBaseURLFromExtensionId("extensionid"));
   EventRouter::PopulateCrostiniEvent(
-      event, extensions::api::file_manager_private::CROSTINI_EVENT_TYPE_UNSHARE,
-      "vmname", "extensionid", "mountname", "filesystemname", "/full/path");
+      ext_event,
+      extensions::api::file_manager_private::CROSTINI_EVENT_TYPE_UNSHARE,
+      "vmname", ext_origin, "mountname", "filesystemname", "/full/path");
 
-  EXPECT_EQ(event.event_type,
+  EXPECT_EQ(ext_event.event_type,
             extensions::api::file_manager_private::CROSTINI_EVENT_TYPE_UNSHARE);
-  EXPECT_EQ(event.vm_name, "vmname");
-  EXPECT_EQ(event.entries.size(), 1u);
-  base::DictionaryValue props;
-  props.SetString(
+  EXPECT_EQ(ext_event.vm_name, "vmname");
+  EXPECT_EQ(ext_event.entries.size(), 1u);
+  base::DictionaryValue ext_props;
+  ext_props.SetString(
       "fileSystemRoot",
       "filesystem:chrome-extension://extensionid/external/mountname/");
-  props.SetString("fileSystemName", "filesystemname");
-  props.SetString("fileFullPath", "/full/path");
-  props.SetBoolean("fileIsDirectory", true);
-  EXPECT_EQ(event.entries[0].additional_properties, props);
+  ext_props.SetString("fileSystemName", "filesystemname");
+  ext_props.SetString("fileFullPath", "/full/path");
+  ext_props.SetBoolean("fileIsDirectory", true);
+  EXPECT_EQ(ext_event.entries[0].additional_properties, ext_props);
+
+  extensions::api::file_manager_private::CrostiniEvent swa_event;
+  url::Origin swa_origin = url::Origin::Create(
+      GURL("chrome://file-manager/this-part-should-not-be-in?the=event"));
+  EventRouter::PopulateCrostiniEvent(
+      swa_event,
+      extensions::api::file_manager_private::CROSTINI_EVENT_TYPE_SHARE,
+      "vmname", swa_origin, "mountname", "filesystemname", "/full/path");
+
+  EXPECT_EQ(swa_event.event_type,
+            extensions::api::file_manager_private::CROSTINI_EVENT_TYPE_SHARE);
+  EXPECT_EQ(swa_event.vm_name, "vmname");
+  EXPECT_EQ(swa_event.entries.size(), 1u);
+  base::DictionaryValue swa_props;
+  swa_props.SetString("fileSystemRoot",
+                      "filesystem:chrome://file-manager/external/mountname/");
+  swa_props.SetString("fileSystemName", "filesystemname");
+  swa_props.SetString("fileFullPath", "/full/path");
+  swa_props.SetBoolean("fileIsDirectory", true);
+  EXPECT_EQ(swa_event.entries[0].additional_properties, swa_props);
 }
 
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
index 116003e6..c1cd46d 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api_unittest.cc
@@ -144,8 +144,7 @@
     fake_chrome_user_manager_ = new ash::FakeChromeUserManager();
     scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
         std::unique_ptr<ash::FakeChromeUserManager>(fake_chrome_user_manager_));
-    mock_login_display_host_ =
-        std::make_unique<chromeos::MockLoginDisplayHost>();
+    mock_login_display_host_ = std::make_unique<ash::MockLoginDisplayHost>();
     mock_existing_user_controller_ =
         std::make_unique<MockExistingUserController>();
     // Set |LOGIN_PRIMARY| as the default state.
@@ -190,7 +189,7 @@
 
   ash::FakeChromeUserManager* fake_chrome_user_manager_;
   std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
-  std::unique_ptr<chromeos::MockLoginDisplayHost> mock_login_display_host_;
+  std::unique_ptr<ash::MockLoginDisplayHost> mock_login_display_host_;
   std::unique_ptr<MockExistingUserController> mock_existing_user_controller_;
   // Sets up the global |SessionManager| instance.
   session_manager::SessionManager session_manager_;
diff --git a/chrome/browser/chromeos/full_restore/arc_ghost_window_shell_surface.cc b/chrome/browser/chromeos/full_restore/arc_ghost_window_shell_surface.cc
index fdd52bd0..97d61484f45 100644
--- a/chrome/browser/chromeos/full_restore/arc_ghost_window_shell_surface.cc
+++ b/chrome/browser/chromeos/full_restore/arc_ghost_window_shell_surface.cc
@@ -122,8 +122,9 @@
 
 void ArcGhostWindowShellSurface::InitContentOverlay(const std::string& app_id,
                                                     uint32_t theme_color) {
-  exo::ShellSurfaceBase::OverlayParams overlay_params(
-      std::make_unique<ArcGhostWindowView>(kDiameter, app_id, theme_color));
+  auto view = std::make_unique<ArcGhostWindowView>(kDiameter, theme_color);
+  view->LoadIcon(app_id);
+  exo::ShellSurfaceBase::OverlayParams overlay_params(std::move(view));
   overlay_params.translucent = true;
   overlay_params.overlaps_frame = false;
   AddOverlay(std::move(overlay_params));
diff --git a/chrome/browser/chromeos/full_restore/arc_ghost_window_view.cc b/chrome/browser/chromeos/full_restore/arc_ghost_window_view.cc
index 9bcbbf4..9464e1b 100644
--- a/chrome/browser/chromeos/full_restore/arc_ghost_window_view.cc
+++ b/chrome/browser/chromeos/full_restore/arc_ghost_window_view.cc
@@ -51,10 +51,8 @@
 namespace full_restore {
 
 ArcGhostWindowView::ArcGhostWindowView(int throbber_diameter,
-                                       const std::string& app_id,
                                        uint32_t theme_color) {
   InitLayout(theme_color, throbber_diameter);
-  LoadIcon(app_id);
 }
 
 ArcGhostWindowView::~ArcGhostWindowView() = default;
@@ -90,12 +88,15 @@
 
   DCHECK(
       apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile));
+
   apps::AppServiceProxyFactory::GetForProfile(profile)->LoadIcon(
       apps::mojom::AppType::kArc, app_id, icon_type,
       ash::SharedAppListConfig::instance().default_grid_icon_dimension(),
       /*allow_placeholder_icon=*/false,
-      base::BindOnce(&ArcGhostWindowView::OnIconLoaded,
-                     weak_ptr_factory_.GetWeakPtr(), icon_type));
+      icon_loaded_cb_for_testing_.is_null()
+          ? base::BindOnce(&ArcGhostWindowView::OnIconLoaded,
+                           weak_ptr_factory_.GetWeakPtr(), icon_type)
+          : std::move(icon_loaded_cb_for_testing_));
 }
 
 void ArcGhostWindowView::OnIconLoaded(apps::mojom::IconType icon_type,
diff --git a/chrome/browser/chromeos/full_restore/arc_ghost_window_view.h b/chrome/browser/chromeos/full_restore/arc_ghost_window_view.h
index 97fddbc..ea94fb3 100644
--- a/chrome/browser/chromeos/full_restore/arc_ghost_window_view.h
+++ b/chrome/browser/chromeos/full_restore/arc_ghost_window_view.h
@@ -22,20 +22,22 @@
 class ArcGhostWindowView : public views::View {
  public:
   explicit ArcGhostWindowView(int throbber_diameter,
-                              const std::string& app_id,
                               uint32_t theme_color);
   ArcGhostWindowView(const ArcGhostWindowView&) = delete;
   ArcGhostWindowView operator=(const ArcGhostWindowView&) = delete;
   ~ArcGhostWindowView() override;
 
+  void LoadIcon(const std::string& app_id);
+
  private:
   void InitLayout(uint32_t theme_color, int diameter);
-
-  void LoadIcon(const std::string& app_id);
   void OnIconLoaded(apps::mojom::IconType icon_type,
                     apps::mojom::IconValuePtr icon_value);
 
+  FRIEND_TEST_ALL_PREFIXES(ArcGhostWindowViewTest, IconLoadTest);
   views::ImageView* icon_view_;
+  base::OnceCallback<void(apps::mojom::IconValuePtr icon_value)>
+      icon_loaded_cb_for_testing_;
 
   base::WeakPtrFactory<ArcGhostWindowView> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/chromeos/full_restore/arc_ghost_window_view_unittest.cc b/chrome/browser/chromeos/full_restore/arc_ghost_window_view_unittest.cc
new file mode 100644
index 0000000..66c4c0b4
--- /dev/null
+++ b/chrome/browser/chromeos/full_restore/arc_ghost_window_view_unittest.cc
@@ -0,0 +1,131 @@
+// 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/chromeos/full_restore/arc_ghost_window_view.h"
+
+#include "base/callback_forward.h"
+#include "base/test/bind.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/login/users/chrome_user_manager.h"
+#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chrome/test/views/chrome_test_views_delegate.h"
+#include "components/services/app_service/public/cpp/app_registry_cache.h"
+#include "components/services/app_service/public/mojom/app_service.mojom.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/test/scoped_views_test_helper.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace chromeos {
+namespace full_restore {
+
+namespace {
+
+constexpr char kTestProfileName[] = "user@gmail.com";
+constexpr char16_t kTestProfileName16[] = u"user@gmail.com";
+
+apps::mojom::AppPtr MakeApp(const char* app_id,
+                            apps::mojom::AppType app_type,
+                            apps::mojom::InstallSource install_source) {
+  apps::mojom::AppPtr app = apps::mojom::App::New();
+  app->app_id = app_id;
+  app->app_type = app_type;
+  app->install_source = install_source;
+  return app;
+}
+
+}  // namespace
+
+class ArcGhostWindowViewTest : public testing::Test {
+ public:
+  ArcGhostWindowViewTest() = default;
+  ArcGhostWindowViewTest(const ArcGhostWindowViewTest&) = delete;
+  ArcGhostWindowViewTest& operator=(const ArcGhostWindowViewTest&) = delete;
+  ~ArcGhostWindowViewTest() override = default;
+
+  void SetUp() override {
+    user_manager_ = new ash::FakeChromeUserManager;
+    user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
+        std::unique_ptr<user_manager::UserManager>(user_manager_));
+
+    profile_manager_ = std::make_unique<TestingProfileManager>(
+        TestingBrowserProcess::GetGlobal());
+    ASSERT_TRUE(profile_manager_->SetUp());
+
+    const user_manager::User* user =
+        user_manager_->AddUser(AccountId::FromUserEmail(kTestProfileName));
+    user_manager_->LoginUser(user->GetAccountId());
+    user_manager_->SwitchActiveUser(user->GetAccountId());
+
+    // Note that user profiles are created after user login in reality.
+    profile_ = profile_manager_->CreateTestingProfile(
+        kTestProfileName, /*prefs=*/{}, kTestProfileName16,
+        /*avatar_id=*/0, /*supervised_user_id=*/{},
+        IdentityTestEnvironmentProfileAdaptor::
+            GetIdentityTestEnvironmentFactories());
+    ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user,
+                                                                 profile_);
+  }
+
+  void InstallApp(const std::string& app_id) {
+    auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_);
+    std::vector<apps::mojom::AppPtr> deltas;
+    apps::AppRegistryCache& cache = proxy->AppRegistryCache();
+    deltas.push_back(MakeApp(app_id.c_str(), apps::mojom::AppType::kArc,
+                             apps::mojom::InstallSource::kUser));
+    cache.OnApps(std::move(deltas), apps::mojom::AppType::kUnknown,
+                 false /* should_notify_initialized */);
+  }
+
+  void CreateView(int throbber_diameter, uint32_t theme_color) {
+    view_ =
+        std::make_unique<ArcGhostWindowView>(throbber_diameter, theme_color);
+  }
+
+  ArcGhostWindowView* view() { return view_.get(); }
+
+ protected:
+  content::BrowserTaskEnvironment task_environment_;
+
+  views::ScopedViewsTestHelper test_helper_{
+      std::make_unique<ChromeTestViewsDelegate<>>()};
+
+ private:
+  std::unique_ptr<ArcGhostWindowView> view_;
+
+  ash::FakeChromeUserManager* user_manager_;  // Not own.
+  std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
+
+  TestingProfile* profile_;
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+};
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+TEST_F(ArcGhostWindowViewTest, IconLoadTest) {
+  const int kDiameter = 24;
+  const uint32_t kThemeColor = SK_ColorWHITE;
+  const std::string kAppId = "test_app";
+  InstallApp(kAppId);
+
+  int count = 0;
+  CreateView(kDiameter, kThemeColor);
+  EXPECT_EQ(count, 0);
+
+  view()->icon_loaded_cb_for_testing_ = base::BindLambdaForTesting(
+      [&count](apps::mojom::IconValuePtr icon_value) { count++; });
+  view()->LoadIcon(kAppId);
+  EXPECT_EQ(count, 1);
+}
+#endif
+
+}  // namespace full_restore
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine.cc b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
index 274557f..59ba6a1d 100644
--- a/chrome/browser/chromeos/input_method/native_input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
@@ -276,7 +276,6 @@
 
     remote_manager_->ConnectToInputMethod(
         new_engine_id, remote_to_engine_.BindNewPipeAndPassReceiver(),
-        receiver_from_engine_.BindNewPipeAndPassRemote(),
         base::BindOnce(&ImeObserver::OnConnected, base::Unretained(this),
                        base::Time::Now(), new_engine_id));
 
@@ -647,7 +646,7 @@
 
 void NativeInputMethodEngine::ImeObserver::FlushForTesting() {
   remote_manager_.FlushForTesting();
-  if (remote_to_engine_.is_bound())
+  if (receiver_from_engine_.is_bound())
     receiver_from_engine_.FlushForTesting();
   if (remote_to_engine_.is_bound())
     remote_to_engine_.FlushForTesting();
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine_unittest.cc b/chrome/browser/chromeos/input_method/native_input_method_engine_unittest.cc
index 9750031..71300c90 100644
--- a/chrome/browser/chromeos/input_method/native_input_method_engine_unittest.cc
+++ b/chrome/browser/chromeos/input_method/native_input_method_engine_unittest.cc
@@ -79,12 +79,8 @@
   void ConnectToInputMethod(
       const std::string& ime_spec,
       mojo::PendingReceiver<ime::mojom::InputChannel> to_engine,
-      mojo::PendingRemote<ime::mojom::InputChannel> from_engine,
       ConnectToInputMethodCallback callback) override {
     receiver_.Bind(std::move(to_engine));
-    if (remote_) {
-      remote_->Bind(std::move(from_engine));
-    }
     std::move(callback).Run(/*bound=*/true);
   }
 
diff --git a/chrome/browser/chromeos/input_method/personal_info_suggester.cc b/chrome/browser/chromeos/input_method/personal_info_suggester.cc
index 203b3888..63a41a9c 100644
--- a/chrome/browser/chromeos/input_method/personal_info_suggester.cc
+++ b/chrome/browser/chromeos/input_method/personal_info_suggester.cc
@@ -114,15 +114,15 @@
 AssistiveType ProposePersonalInfoAssistiveAction(const std::u16string& text) {
   std::string lower_case_utf8_text =
       base::ToLowerASCII(base::UTF16ToUTF8(text));
-  if (!(RE2::FullMatch(lower_case_utf8_text, ".* $"))) {
+  if (!(RE2::PartialMatch(lower_case_utf8_text, " $"))) {
     return AssistiveType::kGenericAction;
   }
 
   if (base::FeatureList::IsEnabled(
           chromeos::features::kAssistPersonalInfoAddress)) {
-    if (RE2::FullMatch(
+    if (RE2::PartialMatch(
             lower_case_utf8_text,
-            base::StringPrintf(".*%s%s%s", kSingleOrPluralSubjectRegex,
+            base::StringPrintf("%s%s%s$", kSingleOrPluralSubjectRegex,
                                kAddressRegex, kTriggersRegex))) {
       return AssistiveType::kPersonalAddress;
     }
@@ -130,37 +130,39 @@
 
   if (base::FeatureList::IsEnabled(
           chromeos::features::kAssistPersonalInfoEmail)) {
-    if (RE2::FullMatch(lower_case_utf8_text,
-                       base::StringPrintf(".*%s%s%s", kSingleSubjectRegex,
-                                          kEmailRegex, kTriggersRegex))) {
+    if (RE2::PartialMatch(lower_case_utf8_text,
+                          base::StringPrintf("%s%s%s$", kSingleSubjectRegex,
+                                             kEmailRegex, kTriggersRegex))) {
       return AssistiveType::kPersonalEmail;
     }
   }
 
   if (base::FeatureList::IsEnabled(
           chromeos::features::kAssistPersonalInfoName)) {
-    if (RE2::FullMatch(lower_case_utf8_text,
-                       base::StringPrintf(".*%s%s%s", kSingleSubjectRegex,
-                                          kNameRegex, kTriggersRegex))) {
+    if (RE2::PartialMatch(lower_case_utf8_text,
+                          base::StringPrintf("%s%s%s$", kSingleSubjectRegex,
+                                             kNameRegex, kTriggersRegex))) {
       return AssistiveType::kPersonalName;
     }
-    if (RE2::FullMatch(lower_case_utf8_text,
-                       base::StringPrintf(".*%s%s%s", kSingleSubjectRegex,
-                                          kFirstNameRegex, kTriggersRegex))) {
+    if (RE2::PartialMatch(
+            lower_case_utf8_text,
+            base::StringPrintf("%s%s%s$", kSingleSubjectRegex, kFirstNameRegex,
+                               kTriggersRegex))) {
       return AssistiveType::kPersonalFirstName;
     }
-    if (RE2::FullMatch(lower_case_utf8_text,
-                       base::StringPrintf(".*%s%s%s", kSingleSubjectRegex,
-                                          kLastNameRegex, kTriggersRegex))) {
+    if (RE2::PartialMatch(lower_case_utf8_text,
+                          base::StringPrintf("%s%s%s$", kSingleSubjectRegex,
+                                             kLastNameRegex, kTriggersRegex))) {
       return AssistiveType::kPersonalLastName;
     }
   }
 
   if (base::FeatureList::IsEnabled(
           chromeos::features::kAssistPersonalInfoPhoneNumber)) {
-    if (RE2::FullMatch(lower_case_utf8_text,
-                       base::StringPrintf(".*%s%s%s", kSingleSubjectRegex,
-                                          kPhoneNumberRegex, kTriggersRegex))) {
+    if (RE2::PartialMatch(
+            lower_case_utf8_text,
+            base::StringPrintf("%s%s%s$", kSingleSubjectRegex,
+                               kPhoneNumberRegex, kTriggersRegex))) {
       return AssistiveType::kPersonalPhoneNumber;
     }
   }
diff --git a/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc b/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc
index 9113d3f2..4561305 100644
--- a/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc
+++ b/chrome/browser/chromeos/input_method/personal_info_suggester_unittest.cc
@@ -193,7 +193,7 @@
   const std::u16string phone_number_ = u"16505678910";
 };
 
-TEST_F(PersonalInfoSuggesterTest, SuggestEmail) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsEmail) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -213,7 +213,42 @@
   suggestion_handler_->VerifySuggestion(email_, 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestEmailWhenFlagIsDisabled) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsEmailWithMultilineText) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitWithFeatures(
+      /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
+      /*disabled_features=*/{});
+
+  profile_->set_profile_name(base::UTF16ToUTF8(email_));
+
+  suggester_->Suggest(u"\nmy email is ", 13, 13);
+  suggestion_handler_->VerifySuggestion(email_, 0);
+  SendKeyboardEvent(ui::DomCode::ESCAPE);
+
+  suggester_->Suggest(u"Hey\nMan\nmy email is ", 20, 20);
+  suggestion_handler_->VerifySuggestion(email_, 0);
+  SendKeyboardEvent(ui::DomCode::ESCAPE);
+}
+
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestWhenPrefixIsntOnLastLine) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitWithFeatures(
+      /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
+      /*disabled_features=*/{});
+
+  profile_->set_profile_name(base::UTF16ToUTF8(email_));
+
+  suggester_->Suggest(u"\nmy email is \n", 14, 14);
+  suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
+
+  suggester_->Suggest(u"\nmy email is \n ", 15, 15);
+  suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
+
+  suggester_->Suggest(u"Hey\nMan\nmy email is \nhey ", 25, 25);
+  suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
+}
+
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestEmailWhenFlagIsDisabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{},
@@ -225,7 +260,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestEmailWhenPrefixDoesNotMatch) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestEmailWhenPrefixDoesNotMatch) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -240,7 +275,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestWhenVirtualKeyboardEnabled) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestWhenVirtualKeyboardEnabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -268,7 +303,7 @@
       std::vector<std::string>{base::UTF16ToUTF8(email_)});
 }
 
-TEST_F(PersonalInfoSuggesterTest, SuggestNames) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsNames) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoName},
@@ -298,7 +333,7 @@
   suggestion_handler_->VerifySuggestion(full_name_, 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, SuggestNamesButInsufficientData) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsNamesButInsufficientData) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoName},
@@ -318,7 +353,7 @@
                                       1);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestNamesWhenFlagIsDisabled) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestNamesWhenFlagIsDisabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{},
@@ -342,7 +377,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestNamesWhenPrefixDoesNotMatch) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestNamesWhenPrefixDoesNotMatch) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -369,7 +404,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, SuggestAddress) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsAddress) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoAddress},
@@ -410,7 +445,7 @@
   suggestion_handler_->VerifySuggestion(address_, 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestAddressWhenFlagIsDisabled) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestAddressWhenFlagIsDisabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{},
@@ -435,7 +470,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestAddressWhenPrefixDoesNotMatch) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestAddressWhenPrefixDoesNotMatch) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoAddress},
@@ -466,7 +501,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, SuggestPhoneNumber) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsPhoneNumber) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoPhoneNumber},
@@ -498,7 +533,7 @@
   suggestion_handler_->VerifySuggestion(phone_number_, 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotSuggestPhoneNumberWhenFlagIsDisabled) {
+TEST_F(PersonalInfoSuggesterTest, DoesntSuggestPhoneNumberWhenFlagIsDisabled) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{},
@@ -516,7 +551,7 @@
 }
 
 TEST_F(PersonalInfoSuggesterTest,
-       DoNotSuggestPhoneNumberWhenPrefixDoesNotMatch) {
+       DoesntSuggestPhoneNumberWhenPrefixDoesNotMatch) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoPhoneNumber},
@@ -541,7 +576,7 @@
   suggestion_handler_->VerifySuggestion(base::EmptyString16(), 0);
 }
 
-TEST_F(PersonalInfoSuggesterTest, AcceptSuggestionWithDownEnter) {
+TEST_F(PersonalInfoSuggesterTest, AcceptsSuggestionWithDownEnter) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -557,7 +592,7 @@
   EXPECT_TRUE(suggestion_handler_->IsSuggestionAccepted());
 }
 
-TEST_F(PersonalInfoSuggesterTest, AcceptSuggestionWithUpEnter) {
+TEST_F(PersonalInfoSuggesterTest, AcceptsSuggestionWithUpEnter) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -576,7 +611,7 @@
   EXPECT_TRUE(suggestion_handler_->IsSuggestionAccepted());
 }
 
-TEST_F(PersonalInfoSuggesterTest, DismissSuggestion) {
+TEST_F(PersonalInfoSuggesterTest, DismissesSuggestion) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoName},
@@ -593,7 +628,7 @@
   EXPECT_FALSE(suggestion_handler_->IsSuggestionAccepted());
 }
 
-TEST_F(PersonalInfoSuggesterTest, SuggestWithConfirmedLength) {
+TEST_F(PersonalInfoSuggesterTest, SuggestsWithConfirmedLength) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoPhoneNumber},
@@ -611,7 +646,7 @@
 }
 
 TEST_F(PersonalInfoSuggesterTest,
-       DoNotAnnounceSpokenFeedbackWhenChromeVoxIsOff) {
+       DoesntAnnounceSpokenFeedbackWhenChromeVoxIsOff) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -631,7 +666,7 @@
   tts_handler_->VerifyAnnouncement("");
 }
 
-TEST_F(PersonalInfoSuggesterTest, AnnounceSpokenFeedbackWhenChromeVoxIsOn) {
+TEST_F(PersonalInfoSuggesterTest, AnnouncesSpokenFeedbackWhenChromeVoxIsOn) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -663,7 +698,7 @@
   tts_handler_->VerifyAnnouncement("Suggestion dismissed.");
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotShowAnnotationAfterMaxAcceptanceCount) {
+TEST_F(PersonalInfoSuggesterTest, DoesntShowAnnotationAfterMaxAcceptanceCount) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -679,7 +714,7 @@
   suggestion_handler_->VerifyShowAnnotation(false);
 }
 
-TEST_F(PersonalInfoSuggesterTest, ShowSettingLink) {
+TEST_F(PersonalInfoSuggesterTest, ShowsSettingLink) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -699,7 +734,7 @@
   suggestion_handler_->VerifyShowSettingLink(false);
 }
 
-TEST_F(PersonalInfoSuggesterTest, DoNotShowSettingLinkAfterAcceptance) {
+TEST_F(PersonalInfoSuggesterTest, DoesntShowSettingLinkAfterAcceptance) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -717,7 +752,7 @@
   suggestion_handler_->VerifyShowSettingLink(false);
 }
 
-TEST_F(PersonalInfoSuggesterTest, ClickSettingsWithDownDownEnter) {
+TEST_F(PersonalInfoSuggesterTest, ClicksSettingsWithDownDownEnter) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -738,7 +773,7 @@
       ui::ime::ButtonId::kSmartInputsSettingLink);
 }
 
-TEST_F(PersonalInfoSuggesterTest, ClickSettingsWithUpEnter) {
+TEST_F(PersonalInfoSuggesterTest, ClicksSettingsWithUpEnter) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -827,7 +862,7 @@
 }
 
 TEST_F(PersonalInfoSuggesterTest,
-       GetSuggestionsReturnsCandidatesWhenAvailable) {
+       GetsSuggestionsReturnsCandidatesWhenAvailable) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
@@ -845,7 +880,7 @@
 }
 
 TEST_F(PersonalInfoSuggesterTest,
-       GetSuggestionsReturnsZeroCandidatesWhenCandidatesUnavailable) {
+       GetsSuggestionsReturnsZeroCandidatesWhenCandidatesUnavailable) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       /*enabled_features=*/{chromeos::features::kAssistPersonalInfoEmail},
diff --git a/chrome/browser/chromeos/policy/device_display_cros_browser_test.cc b/chrome/browser/chromeos/policy/device_display_cros_browser_test.cc
index ebd75d6..f0a6b243 100644
--- a/chrome/browser/chromeos/policy/device_display_cros_browser_test.cc
+++ b/chrome/browser/chromeos/policy/device_display_cros_browser_test.cc
@@ -102,7 +102,7 @@
 
 void DeviceDisplayPolicyCrosBrowserTest::TearDownOnMainThread() {
   // If the login display is still showing, exit gracefully.
-  if (chromeos::LoginDisplayHost::default_host()) {
+  if (ash::LoginDisplayHost::default_host()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(&chrome::AttemptExit));
     RunUntilBrowserProcessQuits();
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 22eab8a..3051b55 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -451,8 +451,7 @@
         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
         content::NotificationService::AllSources()).Wait();
 
-    chromeos::LoginDisplayHost* host =
-        chromeos::LoginDisplayHost::default_host();
+    auto* host = ash::LoginDisplayHost::default_host();
     contents_ = host->GetOobeWebContents();
     ASSERT_TRUE(contents_);
 
@@ -668,8 +667,7 @@
   void StartLogin(const std::string& locale,
                   const std::string& input_method) {
     // Start login into the device-local account.
-    chromeos::LoginDisplayHost* host =
-        chromeos::LoginDisplayHost::default_host();
+    auto* host = ash::LoginDisplayHost::default_host();
     ASSERT_TRUE(host);
     host->StartSignInScreen();
     chromeos::ExistingUserController* controller =
@@ -686,7 +684,7 @@
   void WaitForSessionStart() {
     if (IsSessionStarted())
       return;
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    ash::WizardController::SkipPostLoginScreensForTesting();
     chromeos::test::WaitForPrimaryUserSessionStart();
   }
 
@@ -2648,8 +2646,7 @@
   controller->RemoveLoginStatusConsumer(&login_status_consumer);
 
   // Verify that the Terms of Service screen is being shown.
-  chromeos::WizardController* wizard_controller =
-        chromeos::WizardController::default_controller();
+  auto* wizard_controller = ash::WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
   ASSERT_TRUE(wizard_controller->current_screen());
   EXPECT_EQ(chromeos::TermsOfServiceScreenView::kScreenId.AsId(),
@@ -2758,8 +2755,7 @@
   controller->RemoveLoginStatusConsumer(&login_status_consumer);
 
   // Verify that the Terms of Service screen is being shown.
-  chromeos::WizardController* wizard_controller =
-      chromeos::WizardController::default_controller();
+  auto* wizard_controller = ash::WizardController::default_controller();
   ASSERT_TRUE(wizard_controller);
   ASSERT_TRUE(wizard_controller->current_screen());
   EXPECT_EQ(chromeos::TermsOfServiceScreenView::kScreenId.AsId(),
diff --git a/chrome/browser/chromeos/policy/device_login_screen_policy_browsertest.cc b/chrome/browser/chromeos/policy/device_login_screen_policy_browsertest.cc
index f5554a2..26b4367 100644
--- a/chrome/browser/chromeos/policy/device_login_screen_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_login_screen_policy_browsertest.cc
@@ -234,7 +234,7 @@
   EXPECT_EQ(ash::LoginScreenTestApi::GetUsersCount(), 0);
 
   // Switch to another (Reset) screen.
-  chromeos::LoginDisplayHost::default_host()->StartWizard(
+  ash::LoginDisplayHost::default_host()->StartWizard(
       chromeos::ResetView::kScreenId);
   chromeos::OobeScreenWaiter(chromeos::ResetView::kScreenId).Wait();
 
@@ -251,7 +251,7 @@
   EXPECT_TRUE(ash::LoginScreenTestApi::IsOobeDialogVisible());
   // Oobe screen should not change.
   EXPECT_EQ(
-      chromeos::LoginDisplayHost::default_host()->GetOobeUI()->current_screen(),
+      ash::LoginDisplayHost::default_host()->GetOobeUI()->current_screen(),
       chromeos::ResetView::kScreenId);
 }
 
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.cc b/chrome/browser/chromeos/policy/login_policy_test_base.cc
index bfc2bbc..d9b83c0 100644
--- a/chrome/browser/chromeos/policy/login_policy_test_base.cc
+++ b/chrome/browser/chromeos/policy/login_policy_test_base.cc
@@ -106,14 +106,14 @@
 }
 
 void LoginPolicyTestBase::SkipToLoginScreen() {
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
+  ash::WizardController::SkipPostLoginScreensForTesting();
   OobeBaseTest::WaitForSigninScreen();
 }
 
 void LoginPolicyTestBase::TriggerLogIn(const std::string& user_id,
                                        const std::string& password,
                                        const std::string& services) {
-  chromeos::LoginDisplayHost::default_host()
+  ash::LoginDisplayHost::default_host()
       ->GetOobeUI()
       ->GetView<chromeos::GaiaScreenHandler>()
       ->ShowSigninScreenForTest(user_id, password, services);
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc
index 4ff19ad..683176ea 100644
--- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc
+++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc
@@ -777,7 +777,7 @@
 IN_PROC_BROWSER_TEST_F(MinimumVersionBeforeLoginHost, DeadlineReached) {
   // Checks update required screen is shown at startup if the policy handler is
   // invoked before login display host is created.
-  EXPECT_EQ(chromeos::LoginDisplayHost::default_host(), nullptr);
+  EXPECT_EQ(ash::LoginDisplayHost::default_host(), nullptr);
   EXPECT_TRUE(GetMinimumVersionPolicyHandler());
   EXPECT_TRUE(GetMinimumVersionPolicyHandler()->DeadlineReached());
   ShowLoginWizard(chromeos::OobeScreen::SCREEN_UNKNOWN);
@@ -870,7 +870,7 @@
   ~MinimumVersionPolicyChildUser() override = default;
 
   void LoginChildUser() {
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    ash::WizardController::SkipPostLoginScreensForTesting();
     user_policy_mixin_.RequestPolicyUpdate();
     login_manager_.LoginAsNewChildUser();
     login_manager_.WaitForActiveSession();
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc
index 84a99560..ab767f7 100644
--- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc
+++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_delegate_impl.cc
@@ -70,8 +70,8 @@
 }
 
 void MinimumVersionPolicyHandlerDelegateImpl::ShowUpdateRequiredScreen() {
-  if (chromeos::LoginDisplayHost::default_host()) {
-    chromeos::LoginDisplayHost::default_host()->StartWizard(
+  if (ash::LoginDisplayHost::default_host()) {
+    ash::LoginDisplayHost::default_host()->StartWizard(
         chromeos::UpdateRequiredView::kScreenId);
   }
 }
@@ -82,9 +82,7 @@
 
 void MinimumVersionPolicyHandlerDelegateImpl::
     HideUpdateRequiredScreenIfShown() {
-  using chromeos::WizardController;
-  WizardController* const wizard_controller =
-      WizardController::default_controller();
+  auto* const wizard_controller = ash::WizardController::default_controller();
   if (!wizard_controller)
     return;
   auto* screen = wizard_controller->GetScreen<ash::UpdateRequiredScreen>();
diff --git a/chrome/browser/chromeos/policy/policy_cert_service_factory.cc b/chrome/browser/chromeos/policy/policy_cert_service_factory.cc
index c1fab71..2d9237b 100644
--- a/chrome/browser/chromeos/policy/policy_cert_service_factory.cc
+++ b/chrome/browser/chromeos/policy/policy_cert_service_factory.cc
@@ -67,7 +67,7 @@
     return;
   ListPrefUpdate update(g_browser_process->local_state(),
                         prefs::kUsedPolicyCertificates);
-  update->AppendString(user_email);
+  update->Append(user_email);
 }
 
 // static
@@ -75,7 +75,7 @@
     const std::string& user_email) {
   ListPrefUpdate update(g_browser_process->local_state(),
                         prefs::kUsedPolicyCertificates);
-  update->Remove(base::Value(user_email), nullptr);
+  update->EraseListValue(base::Value(user_email));
 }
 
 // static
diff --git a/chrome/browser/chromeos/policy/policy_certs_browsertest.cc b/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
index 4822e43..9ca3dd4 100644
--- a/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
+++ b/chrome/browser/chromeos/policy/policy_certs_browsertest.cc
@@ -730,9 +730,8 @@
   }
 
   void StartLogin() {
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
-    chromeos::WizardController* const wizard_controller =
-        chromeos::WizardController::default_controller();
+    ash::WizardController::SkipPostLoginScreensForTesting();
+    auto* const wizard_controller = ash::WizardController::default_controller();
     ASSERT_TRUE(wizard_controller);
     wizard_controller->SkipToLoginForTesting();
 
@@ -781,7 +780,7 @@
   }
 
   void TriggerLogIn() {
-    chromeos::LoginDisplayHost::default_host()
+    ash::LoginDisplayHost::default_host()
         ->GetOobeUI()
         ->GetView<chromeos::GaiaScreenHandler>()
         ->ShowSigninScreenForTest(kAccountId, kAccountPassword, kEmptyServices);
diff --git a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
index 9b80424d..b8782a7 100644
--- a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
+++ b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
@@ -308,7 +308,7 @@
   // Start user sign-in. We can't use |LoginPolicyTestBase::LogIn|, because
   // it waits for a user session start unconditionally, which will not happen if
   // chrome requests a restart to set user-session flags.
-  chromeos::WizardController::SkipPostLoginScreensForTesting();
+  ash::WizardController::SkipPostLoginScreensForTesting();
   OobeBaseTest::WaitForSigninScreen();
 
   LoginDisplayHost::default_host()
diff --git a/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc b/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc
index 7501e2b..32236e5 100644
--- a/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc
+++ b/chrome/browser/chromeos/policy/unaffiliated_arc_allowed_browsertest.cc
@@ -56,7 +56,7 @@
 
   void TearDownOnMainThread() override {
     // If the login display is still showing, exit gracefully.
-    if (chromeos::LoginDisplayHost::default_host()) {
+    if (ash::LoginDisplayHost::default_host()) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::BindOnce(&chrome::AttemptExit));
       RunUntilBrowserProcessQuits();
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.cc b/chrome/browser/content_settings/sound_content_setting_observer.cc
index 6955ee7..b6d373f 100644
--- a/chrome/browser/content_settings/sound_content_setting_observer.cc
+++ b/chrome/browser/content_settings/sound_content_setting_observer.cc
@@ -84,7 +84,8 @@
 
 void SoundContentSettingObserver::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  if (navigation_handle->IsInMainFrame() && navigation_handle->HasCommitted() &&
+  if (navigation_handle->IsInPrimaryMainFrame() &&
+      navigation_handle->HasCommitted() &&
       !navigation_handle->IsSameDocument()) {
     MuteOrUnmuteIfNecessary();
     logged_site_muted_ukm_ = false;
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.h b/chrome/browser/content_settings/sound_content_setting_observer.h
index 92b5d76d..0ad7dad 100644
--- a/chrome/browser/content_settings/sound_content_setting_observer.h
+++ b/chrome/browser/content_settings/sound_content_setting_observer.h
@@ -41,6 +41,8 @@
                                const ContentSettingsPattern& secondary_pattern,
                                ContentSettingsType content_type) override;
 
+  bool HasLoggedSiteMutedUkmForTesting() { return logged_site_muted_ukm_; }
+
  private:
   explicit SoundContentSettingObserver(content::WebContents* web_contents);
   friend class content::WebContentsUserData<SoundContentSettingObserver>;
diff --git a/chrome/browser/content_settings/sound_content_setting_observer_browsertest.cc b/chrome/browser/content_settings/sound_content_setting_observer_browsertest.cc
new file mode 100644
index 0000000..8ee88b7a
--- /dev/null
+++ b/chrome/browser/content_settings/sound_content_setting_observer_browsertest.cc
@@ -0,0 +1,115 @@
+// 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/content_settings/sound_content_setting_observer.h"
+
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/prerender_test_util.h"
+#include "content/public/test/test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace {
+
+const char* kMediaTestDataPath = "media/test/data";
+
+// Observes a WebContents and waits until it becomes audible.
+// both indicate that they are audible.
+class TestAudioStartObserver : public content::WebContentsObserver {
+ public:
+  TestAudioStartObserver(content::WebContents* web_contents,
+                         base::OnceClosure quit_closure)
+      : content::WebContentsObserver(web_contents),
+        quit_closure_(std::move(quit_closure)) {
+    DCHECK(!web_contents->IsCurrentlyAudible());
+  }
+  ~TestAudioStartObserver() override = default;
+
+  // WebContentsObserver:
+  void OnAudioStateChanged(bool audible) override {
+    if (quit_closure_)
+      std::move(quit_closure_).Run();
+  }
+
+ private:
+  base::OnceClosure quit_closure_;
+};
+
+}  // namespace
+
+class SoundContentSettingObserverBrowserTest : public InProcessBrowserTest {
+ public:
+  SoundContentSettingObserverBrowserTest()
+      : prerender_helper_(base::BindRepeating(
+            &SoundContentSettingObserverBrowserTest::web_contents,
+            base::Unretained(this))) {}
+  ~SoundContentSettingObserverBrowserTest() override = default;
+
+  content::test::PrerenderTestHelper* prerender_helper() {
+    return &prerender_helper_;
+  }
+
+  content::WebContents* web_contents() {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+
+ private:
+  content::test::PrerenderTestHelper prerender_helper_;
+};
+
+// Tests that the prerending doesn't affect SoundContentSettingObserver status
+// with the main frame.
+IN_PROC_BROWSER_TEST_F(SoundContentSettingObserverBrowserTest,
+                       SoundContentSettingObserverInPrerendering) {
+  // Sets up the embedded test server to serve the test javascript file.
+  embedded_test_server()->ServeFilesFromSourceDirectory(kMediaTestDataPath);
+  net::test_server::EmbeddedTestServerHandle test_server_handle;
+  ASSERT_TRUE(test_server_handle =
+                  embedded_test_server()->StartAndReturnHandle());
+
+  // Configures to check `logged_site_muted_ukm_` in
+  // SoundContentSettingObserver.
+  HostContentSettingsMap* content_settings =
+      HostContentSettingsMapFactory::GetForProfile(browser()->profile());
+  content_settings->SetDefaultContentSetting(ContentSettingsType::SOUND,
+                                             CONTENT_SETTING_BLOCK);
+
+  GURL url = embedded_test_server()->GetURL("/webaudio_oscillator.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  // Start the audio on the current main frame.
+  base::RunLoop run_loop;
+  TestAudioStartObserver audio_start_observer(web_contents(),
+                                              run_loop.QuitClosure());
+  EXPECT_EQ("OK", content::EvalJs(web_contents(), "StartOscillator();",
+                                  content::EXECUTE_SCRIPT_USE_MANUAL_REPLY));
+  run_loop.Run();
+
+  SoundContentSettingObserver* observer =
+      SoundContentSettingObserver::FromWebContents(web_contents());
+  // `logged_site_muted_ukm_` should be set.
+  EXPECT_TRUE(observer->HasLoggedSiteMutedUkmForTesting());
+
+  // Loads a page in the prerender.
+  auto prerender_url = embedded_test_server()->GetURL("/simple.html");
+  int host_id = prerender_helper()->AddPrerender(prerender_url);
+  content::test::PrerenderHostObserver host_observer(*web_contents(), host_id);
+  // The prerendering should not affect the current status.
+  EXPECT_TRUE(observer->HasLoggedSiteMutedUkmForTesting());
+
+  // Activates the page from the prerendering.
+  ui_test_utils::NavigateToURL(browser(), prerender_url);
+  // Makes sure that the page is activated from the prerendering.
+  EXPECT_TRUE(host_observer.was_activated());
+  // It should be reset.
+  EXPECT_FALSE(observer->HasLoggedSiteMutedUkmForTesting());
+}
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
index be8b573..12909e6 100644
--- a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
@@ -208,7 +208,7 @@
 
   if (primary_account_only || !primary_account_info.gaia.empty()) {
     // The extension is using the primary account.
-    OnReceivedExtensionAccountInfo(&primary_account_info);
+    OnReceivedExtensionAccountInfo(primary_account_info);
   } else {
     // No primary account, try the first account in cookies.
     DCHECK_EQ(AccountListeningMode::kNotListening, account_listening_mode_);
@@ -226,15 +226,14 @@
 
 void IdentityGetAuthTokenFunction::FetchExtensionAccountInfo(
     const std::string& gaia_id) {
-  OnReceivedExtensionAccountInfo(base::OptionalOrNullptr(
+  OnReceivedExtensionAccountInfo(
       IdentityManagerFactory::GetForProfile(GetProfile())
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
-              gaia_id)));
+          ->FindExtendedAccountInfoByGaiaId(gaia_id));
 }
 
 void IdentityGetAuthTokenFunction::OnReceivedExtensionAccountInfo(
-    const CoreAccountInfo* account_info) {
-  token_key_.account_info = account_info ? *account_info : CoreAccountInfo();
+    const CoreAccountInfo& account_info) {
+  token_key_.account_info = account_info;
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   policy::BrowserPolicyConnectorChromeOS* connector =
@@ -256,9 +255,9 @@
   }
 #endif
 
-  if (!account_info ||
+  if (account_info.IsEmpty() ||
       !IdentityManagerFactory::GetForProfile(GetProfile())
-           ->HasAccountWithRefreshToken(account_info->account_id)) {
+           ->HasAccountWithRefreshToken(account_info.account_id)) {
     if (!ShouldStartSigninFlow()) {
       IdentityGetAuthTokenError error(
           IsBrowserSigninAllowed(GetProfile())
@@ -292,12 +291,11 @@
     // If the account is in auth error, it won't be in the identity manager.
     // Save the email now to use as email hint for the login prompt.
     email_for_default_web_account_ = account.email;
-    OnReceivedExtensionAccountInfo(base::OptionalOrNullptr(
+    OnReceivedExtensionAccountInfo(
         IdentityManagerFactory::GetForProfile(GetProfile())
-            ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
-                account.gaia_id)));
+            ->FindExtendedAccountInfoByGaiaId(account.gaia_id));
   } else {
-    OnReceivedExtensionAccountInfo(nullptr);
+    OnReceivedExtensionAccountInfo(CoreAccountInfo());
   }
 }
 
@@ -719,10 +717,9 @@
   DCHECK(!consent_result.empty());
   remote_consent_approved_ = true;
 
-  absl::optional<AccountInfo> account =
-      IdentityManagerFactory::GetForProfile(GetProfile())
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(gaia_id);
-  if (!account) {
+  AccountInfo account = IdentityManagerFactory::GetForProfile(GetProfile())
+                            ->FindExtendedAccountInfoByGaiaId(gaia_id);
+  if (account.IsEmpty()) {
     CompleteMintTokenFlow();
     CompleteFunctionWithError(IdentityGetAuthTokenError(
         IdentityGetAuthTokenError::State::kRemoteConsentUserNotSignedIn));
@@ -733,7 +730,7 @@
     CoreAccountId primary_account_id =
         IdentityManagerFactory::GetForProfile(GetProfile())
             ->GetPrimaryAccountId(signin::ConsentLevel::kSync);
-    if (primary_account_id != account->account_id) {
+    if (primary_account_id != account.account_id) {
       CompleteMintTokenFlow();
       CompleteFunctionWithError(IdentityGetAuthTokenError(
           IdentityGetAuthTokenError::State::kRemoteConsentUserNonPrimary));
@@ -747,7 +744,7 @@
   // It's important to update the cache before calling CompleteMintTokenFlow()
   // as this call may start a new request synchronously and query the cache.
   ExtensionTokenKey new_token_key(token_key_);
-  new_token_key.account_info = account.value();
+  new_token_key.account_info = account;
   id_api->token_cache()->SetToken(
       new_token_key,
       IdentityTokenCacheValue::CreateRemoteConsentApproved(consent_result));
@@ -888,12 +885,11 @@
 }
 
 void IdentityGetAuthTokenFunction::ShowExtensionLoginPrompt() {
-  absl::optional<AccountInfo> account =
-      IdentityManagerFactory::GetForProfile(GetProfile())
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              token_key_.account_info.account_id);
+  AccountInfo account = IdentityManagerFactory::GetForProfile(GetProfile())
+                            ->FindExtendedAccountInfoByAccountId(
+                                token_key_.account_info.account_id);
   std::string email_hint =
-      account ? account->email : email_for_default_web_account_;
+      account.IsEmpty() ? email_for_default_web_account_ : account.email;
 
   LoginUIService* login_ui_service =
       LoginUIServiceFactory::GetForProfile(GetProfile());
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
index 1834786..dc92593 100644
--- a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
@@ -143,12 +143,12 @@
   // instance, or empty if this was not in the parameters.
   void GetAuthTokenForPrimaryAccount(const std::string& extension_gaia_id);
 
-  // Wrapper to FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId() to
-  // avoid a synchronous call to IdentityManager in RunAsync().
+  // Wrapper to FindExtendedAccountInfoByGaiaId() to avoid a synchronous call to
+  // IdentityManager in RunAsync().
   void FetchExtensionAccountInfo(const std::string& gaia_id);
 
   // Called when the AccountInfo that this instance should use is available.
-  void OnReceivedExtensionAccountInfo(const CoreAccountInfo* account_info);
+  void OnReceivedExtensionAccountInfo(const CoreAccountInfo& account_info);
 
   // signin::IdentityManager::Observer implementation:
   void OnRefreshTokenUpdatedForAccount(
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index 10efc21..2cd4802 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -453,15 +453,6 @@
 
   // Set app-specific data.
   if (extension_sync_data.is_app()) {
-    if (extension_sync_data.app_launch_ordinal().IsValid() &&
-        extension_sync_data.page_ordinal().IsValid()) {
-      AppSorting* app_sorting = system_->app_sorting();
-      app_sorting->SetAppLaunchOrdinal(
-          id,
-          extension_sync_data.app_launch_ordinal());
-      app_sorting->SetPageOrdinal(id, extension_sync_data.page_ordinal());
-    }
-
     // The corresponding validation of this value during ExtensionSyncData
     // population is in ExtensionSyncData::ToAppSpecifics.
     if (extension_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST &&
@@ -475,6 +466,14 @@
       // WebAppSyncBridge.
       return;
     }
+
+    if (extension_sync_data.app_launch_ordinal().IsValid() &&
+        extension_sync_data.page_ordinal().IsValid()) {
+      AppSorting* app_sorting = system_->app_sorting();
+      app_sorting->SetAppLaunchOrdinal(
+          id, extension_sync_data.app_launch_ordinal());
+      app_sorting->SetPageOrdinal(id, extension_sync_data.page_ordinal());
+    }
   }
 
   // Finally, trigger installation/update as required.
diff --git a/chrome/browser/media/chromeos_login_media_access_handler.cc b/chrome/browser/media/chromeos_login_media_access_handler.cc
index 17ce336..0998ab6 100644
--- a/chrome/browser/media/chromeos_login_media_access_handler.cc
+++ b/chrome/browser/media/chromeos_login_media_access_handler.cc
@@ -27,7 +27,7 @@
     const extensions::Extension* extension) {
   if (!web_contents)
     return false;
-  chromeos::LoginDisplayHost* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = ash::LoginDisplayHost::default_host();
   return host && web_contents == host->GetOobeWebContents();
 }
 
diff --git a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
index 2242bb3..7b5b130 100644
--- a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
+++ b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
@@ -303,8 +303,7 @@
 
   void StartPublicSessionLogin() {
     // Start login into the device-local account.
-    chromeos::LoginDisplayHost* host =
-        chromeos::LoginDisplayHost::default_host();
+    auto* host = ash::LoginDisplayHost::default_host();
     ASSERT_TRUE(host);
     host->StartSignInScreen();
     chromeos::ExistingUserController* controller =
@@ -321,7 +320,7 @@
   void WaitForSessionStart() {
     if (IsSessionStarted())
       return;
-    chromeos::WizardController::SkipPostLoginScreensForTesting();
+    ash::WizardController::SkipPostLoginScreensForTesting();
     chromeos::test::WaitForPrimaryUserSessionStart();
   }
 
diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc
index 67a71404..6f304559 100644
--- a/chrome/browser/pdf/pdf_extension_util.cc
+++ b/chrome/browser/pdf/pdf_extension_util.cc
@@ -198,7 +198,7 @@
   bool annotations_enabled = false;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // For Chrome OS, enable printing only if we are not at OOBE.
-  printing_enabled = !chromeos::LoginDisplayHost::default_host();
+  printing_enabled = !ash::LoginDisplayHost::default_host();
   annotations_enabled = enable_annotations;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
   dict->SetKey("printingEnabled", base::Value(printing_enabled));
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index a4441c7..499d5d8c9 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -206,10 +206,11 @@
     "chromeos/lazy_load.js",
     "chromeos/google_assistant_page/google_assistant_browser_proxy.js",
     "chromeos/guest_os/guest_os_browser_proxy.js",
+    "chromeos/os_languages_page/input_method_settings.js",
+    "chromeos/os_printing_page/cups_printers_entry_list_behavior.js",
     "chromeos/os_printing_page/cups_printer_dialog_util.js",
     "chromeos/os_printing_page/cups_printer_types.js",
     "chromeos/os_printing_page/cups_printers_browser_proxy.js",
-    "chromeos/os_printing_page/cups_printers_entry_list_behavior.js",
     "chromeos/os_printing_page/cups_printers_entry_manager.js",
     "chromeos/os_reset_page/os_reset_browser_proxy.js",
     "chromeos/os_settings.js",
diff --git a/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/BUILD.gn b/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/BUILD.gn
index c90b1ea..590c06d 100644
--- a/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/BUILD.gn
@@ -14,8 +14,10 @@
 
 js_library("keyboard_shortcut_banner") {
   deps = [
+    "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
+    "//ui/webui/resources/js:i18n_behavior.m",
   ]
 }
 
diff --git a/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/keyboard_shortcut_banner.js b/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/keyboard_shortcut_banner.js
index d79d756c..a47179b 100644
--- a/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/keyboard_shortcut_banner.js
+++ b/chrome/browser/resources/settings/chromeos/keyboard_shortcut_banner/keyboard_shortcut_banner.js
@@ -14,9 +14,20 @@
  */
 import '//resources/cr_elements/cr_button/cr_button.m.js';
 
-import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
+import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
 
-class KeyboardShortcutBanner extends PolymerElement {
+/**
+ * @constructor
+ * @extends {PolymerElement}
+ * @implements {I18nBehaviorInterface}
+ */
+const KeyboardShortcutBannerBase =
+    mixinBehaviors([I18nBehavior], PolymerElement);
+
+/** @polymer */
+class KeyboardShortcutBanner extends KeyboardShortcutBannerBase {
   static get is() {
     return 'keyboard-shortcut-banner';
   }
@@ -38,8 +49,19 @@
     };
   }
 
+  /** @override */
+  connectedCallback() {
+    super.connectedCallback();
+    IronA11yAnnouncer.requestAvailability();
+  }
+
   /** @private */
   onDismissClick_() {
+    this.dispatchEvent(new CustomEvent('iron-announce', {
+      bubbles: true,
+      composed: true,
+      detail: {text: this.i18n('shortcutBannerDismissed')}
+    }));
     this.dispatchEvent(new CustomEvent('dismiss'));
   }
 
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
index 370c5923..1c4f940d 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -61,10 +61,17 @@
 
 js_library("input_method_util.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.m.js" ]
-  deps = [ "//ui/webui/resources/js:cr.m" ]
+  deps = [
+    ":input_method_settings",
+    "//ui/webui/resources/js:cr.m",
+  ]
   extra_deps = [ ":modulize" ]
 }
 
+js_library("input_method_settings") {
+  deps = [ "//ui/webui/resources/js:cr.m" ]
+}
+
 js_library("input_method_options_page.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.m.js" ]
   deps = [
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
index 9a9cd78..8606bc8 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
@@ -138,11 +138,11 @@
    */
   getPrefsPrefix_() {
     if (this.engineId_ ===
-        settings.input_method_util.InputToolCode.PINYIN_CHINESE_SIMPLIFIED) {
+        settings.input_method_util.EngineId.PINYIN_CHINESE_SIMPLIFIED) {
       return 'pinyin';
     } else if (
         this.engineId_ ===
-        settings.input_method_util.InputToolCode.ZHUYIN_CHINESE_TRADITIONAL) {
+        settings.input_method_util.EngineId.ZHUYIN_CHINESE_TRADITIONAL) {
       return 'zhuyin';
     }
     return this.engineId_;
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_settings.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_settings.js
new file mode 100644
index 0000000..524cc872
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_settings.js
@@ -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.
+
+/**
+ * Types of controller
+ * @enum {number}
+ */
+export const SettingsTypes = {
+  LATIN_SETTINGS: 0,
+};
+/**
+ * The string keys are the input methods ids.
+ * @type {Object<string,!Array<!SettingsTypes>>}
+ */
+export const inputMethodSettings = {
+  'xkb:us::eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:intl:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:intl_pc:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:intl:nld': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:intl_pc:nld': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:intl:por': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:intl_pc:por': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:altgr-intl:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:dvorak:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:dvp:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:colemak:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:workman:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:us:workman-intl:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:be::nld': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:fr::fra': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:fr:bepo:fra': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:be::fra': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:ca::fra': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:ch:fr:fra': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:ca:multix:fra': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:de::ger': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:de:neo:ger': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:be::ger': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:ch::ger': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:br::por': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:ca:eng:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:es::spa': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:dk::dan': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:latam::spa': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:gb:extd:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:gb:dvorak:eng': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:fi::fin': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:it::ita': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:no::nob': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:pl::pol': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:pt::por': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:se::swe': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:tr::tur': [SettingsTypes.LATIN_SETTINGS],
+  'xkb:tr:f:tur': [SettingsTypes.LATIN_SETTINGS],
+};
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
index d524164..2e213a4 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 // #import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
+import {inputMethodSettings, SettingsTypes} from './input_method_settings.js';
 
 /**
  * @fileoverview constants related to input method options.
@@ -16,7 +17,7 @@
       '_comp_ime_jkghodnilhceideoidjikpgommlajknk';
 
   /**
-   * All possible keyboard layouts.
+   * All possible keyboard layouts. Should match Google3.
    *
    * @enum {string}
    */
@@ -42,7 +43,7 @@
   };
 
   /**
-   * All possible options on options pages.
+   * All possible options on options pages. Should match Gooogle3.
    *
    * @enum {string}
    */
@@ -142,17 +143,33 @@
   };
 
   /**
-   * Enumeration for input tool codes.
+   * Enumeration for engine IDs.
    *
    * @enum {string}
    */
-  /* #export */ const InputToolCode = {
+  /* #export */ const EngineId = {
     PINYIN_CHINESE_SIMPLIFIED: 'zh-t-i0-pinyin',
     ZHUYIN_CHINESE_TRADITIONAL: 'zh-hant-t-i0-und',
-    XKB_US_ENG: 'xkb:us::eng',
-    XKB_UK_ENG: 'xkb:gb:extd:eng',
   };
 
+  const Settings = {
+    [SettingsTypes.LATIN_SETTINGS]: {
+      physicalKeyboard: [
+        OptionType.PHYSICAL_KEYBOARD_AUTO_CORRECTION_LEVEL,
+        OptionType.PHYSICAL_KEYBOARD_ENABLE_CAPITALIZATION,
+        OptionType.ENABLE_PREDICTION
+      ],
+      virtualKeyboard: [
+        OptionType.ENABLE_SOUND_ON_KEYPRESS,
+        OptionType.VIRTUAL_KEYBOARD_AUTO_CORRECTION_LEVEL,
+        OptionType.VIRTUAL_KEYBOARD_ENABLE_CAPITALIZATION,
+        OptionType.ENABLE_DOUBLE_SPACE_PERIOD, OptionType.ENABLE_GESTURE_TYPING,
+        OptionType.EDIT_USER_DICT
+      ],
+      basic: [],
+      advanced: [],
+    }
+  };
   /**
    * @param {string} id Input method ID.
    * @return {string} The corresponding engind ID of the input method.
@@ -171,9 +188,9 @@
       return false;
     }
     const engineId = getFirstPartyInputMethodEngineId(id);
-    return engineId === InputToolCode.PINYIN_CHINESE_SIMPLIFIED ||
-        engineId === InputToolCode.XKB_US_ENG ||
-        engineId === InputToolCode.XKB_UK_ENG;
+
+    return engineId === EngineId.PINYIN_CHINESE_SIMPLIFIED ||
+        (!!inputMethodSettings[engineId]);
   }
 
   /**
@@ -186,7 +203,7 @@
   /* #export */ function generateOptions(engineId) {
     const options =
         {basic: [], advanced: [], physicalKeyboard: [], virtualKeyboard: []};
-    if (engineId === InputToolCode.PINYIN_CHINESE_SIMPLIFIED) {
+    if (engineId === EngineId.PINYIN_CHINESE_SIMPLIFIED) {
       options.basic.push(
           OptionType.XKB_LAYOUT, OptionType.PINYIN_ENABLE_UPPER_PAGING,
           OptionType.PINYIN_ENABLE_LOWER_PAGING,
@@ -195,31 +212,16 @@
           OptionType.PINYIN_CHINESE_PUNCTUATION);
       options.advanced.push(
           OptionType.PINYIN_ENABLE_FUZZY, OptionType.EDIT_USER_DICT);
-    }
-    if (engineId === InputToolCode.XKB_US_ENG) {
-      options.physicalKeyboard.push(
-          OptionType.PHYSICAL_KEYBOARD_AUTO_CORRECTION_LEVEL,
-          OptionType.PHYSICAL_KEYBOARD_ENABLE_CAPITALIZATION,
-          OptionType.ENABLE_PREDICTION);
-      options.virtualKeyboard.push(
-          OptionType.ENABLE_SOUND_ON_KEYPRESS,
-          OptionType.VIRTUAL_KEYBOARD_AUTO_CORRECTION_LEVEL,
-          OptionType.VIRTUAL_KEYBOARD_ENABLE_CAPITALIZATION,
-          OptionType.ENABLE_DOUBLE_SPACE_PERIOD,
-          OptionType.ENABLE_GESTURE_TYPING, OptionType.EDIT_USER_DICT);
-    }
-
-    if (engineId === InputToolCode.XKB_UK_ENG) {
-      options.physicalKeyboard.push(
-          OptionType.PHYSICAL_KEYBOARD_AUTO_CORRECTION_LEVEL,
-          OptionType.PHYSICAL_KEYBOARD_ENABLE_CAPITALIZATION,
-          OptionType.ENABLE_PREDICTION);
-      options.virtualKeyboard.push(
-          OptionType.ENABLE_SOUND_ON_KEYPRESS,
-          OptionType.VIRTUAL_KEYBOARD_AUTO_CORRECTION_LEVEL,
-          OptionType.VIRTUAL_KEYBOARD_ENABLE_CAPITALIZATION,
-          OptionType.ENABLE_DOUBLE_SPACE_PERIOD,
-          OptionType.ENABLE_GESTURE_TYPING, OptionType.EDIT_USER_DICT);
+    } else {
+      if (inputMethodSettings[engineId]) {
+        inputMethodSettings[engineId].forEach((settingType) => {
+          const settings = Settings[settingType];
+          options.basic.push(...settings.basic);
+          options.advanced.push(...settings.advanced);
+          options.physicalKeyboard.push(...settings.physicalKeyboard);
+          options.virtualKeyboard.push(...settings.virtualKeyboard);
+        });
+      }
     }
 
     return [
@@ -380,7 +382,7 @@
     OptionType,
     OPTION_DEFAULT,
     UiType,
-    InputToolCode,
+    EngineId,
     getFirstPartyInputMethodEngineId,
     hasOptionsPageInSettings,
     generateOptions,
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index 91ef426..b32b754 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -82,7 +82,7 @@
                                    "settings.input_method_util.getOptionUiType|getOptionUiType",
                                    "settings.input_method_util.getOptionUrl|getOptionUrl",
                                    "settings.input_method_util.hasOptionsPageInSettings|hasOptionsPageInSettings",
-                                   "settings.input_method_util.InputToolCode|InputToolCode",
+                                   "settings.input_method_util.EngineId|EngineId",
                                    "settings.input_method_util.isNumberValue|isNumberValue",
                                    "settings.input_method_util.OPTION_DEFAULT|OPTION_DEFAULT",
                                    "settings.input_method_util.OptionType|OptionType",
@@ -224,7 +224,7 @@
                              "chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page_browser_proxy.html|OsA11yPageBrowserProxyImpl,OsA11yPageBrowserProxy",
                              "chrome/browser/resources/settings/chromeos/os_a11y_page/tts_subpage_browser_proxy.html|TtsSubpageBrowserProxy,TtsSubpageBrowserProxyImpl",
                              "chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_action_assignment_dialog.html|getLabelForAssignment",
-                             "chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.html|generateOptions,getFirstPartyInputMethodEngineId,getOptionLabelName,getOptionMenuItems,getOptionUiType,getOptionUrl,hasOptionsPageInSettings,InputToolCode,isNumberValue,OPTION_DEFAULT,OptionType,UiType",
+                             "chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.html|generateOptions,getFirstPartyInputMethodEngineId,getOptionLabelName,getOptionMenuItems,getOptionUiType,getOptionUrl,hasOptionsPageInSettings,EngineId,isNumberValue,OPTION_DEFAULT,OptionType,UiType",
                              "chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.html|LanguagesMetricsProxy, LanguagesMetricsProxyImpl, LanguagesPageInteraction",
                              "chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.html|FingerprintInfo,FingerprintBrowserProxy,FingerprintResultType,FingerprintBrowserProxyImpl,FingerprintAttempt,FingerprintScan",
                              "chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.html|LockScreenUnlockType,LockStateBehaviorImpl,LockStateBehavior",
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index f7b60adb..9cf039c1 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -1584,9 +1584,7 @@
   if (account_iterator == signed_in_accounts.end())
     return AccountInfo();
 
-  return identity_manager
-      ->FindExtendedAccountInfoForAccountWithRefreshToken(*account_iterator)
-      .value_or(AccountInfo());
+  return identity_manager->FindExtendedAccountInfo(*account_iterator);
 }
 
 bool ChromePasswordProtectionService::IsInExcludedCountry() {
@@ -1659,11 +1657,8 @@
   if (!identity_manager)
     return AccountInfo();
 
-  absl::optional<AccountInfo> primary_account_info =
-      identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
-          identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync));
-
-  return primary_account_info.value_or(AccountInfo());
+  return identity_manager->FindExtendedAccountInfo(
+      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync));
 }
 
 ChromePasswordProtectionService::ChromePasswordProtectionService(
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index 201306c..5e4a406 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -592,14 +592,14 @@
     bool is_off_the_record,
     int incognito_availibility,
     AccountConsistencyMethod account_consistency,
-    std::string gaia_id,
+    const std::string& gaia_id,
     const absl::optional<bool>& is_child_account,
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     bool is_secondary_account_addition_allowed,
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
     bool is_sync_enabled,
-    std::string signin_scoped_device_id,
+    const std::string& signin_scoped_device_id,
 #endif
     content_settings::CookieSettings* cookie_settings) {
   if (is_off_the_record)
diff --git a/chrome/browser/signin/chrome_signin_helper.h b/chrome/browser/signin/chrome_signin_helper.h
index 4173297..0ce6b13c 100644
--- a/chrome/browser/signin/chrome_signin_helper.h
+++ b/chrome/browser/signin/chrome_signin_helper.h
@@ -97,14 +97,14 @@
     bool is_off_the_record,
     int incognito_availibility,
     AccountConsistencyMethod account_consistency,
-    std::string gaia_id,
+    const std::string& gaia_id,
     const absl::optional<bool>& is_child_account,
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     bool is_secondary_account_addition_allowed,
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
     bool is_sync_enabled,
-    std::string signin_scoped_device_id,
+    const std::string& signin_scoped_device_id,
 #endif
     content_settings::CookieSettings* cookie_settings);
 
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java
index a8fc67cd..16e2f74 100644
--- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java
+++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java
@@ -157,9 +157,8 @@
         doAnswer(AdditionalAnswers.answerVoid(Runnable::run))
                 .when(mAccountTrackerServiceMock)
                 .seedAccountsIfNeeded(any(Runnable.class));
-        when(mIdentityManagerNativeMock
-                        .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                                anyLong(), eq(ACCOUNT_EMAIL)))
+        when(mIdentityManagerNativeMock.findExtendedAccountInfoByEmailAddress(
+                     anyLong(), eq(ACCOUNT_EMAIL)))
                 .thenReturn(mAccountInfoWithAvatar);
         mAccountManagerTestRule.addAccount(
                 new ProfileDataSource.ProfileData(ACCOUNT_EMAIL, null, "Full Name", "Given Name"));
@@ -199,9 +198,8 @@
         doAnswer(AdditionalAnswers.answerVoid(Runnable::run))
                 .when(mAccountTrackerServiceMock)
                 .seedAccountsIfNeeded(any(Runnable.class));
-        when(mIdentityManagerNativeMock
-                        .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                                anyLong(), eq(ACCOUNT_EMAIL)))
+        when(mIdentityManagerNativeMock.findExtendedAccountInfoByEmailAddress(
+                     anyLong(), eq(ACCOUNT_EMAIL)))
                 .thenReturn(mAccountInfoWithAvatar);
         mAccountManagerTestRule.addAccount(ACCOUNT_EMAIL);
 
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index f94b9e0d..ad997074 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -103,13 +103,11 @@
   // If we're already signed in, check the account immediately just to be sure.
   // (We might have missed an update before registering as an observer.)
   // "Unconsented" because this class doesn't care about browser sync consent.
-  absl::optional<AccountInfo> primary_account_info =
-      identity_manager_->FindExtendedAccountInfoForAccountWithRefreshToken(
-          identity_manager_->GetPrimaryAccountInfo(
-              signin::ConsentLevel::kSignin));
+  AccountInfo primary_account_info = identity_manager_->FindExtendedAccountInfo(
+      identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin));
 
-  if (primary_account_info.has_value())
-    OnExtendedAccountInfoUpdated(primary_account_info.value());
+  if (!primary_account_info.IsEmpty())
+    OnExtendedAccountInfoUpdated(primary_account_info);
 }
 
 bool ChildAccountService::IsChildAccountStatusKnown() {
@@ -251,11 +249,10 @@
     const signin::PrimaryAccountChangeEvent& event_details) {
   if (event_details.GetEventTypeFor(signin::ConsentLevel::kSignin) ==
       signin::PrimaryAccountChangeEvent::Type::kSet) {
-    auto account_info =
-        identity_manager_->FindExtendedAccountInfoForAccountWithRefreshToken(
-            event_details.GetCurrentState().primary_account);
-    if (account_info.has_value()) {
-      OnExtendedAccountInfoUpdated(account_info.value());
+    AccountInfo account_info = identity_manager_->FindExtendedAccountInfo(
+        event_details.GetCurrentState().primary_account);
+    if (!account_info.IsEmpty()) {
+      OnExtendedAccountInfoUpdated(account_info);
     }
     // Otherwise OnExtendedAccountInfoUpdated will be notified once
     // the account info is available.
diff --git a/chrome/browser/sync/test/integration/secondary_account_helper.cc b/chrome/browser/sync/test/integration/secondary_account_helper.cc
index 2a8dbfba..fa7f731 100644
--- a/chrome/browser/sync/test/integration/secondary_account_helper.cc
+++ b/chrome/browser/sync/test/integration/secondary_account_helper.cc
@@ -90,13 +90,11 @@
 void MakeAccountPrimary(Profile* profile, const std::string& email) {
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
-  absl::optional<AccountInfo> maybe_account =
-      identity_manager
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-              email);
-  DCHECK(maybe_account.has_value());
+  AccountInfo account =
+      identity_manager->FindExtendedAccountInfoByEmailAddress(email);
+  DCHECK(!account.IsEmpty());
   auto* primary_account_mutator = identity_manager->GetPrimaryAccountMutator();
-  primary_account_mutator->SetPrimaryAccount(maybe_account->account_id,
+  primary_account_mutator->SetPrimaryAccount(account.account_id,
                                              signin::ConsentLevel::kSync);
 }
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 8683625..fe11d991 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2928,6 +2928,7 @@
       "views/autofill/payments/webauthn_dialog_view_impl.h",
       "views/close_bubble_on_tab_activation_helper.cc",
       "views/close_bubble_on_tab_activation_helper.h",
+      "views/direct_sockets_connection_bubble_dialog.cc",
       "views/external_protocol_dialog.cc",
       "views/external_protocol_dialog.h",
       "views/hats/hats_next_web_dialog.cc",
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb
index 560133e..0d58473 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_am.xtb
@@ -897,7 +897,7 @@
 <translation id="6648977384226967773">{CONTACT,plural, =1{<ph name="CONTACT_PREVIEW" />\u2026 እና <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ተጨማሪ}one{<ph name="CONTACT_PREVIEW" />\u2026 እና <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ተጨማሪ}other{<ph name="CONTACT_PREVIEW" />\u2026 እና <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ተጨማሪ}}</translation>
 <translation id="6649642165559792194">ምስል <ph name="BEGIN_NEW" />አዲስ<ph name="END_NEW" />ን ቅድሚያ ይመልከቱ</translation>
 <translation id="6656545060687952787">Chrome መሣሪያዎችን ለመቃኘት የአካባቢ መዳረሻ ያስፈልገዋል። <ph name="BEGIN_LINK" />ፍቃዶችን ያዘምኑ<ph name="END_LINK" /></translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6659594942844771486">ትር</translation>
 <translation id="666731172850799929">በ<ph name="APP_NAME" /> ውስጥ ክፈት</translation>
 <translation id="666981079809192359">የChrome ግላዊነት ማስታወቂያ</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
index 6f7a767..f4afbde 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_el.xtb
@@ -897,7 +897,7 @@
 <translation id="6648977384226967773">{CONTACT,plural, =1{<ph name="CONTACT_PREVIEW" />\u2026 και <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ακόμη}other{<ph name="CONTACT_PREVIEW" />\u2026 και <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ακόμη}}</translation>
 <translation id="6649642165559792194">Προεπισκόπηση εικόνας <ph name="BEGIN_NEW" />Νέο<ph name="END_NEW" /></translation>
 <translation id="6656545060687952787">Το Chrome χρειάζεται πρόσβαση στην τοποθεσία, προκειμένου να κάνει σάρωση για συσκευές. <ph name="BEGIN_LINK" />Ενημέρωση δικαιωμάτων<ph name="END_LINK" /></translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6659594942844771486">Καρτέλα</translation>
 <translation id="666731172850799929">Άνοιγμα σε <ph name="APP_NAME" /></translation>
 <translation id="666981079809192359">Σημείωση Απορρήτου του Chrome</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb
index c7c8c7c0..194aa46 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_ro.xtb
@@ -1184,7 +1184,7 @@
 <translation id="8493948351860045254">Eliberează spațiu</translation>
 <translation id="8497726226069778601">Nu este nimic de văzut aici... deocamdată</translation>
 <translation id="8503559462189395349">Parole Chrome</translation>
-<translation id="8503813439785031346">Nume utilizator</translation>
+<translation id="8503813439785031346">Nume de utilizator</translation>
 <translation id="8514477925623180633">Exportă parolele stocate în Chrome</translation>
 <translation id="8516012719330875537">Editor de imagini</translation>
 <translation id="8523928698583292556">Șterge parola stocată</translation>
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
index 43c5120..2976c7f 100644
--- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
+++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_zh-HK.xtb
@@ -1184,7 +1184,7 @@
 <translation id="8493948351860045254">釋出儲存空間</translation>
 <translation id="8497726226069778601">這裡尚未顯示任何內容…</translation>
 <translation id="8503559462189395349">Chrome 密碼</translation>
-<translation id="8503813439785031346">使用者名稱</translation>
+<translation id="8503813439785031346">用戶名稱</translation>
 <translation id="8514477925623180633">匯出儲存在 Chrome 中的密碼</translation>
 <translation id="8516012719330875537">圖片編輯器</translation>
 <translation id="8523928698583292556">刪除已儲存的密碼</translation>
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 639bcdcd..5903e2c 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
@@ -604,7 +604,8 @@
     const auto* holding_space_item =
         primary_holding_space_model->items()[0].get();
 
-    persisted_holding_space_items.Remove(0, /*out_value=*/nullptr);
+    persisted_holding_space_items.EraseListIter(
+        persisted_holding_space_items.GetList().begin());
     primary_holding_space_model->RemoveItem(holding_space_item->id());
 
     EXPECT_EQ(*GetProfile()->GetPrefs()->GetList(
diff --git a/chrome/browser/ui/ash/login_screen_client_impl.cc b/chrome/browser/ui/ash/login_screen_client_impl.cc
index 2d44c58..73cfa287 100644
--- a/chrome/browser/ui/ash/login_screen_client_impl.cc
+++ b/chrome/browser/ui/ash/login_screen_client_impl.cc
@@ -206,8 +206,8 @@
       ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
   user_manager::UserManager::Get()->RemoveUser(account_id,
                                                nullptr /*delegate*/);
-  if (chromeos::LoginDisplayHost::default_host())
-    chromeos::LoginDisplayHost::default_host()->UpdateAddUserButtonStatus();
+  if (ash::LoginDisplayHost::default_host())
+    ash::LoginDisplayHost::default_host()->UpdateAddUserButtonStatus();
 }
 
 void LoginScreenClientImpl::LaunchPublicSession(
@@ -229,8 +229,8 @@
 
 void LoginScreenClientImpl::HandleAccelerator(
     ash::LoginAcceleratorAction action) {
-  if (chromeos::LoginDisplayHost::default_host())
-    chromeos::LoginDisplayHost::default_host()->HandleAccelerator(action);
+  if (ash::LoginDisplayHost::default_host())
+    ash::LoginDisplayHost::default_host()->HandleAccelerator(action);
 }
 
 void LoginScreenClientImpl::ShowAccountAccessHelpApp(
@@ -282,12 +282,11 @@
 
 void LoginScreenClientImpl::LoginAsGuest() {
   DCHECK(!chromeos::ScreenLocker::default_screen_locker());
-  if (chromeos::LoginDisplayHost::default_host()) {
-    chromeos::LoginDisplayHost::default_host()
-        ->GetExistingUserController()
-        ->Login(chromeos::UserContext(user_manager::USER_TYPE_GUEST,
-                                      user_manager::GuestAccountId()),
-                chromeos::SigninSpecifics());
+  if (ash::LoginDisplayHost::default_host()) {
+    ash::LoginDisplayHost::default_host()->GetExistingUserController()->Login(
+        chromeos::UserContext(user_manager::USER_TYPE_GUEST,
+                              user_manager::GuestAccountId()),
+        chromeos::SigninSpecifics());
   }
 }
 
@@ -327,8 +326,8 @@
 }
 
 void LoginScreenClientImpl::OnUserActivity() {
-  if (chromeos::LoginDisplayHost::default_host()) {
-    chromeos::LoginDisplayHost::default_host()
+  if (ash::LoginDisplayHost::default_host()) {
+    ash::LoginDisplayHost::default_host()
         ->GetExistingUserController()
         ->ResetAutoLoginTimer();
   }
@@ -343,9 +342,8 @@
 
 void LoginScreenClientImpl::ShowGaiaSigninInternal(
     const AccountId& prefilled_account) {
-  if (chromeos::LoginDisplayHost::default_host()) {
-    chromeos::LoginDisplayHost::default_host()->ShowGaiaDialog(
-        prefilled_account);
+  if (ash::LoginDisplayHost::default_host()) {
+    ash::LoginDisplayHost::default_host()->ShowGaiaDialog(prefilled_account);
   } else {
     const user_manager::User* user =
         user_manager::UserManager::Get()->FindUser(prefilled_account);
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
index 519c0c1..f5ec500 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -3109,7 +3109,7 @@
 
   // Removing |extension1_| from the policy should not be reflected in the
   // shelf and pin will exist.
-  policy_value.Remove(0, nullptr);
+  policy_value.EraseListIter(policy_value.GetList().begin());
   profile()->GetTestingPrefService()->SetManagedPref(
       prefs::kPolicyPinnedLauncherApps,
       base::Value::ToUniquePtrValue(policy_value.Clone()));
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
index 1c670ce..fb66c63 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
@@ -225,7 +225,7 @@
   }
 
   // Do not set wallpaper in tests.
-  if (chromeos::WizardController::IsZeroDelayEnabled())
+  if (ash::WizardController::IsZeroDelayEnabled())
     return;
 
   // Show the wallpaper of the active user during an user session.
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h
index c01ba82..70b55231 100644
--- a/chrome/browser/ui/browser_dialogs.h
+++ b/chrome/browser/ui/browser_dialogs.h
@@ -412,6 +412,19 @@
 void ShowWindowNamePromptForTesting(Browser* browser,
                                     gfx::NativeWindow context);
 
+// Callback used to indicate whether Direct Sockets connection dialog is
+// accepted or not. If accepted, the remote address and port number are
+// provided.
+using OnProceedCallback = base::OnceCallback<
+    void(bool accepted, const std::string& address, const std::string& port)>;
+
+// Show dialog to accept remote address and port number information, which will
+// be used to make a socket connection. The window is automatically destroyed
+// when it is closed.
+void ShowDirectSocketsConnectionDialog(Browser* browser,
+                                       const std::string& address,
+                                       OnProceedCallback callback);
+
 }  // namespace chrome
 
 void ShowFolderUploadConfirmationDialog(
diff --git a/chrome/browser/ui/views/direct_sockets_connection_bubble_dialog.cc b/chrome/browser/ui/views/direct_sockets_connection_bubble_dialog.cc
new file mode 100644
index 0000000..d1aba533
--- /dev/null
+++ b/chrome/browser/ui/views/direct_sockets_connection_bubble_dialog.cc
@@ -0,0 +1,108 @@
+// 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 <string>
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/dialog_model.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/bubble/bubble_dialog_model_host.h"
+
+namespace chrome {
+
+namespace {
+
+// Unique identifiers used for getting related DialogModelFields.
+constexpr int kRemoteAddressId = 1;
+constexpr int kRemotePortId = 2;
+
+class DirectSocketsConnectionBubbleDelegate : public ui::DialogModelDelegate {
+ public:
+  explicit DirectSocketsConnectionBubbleDelegate(
+      OnProceedCallback proceed_callback)
+      : proceed_callback_(std::move(proceed_callback)) {}
+
+  // Callback functions for when the dialog is accepted or not, with |accepted|
+  // set to true or false.
+  void OnProceed(bool accepted) {
+    std::u16string remote_address;
+    std::u16string remote_port;
+    // Only send back the user input if the dialog is accepted.
+    if (accepted) {
+      remote_address =
+          dialog_model()->GetTextfieldByUniqueId(kRemoteAddressId)->text();
+      remote_port =
+          dialog_model()->GetTextfieldByUniqueId(kRemotePortId)->text();
+    }
+    std::move(proceed_callback_)
+        .Run(accepted, base::UTF16ToUTF8(remote_address),
+             base::UTF16ToUTF8(remote_port));
+  }
+
+  void OnClose() {
+    // OnClose() may be called after OnProceed(), in which case the callback is
+    // null.
+    if (proceed_callback_)
+      OnProceed(/*accepted=*/false);
+  }
+
+ private:
+  OnProceedCallback proceed_callback_;
+};
+
+}  // namespace
+
+void ShowDirectSocketsConnectionDialog(Browser* browser,
+                                       const std::string& address,
+                                       OnProceedCallback proceed_callback) {
+  auto bubble_delegate_unique =
+      std::make_unique<DirectSocketsConnectionBubbleDelegate>(
+          std::move(proceed_callback));
+  DirectSocketsConnectionBubbleDelegate* bubble_delegate =
+      bubble_delegate_unique.get();
+
+  auto dialog_model =
+      ui::DialogModel::Builder(std::move(bubble_delegate_unique))
+          .SetTitle(l10n_util::GetStringUTF16(
+              IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_TITLE_LABEL))
+          .SetWindowClosingCallback(
+              base::BindOnce(&DirectSocketsConnectionBubbleDelegate::OnClose,
+                             base::Unretained(bubble_delegate)))
+          .AddOkButton(
+              base::BindOnce(&DirectSocketsConnectionBubbleDelegate::OnProceed,
+                             base::Unretained(bubble_delegate),
+                             /*accepted=*/true),
+              l10n_util::GetStringUTF16(IDS_OK))
+          .AddCancelButton(
+              base::BindOnce(&DirectSocketsConnectionBubbleDelegate::OnProceed,
+                             base::Unretained(bubble_delegate),
+                             /*accepted=*/false),
+              l10n_util::GetStringUTF16(IDS_CANCEL))
+          .AddTextfield(
+              l10n_util::GetStringUTF16(
+                  IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_ADDRESS_LABEL),
+              base::UTF8ToUTF16(address),
+              ui::DialogModelTextfield::Params().SetUniqueId(kRemoteAddressId))
+          .AddTextfield(
+              l10n_util::GetStringUTF16(
+                  IDS_DIRECT_SOCKETS_CONNECTION_BUBBLE_PORT_LABEL),
+              std::u16string(),
+              ui::DialogModelTextfield::Params().SetUniqueId(kRemotePortId))
+          .SetInitiallyFocusedField(kRemoteAddressId)
+          .Build();
+
+  views::BubbleDialogDelegateView::CreateBubble(
+      std::make_unique<views::BubbleDialogModelHost>(
+          std::move(dialog_model),
+          BrowserView::GetBrowserViewForBrowser(browser),
+          views::BubbleBorder::FLOAT))
+      ->Show();
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/views/direct_sockets_connection_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/direct_sockets_connection_bubble_dialog_browsertest.cc
new file mode 100644
index 0000000..a9f0a954
--- /dev/null
+++ b/chrome/browser/ui/views/direct_sockets_connection_bubble_dialog_browsertest.cc
@@ -0,0 +1,65 @@
+// 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 <string>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "content/public/test/browser_test.h"
+
+namespace chrome {
+
+namespace {
+
+const char kHostname[] = "ds.example";
+
+}  // anonymous namespace
+
+class DirectSocketsConnectionBubbleDialogBrowserTest
+    : public DialogBrowserTest {
+ public:
+  DirectSocketsConnectionBubbleDialogBrowserTest() = default;
+
+  DirectSocketsConnectionBubbleDialogBrowserTest(
+      const DirectSocketsConnectionBubbleDialogBrowserTest&) = delete;
+  DirectSocketsConnectionBubbleDialogBrowserTest& operator=(
+      const DirectSocketsConnectionBubbleDialogBrowserTest&) = delete;
+
+  // DialogBrowserTest:
+  void ShowUi(const std::string& name) override {
+    chrome::ShowDirectSocketsConnectionDialog(
+        browser(), kHostname,
+        base::BindOnce(
+            &DirectSocketsConnectionBubbleDialogBrowserTest::OnDialogProceed,
+            weak_ptr_factory_.GetWeakPtr(), name));
+  }
+
+ private:
+  void OnDialogProceed(const std::string& name,
+                       bool accepted,
+                       const std::string& address,
+                       const std::string& port) {
+    // The Dialog is closed by default. Make sure the dialog isn't accepted and
+    // what the user has input should not be sent back to the caller.
+    if (name == "default") {
+      EXPECT_FALSE(accepted);
+      EXPECT_TRUE(address.empty());
+      EXPECT_TRUE(port.empty());
+    }
+  }
+
+  base::WeakPtrFactory<DirectSocketsConnectionBubbleDialogBrowserTest>
+      weak_ptr_factory_{this};
+};
+
+// Test that calls ShowUi("default").
+IN_PROC_BROWSER_TEST_F(DirectSocketsConnectionBubbleDialogBrowserTest,
+                       InvokeUi_default) {
+  ShowAndVerifyUi();
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc
index 0a789ae..a6324f6 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -111,7 +111,7 @@
 
 // Return the Chrome OS WebUI login WebContents, if applicable.
 content::WebContents* GetLoginWebContents() {
-  chromeos::LoginDisplayHost* host = chromeos::LoginDisplayHost::default_host();
+  auto* host = ash::LoginDisplayHost::default_host();
   return host ? host->GetOobeWebContents() : nullptr;
 }
 
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index e04c83a..a199e56 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -173,7 +173,7 @@
 // Returns an absolute path under the preinstalled demo resources directory.
 base::FilePath CreateDemoResourcesTermsPath(const base::FilePath& file_path) {
   // Offline ARC TOS are only available during demo mode setup.
-  auto* wizard_controller = chromeos::WizardController::default_controller();
+  auto* wizard_controller = ash::WizardController::default_controller();
   if (!wizard_controller || !wizard_controller->demo_setup_controller())
     return base::FilePath();
   return wizard_controller->demo_setup_controller()
diff --git a/chrome/browser/ui/webui/about_ui_unittest.cc b/chrome/browser/ui/webui/about_ui_unittest.cc
index 273d555..b082ad821 100644
--- a/chrome/browser/ui/webui/about_ui_unittest.cc
+++ b/chrome/browser/ui/webui/about_ui_unittest.cc
@@ -170,8 +170,7 @@
 
     // Simulate Demo Mode setup.
     chromeos::DBusThreadManager::Initialize();
-    fake_login_display_host_ =
-        std::make_unique<chromeos::FakeLoginDisplayHost>();
+    fake_login_display_host_ = std::make_unique<ash::FakeLoginDisplayHost>();
     fake_login_display_host_->StartWizard(
         chromeos::DemoPreferencesScreenView::kScreenId);
     fake_login_display_host_->GetWizardController()
@@ -224,7 +223,7 @@
   }
 
  private:
-  std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
+  std::unique_ptr<ash::FakeLoginDisplayHost> fake_login_display_host_;
 
   DISALLOW_COPY_AND_ASSIGN(DemoModeChromeOSTermsTest);
 };
diff --git a/chrome/browser/ui/webui/chromeos/login/active_directory_login_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/active_directory_login_screen_handler.h
index 90e682a..0152f19 100644
--- a/chrome/browser/ui/webui/chromeos/login/active_directory_login_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/active_directory_login_screen_handler.h
@@ -82,6 +82,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::ActiveDirectoryLoginScreenHandler;
 using ::chromeos::ActiveDirectoryLoginView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h
index 8a978fee..c389126e 100644
--- a/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h
@@ -77,6 +77,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::ActiveDirectoryPasswordChangeScreenHandler;
 using ::chromeos::ActiveDirectoryPasswordChangeView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/app_downloading_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/app_downloading_screen_handler.h
index 26d0c75..330e033 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_downloading_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/app_downloading_screen_handler.h
@@ -63,6 +63,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::AppDownloadingScreenHandler;
 using ::chromeos::AppDownloadingScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
index d33cc0c9..e21825c 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
@@ -148,4 +148,11 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::AppLaunchSplashScreenHandler;
+using ::chromeos::AppLaunchSplashScreenView;
+}  // namespace ash
+
 #endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_APP_LAUNCH_SPLASH_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
index 1cfcbe5..1bf351e5 100644
--- a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
@@ -182,6 +182,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::ArcTermsOfServiceScreenHandler;
 using ::chromeos::ArcTermsOfServiceScreenView;
 using ::chromeos::ArcTermsOfServiceScreenViewObserver;
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
index 2611a15..68719cf 100644
--- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
@@ -183,6 +183,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::AssistantOptInFlowScreenHandler;
 using ::chromeos::AssistantOptInFlowScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h
index f4e9b63b..f16b830 100644
--- a/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h
@@ -45,5 +45,11 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::AutoEnrollmentCheckScreenHandler;
+}
+
 #endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_AUTO_ENROLLMENT_CHECK_SCREEN_HANDLER_H_
 
diff --git a/chrome/browser/ui/webui/chromeos/login/demo_preferences_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/demo_preferences_screen_handler.h
index b4c3c44..858af65 100644
--- a/chrome/browser/ui/webui/chromeos/login/demo_preferences_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/demo_preferences_screen_handler.h
@@ -73,6 +73,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::DemoPreferencesScreenHandler;
 using ::chromeos::DemoPreferencesScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
index d8db533..01346c1 100644
--- a/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
@@ -80,6 +80,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::DemoSetupScreenHandler;
 using ::chromeos::DemoSetupScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h
index 78a45e9..0b19f8e2 100644
--- a/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h
@@ -64,6 +64,7 @@
 
 // TODO(https://crbug.com/1164001): remove when moved to ash.
 namespace ash {
+using ::chromeos::DeviceDisabledScreenHandler;
 using ::chromeos::DeviceDisabledScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/enable_adb_sideloading_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enable_adb_sideloading_screen_handler.h
index a8ad251..ef23789e 100644
--- a/chrome/browser/ui/webui/chromeos/login/enable_adb_sideloading_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enable_adb_sideloading_screen_handler.h
@@ -71,6 +71,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::EnableAdbSideloadingScreenHandler;
 using ::chromeos::EnableAdbSideloadingScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h
index 54e437e..010932d 100644
--- a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h
@@ -83,6 +83,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::EnableDebuggingScreenHandler;
 using ::chromeos::EnableDebuggingScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
index c4462ef9..464a6648 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.h
@@ -87,6 +87,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::EncryptionMigrationScreenHandler;
 using ::chromeos::EncryptionMigrationScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
index f976df8..97417fa9 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
@@ -212,6 +212,7 @@
 // source migration is finished.
 namespace ash {
 using ::chromeos::ActiveDirectoryErrorState;
+using ::chromeos::EnrollmentScreenHandler;
 }
 
 #endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ENROLLMENT_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
index 960a349..03db5be4 100644
--- a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
@@ -89,6 +89,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::EulaScreenHandler;
 using ::chromeos::EulaView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h
index 3e23e0d..8a54b15 100644
--- a/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/fake_app_launch_splash_screen_handler.h
@@ -34,4 +34,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::FakeAppLaunchSplashScreenHandler;
+}
+
 #endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_FAKE_APP_LAUNCH_SPLASH_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/family_link_notice_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/family_link_notice_screen_handler.h
index a9337dc..55dfc149 100644
--- a/chrome/browser/ui/webui/chromeos/login/family_link_notice_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/family_link_notice_screen_handler.h
@@ -76,6 +76,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::FamilyLinkNoticeScreenHandler;
 using ::chromeos::FamilyLinkNoticeView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h
index e2cc498c..bf63fb1 100644
--- a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h
@@ -78,6 +78,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::FingerprintSetupScreenHandler;
 using ::chromeos::FingerprintSetupScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h
index 2f1a1693..223a2d4 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h
@@ -66,6 +66,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::GaiaPasswordChangedScreenHandler;
 using ::chromeos::GaiaPasswordChangedView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h
index 963fc33..46dd1be 100644
--- a/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h
@@ -66,6 +66,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::GestureNavigationScreenHandler;
 using ::chromeos::GestureNavigationScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h
index c9810ca..b8d6d56 100644
--- a/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h
@@ -77,6 +77,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::KioskAutolaunchScreenHandler;
 using ::chromeos::KioskAutolaunchScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h
index 7bdd19d8..98429520 100644
--- a/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h
@@ -63,6 +63,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::KioskEnableScreenHandler;
 using ::chromeos::KioskEnableScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/locale_switch_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/locale_switch_screen_handler.h
index 64d8bdbd..15c210ff 100644
--- a/chrome/browser/ui/webui/chromeos/login/locale_switch_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/locale_switch_screen_handler.h
@@ -60,6 +60,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::LocaleSwitchScreenHandler;
 using ::chromeos::LocaleSwitchView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
index b16f6ec..75d3ae52 100644
--- a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
@@ -91,6 +91,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::MarketingOptInScreenHandler;
 using ::chromeos::MarketingOptInScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h
index fc0418f..7a55143 100644
--- a/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/multidevice_setup_screen_handler.h
@@ -58,6 +58,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::MultiDeviceSetupScreenHandler;
 using ::chromeos::MultiDeviceSetupScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
index fa07adf..885700c 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
@@ -84,6 +84,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::NetworkScreenHandler;
 using ::chromeos::NetworkScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/offline_login_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/offline_login_screen_handler.h
index 6d962aa6..d693563 100644
--- a/chrome/browser/ui/webui/chromeos/login/offline_login_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/offline_login_screen_handler.h
@@ -90,6 +90,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::OfflineLoginScreenHandler;
 using ::chromeos::OfflineLoginView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.h
index c7a69e1..9d6e433c 100644
--- a/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/os_install_screen_handler.h
@@ -61,4 +61,11 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::OsInstallScreenHandler;
+using ::chromeos::OsInstallScreenView;
+}  // namespace ash
+
 #endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_OS_INSTALL_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/login/packaged_license_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/packaged_license_screen_handler.h
index e91da03..74da0134 100644
--- a/chrome/browser/ui/webui/chromeos/login/packaged_license_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/packaged_license_screen_handler.h
@@ -70,6 +70,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::PackagedLicenseScreenHandler;
 using ::chromeos::PackagedLicenseView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/parental_handoff_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/parental_handoff_screen_handler.h
index 5576319..10543eae 100644
--- a/chrome/browser/ui/webui/chromeos/login/parental_handoff_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/parental_handoff_screen_handler.h
@@ -68,6 +68,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::ParentalHandoffScreenHandler;
 using ::chromeos::ParentalHandoffScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/pin_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/pin_setup_screen_handler.h
index aff6ebc..e23e965d 100644
--- a/chrome/browser/ui/webui/chromeos/login/pin_setup_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/pin_setup_screen_handler.h
@@ -67,6 +67,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::PinSetupScreenHandler;
 using ::chromeos::PinSetupScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h
index c16dbc4..1c14b36 100644
--- a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h
@@ -93,6 +93,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::RecommendAppsScreenHandler;
 using ::chromeos::RecommendAppsScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
index a0df56c..a188bfa5 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
@@ -111,6 +111,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::ResetScreenHandler;
 using ::chromeos::ResetView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_fatal_error_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_fatal_error_screen_handler.h
index 9cc98ad..65bbc99 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_fatal_error_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_fatal_error_screen_handler.h
@@ -59,6 +59,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::SignInFatalErrorScreenHandler;
 using ::chromeos::SignInFatalErrorView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h
index e558ed5a..b18e387 100644
--- a/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h
@@ -111,6 +111,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::TermsOfServiceScreenHandler;
 using ::chromeos::TermsOfServiceScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h
index dca27c2..95b7ae6 100644
--- a/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h
@@ -60,6 +60,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::TpmErrorScreenHandler;
 using ::chromeos::TpmErrorView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h
index 647f9eb..886723f 100644
--- a/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h
@@ -117,6 +117,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::UpdateRequiredScreenHandler;
 using ::chromeos::UpdateRequiredView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
index 93ee6b5..156d03b19 100644
--- a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
@@ -102,6 +102,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::UpdateScreenHandler;
 using ::chromeos::UpdateView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h
index 452b86f6..957ceae8 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h
@@ -65,6 +65,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::UserCreationScreenHandler;
 using ::chromeos::UserCreationView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
index 6fc81319..7efe85fb 100644
--- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
@@ -129,6 +129,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::WelcomeScreenHandler;
 using ::chromeos::WelcomeView;
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h
index d258410..40aff6b 100644
--- a/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h
@@ -67,6 +67,7 @@
 // TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
 // source migration is finished.
 namespace ash {
+using ::chromeos::WrongHWIDScreenHandler;
 using ::chromeos::WrongHWIDScreenView;
 }
 
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index adf5ee9c..78d1fabc 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -30,15 +30,13 @@
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/l10n/l10n_util.h"
 
-using chromeos::CrosSettings;
-using chromeos::DBusThreadManager;
-using chromeos::OwnerSettingsServiceAsh;
-using chromeos::OwnerSettingsServiceAshFactory;
-using chromeos::UpdateEngineClient;
-using chromeos::WizardController;
-
 namespace {
 
+using ::chromeos::DBusThreadManager;
+using ::chromeos::OwnerSettingsServiceAsh;
+using ::chromeos::OwnerSettingsServiceAshFactory;
+using ::chromeos::UpdateEngineClient;
+
 // Network status in the context of device update.
 enum NetworkStatus {
   // It's allowed to use current network for update.
@@ -173,7 +171,7 @@
   check_for_update_when_idle_ = false;
 
   // Make sure that libcros is loaded and OOBE is complete.
-  if (!WizardController::default_controller() ||
+  if (!ash::WizardController::default_controller() ||
       chromeos::StartupUtils::IsDeviceRegistered()) {
     update_engine_client->RequestUpdateCheck(base::BindOnce(
         &VersionUpdaterCros::OnUpdateCheck, weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index dad823f..14c5cfd8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -298,11 +298,9 @@
       continue;
     }
 
-    absl::optional<AccountInfo> maybe_account_info =
-        identity_manager_
-            ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
-                account_key.id);
-    if (!maybe_account_info.has_value()) {
+    AccountInfo maybe_account_info =
+        identity_manager_->FindExtendedAccountInfoByGaiaId(account_key.id);
+    if (maybe_account_info.IsEmpty()) {
       // This account hasn't propagated to IdentityManager yet. When this
       // happens, `IdentityManager` will call `OnRefreshTokenUpdatedForAccount`
       // which will trigger another UI update.
@@ -313,16 +311,16 @@
     account.SetId(account_key.id)
         .SetAccountType(static_cast<int>(account_key.account_type))
         .SetIsDeviceAccount(false)
-        .SetFullName(maybe_account_info->full_name)
+        .SetFullName(maybe_account_info.full_name)
         .SetEmail(stored_account.raw_email)
         .SetUnmigrated(!is_child_user && account_token_pair.second)
         .SetIsSignedIn(!identity_manager_
                             ->HasAccountWithRefreshTokenInPersistentErrorState(
-                                maybe_account_info->account_id));
+                                maybe_account_info.account_id));
 
-    if (!maybe_account_info->account_image.IsEmpty()) {
-      account.SetPic(webui::GetBitmapDataUrl(
-          maybe_account_info->account_image.AsBitmap()));
+    if (!maybe_account_info.account_image.IsEmpty()) {
+      account.SetPic(
+          webui::GetBitmapDataUrl(maybe_account_info.account_image.AsBitmap()));
     } else {
       gfx::ImageSkia default_icon =
           *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc
index f232e67..0066e30 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc
@@ -371,16 +371,15 @@
     EXPECT_EQ(expected_account.raw_email,
               ValueOrEmpty(account.FindStringKey("email")));
 
-    absl::optional<AccountInfo> expected_account_info =
-        identity_manager()
-            ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
-                expected_account.key.id);
-    EXPECT_TRUE(expected_account_info.has_value());
-    EXPECT_EQ(expected_account_info->full_name,
+    AccountInfo expected_account_info =
+        identity_manager()->FindExtendedAccountInfoByGaiaId(
+            expected_account.key.id);
+    EXPECT_FALSE(expected_account_info.IsEmpty());
+    EXPECT_EQ(expected_account_info.full_name,
               ValueOrEmpty(account.FindStringKey("fullName")));
     EXPECT_EQ(
         !identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
-            expected_account_info->account_id),
+            expected_account_info.account_id),
         account.FindBoolKey("isSignedIn").value());
   }
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/main_section.cc b/chrome/browser/ui/webui/settings/chromeos/main_section.cc
index f26640c..f8761bc 100644
--- a/chrome/browser/ui/webui/settings/chromeos/main_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/main_section.cc
@@ -131,6 +131,7 @@
       {"edit", IDS_SETTINGS_EDIT},
       {"extensionsLinkTooltip", IDS_SETTINGS_MENU_EXTENSIONS_LINK_TOOLTIP},
       {"learnMore", IDS_LEARN_MORE},
+      {"shortcutBannerDismissed", IDS_SETTINGS_SHORTCUT_BANNER_DISMISSED},
       {"menu", IDS_MENU},
       {"menuButtonLabel", IDS_SETTINGS_MENU_BUTTON_LABEL},
       {"moreActions", IDS_SETTINGS_MORE_ACTIONS},
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index b22eecd..ac3fda8e 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -490,11 +490,10 @@
   // Chrome OS), then show only the primary account, whether or not that account
   // has consented to sync.
   auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
-  absl::optional<AccountInfo> primary_account_info =
-      identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
-          identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSignin));
-  if (primary_account_info.has_value())
-    accounts.Append(GetAccountValue(primary_account_info.value()));
+  AccountInfo primary_account_info = identity_manager->FindExtendedAccountInfo(
+      identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+  if (!primary_account_info.IsEmpty())
+    accounts.Append(GetAccountValue(primary_account_info));
   return accounts;
 }
 
@@ -509,14 +508,12 @@
   Browser* browser =
       chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
 
-  absl::optional<AccountInfo> maybe_account =
+  AccountInfo maybe_account =
       IdentityManagerFactory::GetForProfile(profile_)
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-              email->GetString());
+          ->FindExtendedAccountInfoByEmailAddress(email->GetString());
 
   signin_ui_util::EnableSyncFromMultiAccountPromo(
-      browser,
-      maybe_account.has_value() ? maybe_account.value() : AccountInfo(),
+      browser, maybe_account,
       signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
       is_default_promo_account->GetBool());
 #else
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
index 557134d..4343ab10 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/extensions/extension_constants.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/services/app_service/public/cpp/publisher_base.h"
 #include "content/public/browser/clear_site_data_utils.h"
@@ -40,6 +39,7 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ash/arc/arc_web_contents_data.h"
+#include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/chromeos/extensions/gfx_utils.h"
 #include "components/full_restore/app_launch_info.h"
 #include "components/full_restore/full_restore_utils.h"
@@ -89,7 +89,8 @@
       app_type_(app_type),
       delegate_(delegate),
       provider_(WebAppProvider::Get(profile)) {
-  web_app_launch_manager_ = std::make_unique<WebAppLaunchManager>(profile_);
+  DCHECK(profile_);
+  Init();
 }
 
 WebAppPublisherHelper::~WebAppPublisherHelper() = default;
@@ -100,6 +101,38 @@
   return base::Contains(kSupportedPermissionTypes, permission_type);
 }
 
+// static
+webapps::WebappUninstallSource
+WebAppPublisherHelper::ConvertUninstallSourceToWebAppUninstallSource(
+    apps::mojom::UninstallSource uninstall_source) {
+  switch (uninstall_source) {
+    case apps::mojom::UninstallSource::kAppList:
+      return webapps::WebappUninstallSource::kAppList;
+    case apps::mojom::UninstallSource::kAppManagement:
+      return webapps::WebappUninstallSource::kAppManagement;
+    case apps::mojom::UninstallSource::kShelf:
+      return webapps::WebappUninstallSource::kShelf;
+    case apps::mojom::UninstallSource::kMigration:
+      return webapps::WebappUninstallSource::kMigration;
+    case apps::mojom::UninstallSource::kUnknown:
+      return webapps::WebappUninstallSource::kUnknown;
+  }
+}
+
+// static
+bool WebAppPublisherHelper::Accepts(const std::string& app_id) {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // Crostini Terminal System App is handled by Crostini Apps.
+  return app_id != crostini::kCrostiniTerminalSystemAppId;
+#else
+  return true;
+#endif
+}
+
+void WebAppPublisherHelper::Shutdown() {
+  content_settings_observation_.Reset();
+}
+
 void WebAppPublisherHelper::SetWebAppShowInFields(apps::mojom::AppPtr& app,
                                                   const WebApp* web_app) {
   if (web_app->chromeos_data().has_value()) {
@@ -214,24 +247,6 @@
   return app;
 }
 
-// static
-webapps::WebappUninstallSource
-WebAppPublisherHelper::ConvertUninstallSourceToWebAppUninstallSource(
-    apps::mojom::UninstallSource uninstall_source) {
-  switch (uninstall_source) {
-    case apps::mojom::UninstallSource::kAppList:
-      return webapps::WebappUninstallSource::kAppList;
-    case apps::mojom::UninstallSource::kAppManagement:
-      return webapps::WebappUninstallSource::kAppManagement;
-    case apps::mojom::UninstallSource::kShelf:
-      return webapps::WebappUninstallSource::kShelf;
-    case apps::mojom::UninstallSource::kMigration:
-      return webapps::WebappUninstallSource::kMigration;
-    case apps::mojom::UninstallSource::kUnknown:
-      return webapps::WebappUninstallSource::kUnknown;
-  }
-}
-
 void WebAppPublisherHelper::UninstallWebApp(
     const WebApp* web_app,
     apps::mojom::UninstallSource uninstall_source,
@@ -269,49 +284,6 @@
                          kAvoidClosingConnections, base::DoNothing());
 }
 
-IconEffects WebAppPublisherHelper::GetIconEffects(
-    const WebApp* web_app,
-    absl::optional<bool> is_disabled_opt) {
-  IconEffects icon_effects = IconEffects::kRoundCorners;
-  if (!web_app->is_locally_installed()) {
-    icon_effects |= IconEffects::kBlocked;
-  }
-
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
-    icon_effects |= web_app->is_generated_icon()
-                        ? IconEffects::kCrOsStandardMask
-                        : IconEffects::kCrOsStandardIcon;
-  } else {
-    icon_effects |= IconEffects::kResizeAndPad;
-  }
-#endif
-
-  if (IsPaused(web_app->app_id())) {
-    icon_effects |= IconEffects::kPaused;
-  }
-
-  bool is_disabled = false;
-  if (is_disabled_opt.has_value()) {
-    is_disabled = *is_disabled_opt;
-  } else if (web_app->chromeos_data().has_value()) {
-    is_disabled = web_app->chromeos_data()->is_disabled;
-  }
-  if (is_disabled) {
-    icon_effects |= IconEffects::kBlocked;
-  }
-
-// TODO(crbug.com/1214707): Implement badging for Lacros.
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  if (extensions::util::ShouldApplyChromeBadgeToWebApp(profile(),
-                                                       web_app->app_id())) {
-    icon_effects |= IconEffects::kChromeBadge;
-  }
-#endif
-
-  return icon_effects;
-}
-
 apps::mojom::IconKeyPtr WebAppPublisherHelper::MakeIconKey(
     const WebApp* web_app,
     absl::optional<bool> is_disabled) {
@@ -582,6 +554,77 @@
   return *provider_->registrar().AsWebAppRegistrar();
 }
 
+void WebAppPublisherHelper::OnContentSettingChanged(
+    const ContentSettingsPattern& primary_pattern,
+    const ContentSettingsPattern& secondary_pattern,
+    ContentSettingsType content_type) {
+  // If content_type is not one of the supported permissions, do nothing.
+  if (!IsSupportedWebAppPermissionType(content_type)) {
+    return;
+  }
+
+  for (const WebApp& web_app : registrar().GetApps()) {
+    if (primary_pattern.Matches(web_app.start_url()) &&
+        Accepts(web_app.app_id())) {
+      apps::mojom::AppPtr app = apps::mojom::App::New();
+      app->app_type = app_type_;
+      app->app_id = web_app.app_id();
+      PopulateWebAppPermissions(&web_app, &app->permissions);
+
+      delegate_->PublishWebApp(std::move(app));
+    }
+  }
+}
+
+void WebAppPublisherHelper::Init() {
+  content_settings_observation_.Observe(
+      HostContentSettingsMapFactory::GetForProfile(profile_));
+  web_app_launch_manager_ = std::make_unique<WebAppLaunchManager>(profile_);
+}
+
+IconEffects WebAppPublisherHelper::GetIconEffects(
+    const WebApp* web_app,
+    absl::optional<bool> is_disabled_opt) {
+  IconEffects icon_effects = IconEffects::kRoundCorners;
+  if (!web_app->is_locally_installed()) {
+    icon_effects |= IconEffects::kBlocked;
+  }
+
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+  if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
+    icon_effects |= web_app->is_generated_icon()
+                        ? IconEffects::kCrOsStandardMask
+                        : IconEffects::kCrOsStandardIcon;
+  } else {
+    icon_effects |= IconEffects::kResizeAndPad;
+  }
+#endif
+
+  if (IsPaused(web_app->app_id())) {
+    icon_effects |= IconEffects::kPaused;
+  }
+
+  bool is_disabled = false;
+  if (is_disabled_opt.has_value()) {
+    is_disabled = *is_disabled_opt;
+  } else if (web_app->chromeos_data().has_value()) {
+    is_disabled = web_app->chromeos_data()->is_disabled;
+  }
+  if (is_disabled) {
+    icon_effects |= IconEffects::kBlocked;
+  }
+
+// TODO(crbug.com/1214707): Implement badging for Lacros.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  if (extensions::util::ShouldApplyChromeBadgeToWebApp(profile(),
+                                                       web_app->app_id())) {
+    icon_effects |= IconEffects::kChromeBadge;
+  }
+#endif
+
+  return icon_effects;
+}
+
 const WebApp* WebAppPublisherHelper::GetWebApp(const AppId& app_id) const {
   return registrar().GetAppById(app_id);
 }
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
index c8b311b..9d40d1df 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
@@ -9,10 +9,13 @@
 #include <string>
 #include <vector>
 
+#include "base/scoped_observation.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/icon_key_util.h"
 #include "chrome/browser/apps/app_service/paused_apps.h"
+#include "components/content_settings/core/browser/content_settings_observer.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/webapps/browser/installable/installable_metrics.h"
@@ -30,7 +33,7 @@
 class WebAppRegistrar;
 class WebAppLaunchManager;
 
-class WebAppPublisherHelper {
+class WebAppPublisherHelper : public content_settings::Observer {
  public:
   class Delegate {
    public:
@@ -49,12 +52,23 @@
                         Delegate* delegate);
   WebAppPublisherHelper(const WebAppPublisherHelper&) = delete;
   WebAppPublisherHelper& operator=(const WebAppPublisherHelper&) = delete;
-  ~WebAppPublisherHelper();
+  ~WebAppPublisherHelper() override;
 
   // Indicates if |permission_type| is supported by Web Applications.
   static bool IsSupportedWebAppPermissionType(
       ContentSettingsType permission_type);
 
+  // Converts |uninstall_source| to a |WebappUninstallSource|.
+  static webapps::WebappUninstallSource
+  ConvertUninstallSourceToWebAppUninstallSource(
+      apps::mojom::UninstallSource uninstall_source);
+
+  // Returns true if the app is published as a web app.
+  static bool Accepts(const std::string& app_id);
+
+  // Must be called before profile keyed services are destroyed.
+  void Shutdown();
+
   // Populates the various show_in_* fields of |app|.
   void SetWebAppShowInFields(apps::mojom::AppPtr& app, const WebApp* web_app);
 
@@ -75,11 +89,6 @@
   // last launch time.
   apps::mojom::AppPtr ConvertLaunchedWebApp(const WebApp* web_app);
 
-  // Converts |uninstall_source| to a |WebappUninstallSource|.
-  static webapps::WebappUninstallSource
-  ConvertUninstallSourceToWebAppUninstallSource(
-      apps::mojom::UninstallSource uninstall_source);
-
   // Directly uninstalls |web_app| without prompting the user.
   // If |clear_site_data| is true, any site data associated with the app will
   // be removed.
@@ -146,6 +155,13 @@
   WebAppRegistrar& registrar() const;
 
  private:
+  // content_settings::Observer:
+  void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
+                               const ContentSettingsPattern& secondary_pattern,
+                               ContentSettingsType content_type) override;
+
+  void Init();
+
   apps::IconEffects GetIconEffects(const WebApp* web_app,
                                    absl::optional<bool> is_disabled_opt);
 
@@ -168,6 +184,9 @@
 
   WebAppProvider* const provider_;
 
+  base::ScopedObservation<HostContentSettingsMap, content_settings::Observer>
+      content_settings_observation_{this};
+
   std::unique_ptr<WebAppLaunchManager> web_app_launch_manager_;
 
   apps_util::IncrementingIconKeyFactory icon_key_factory_;
diff --git a/chrome/browser/web_applications/app_service/web_apps.cc b/chrome/browser/web_applications/app_service/web_apps.cc
index d8d7d1e..20d9c4e 100644
--- a/chrome/browser/web_applications/app_service/web_apps.cc
+++ b/chrome/browser/web_applications/app_service/web_apps.cc
@@ -55,8 +55,4 @@
   return app;
 }
 
-bool WebApps::Accepts(const std::string& app_id) {
-  return true;
-}
-
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/app_service/web_apps.h b/chrome/browser/web_applications/app_service/web_apps.h
index 75d8a64..bb7cfbe 100644
--- a/chrome/browser/web_applications/app_service/web_apps.h
+++ b/chrome/browser/web_applications/app_service/web_apps.h
@@ -39,7 +39,6 @@
   // WebAppsBase overrides.
   apps::mojom::AppPtr Convert(const WebApp* web_app,
                               apps::mojom::Readiness readiness) override;
-  bool Accepts(const std::string& app_id) override;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/app_service/web_apps_base.cc b/chrome/browser/web_applications/app_service/web_apps_base.cc
index 53e3ddb8..7cd3121b 100644
--- a/chrome/browser/web_applications/app_service/web_apps_base.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_base.cc
@@ -72,7 +72,7 @@
 void WebAppsBase::Shutdown() {
   if (provider_) {
     registrar_observation_.Reset();
-    content_settings_observation_.Reset();
+    publisher_helper().Shutdown();
   }
 }
 
@@ -82,6 +82,10 @@
   return GetRegistrar() ? GetRegistrar()->GetAppById(app_id) : nullptr;
 }
 
+bool WebAppsBase::Accepts(const std::string& app_id) const {
+  return WebAppPublisherHelper::Accepts(app_id);
+}
+
 void WebAppsBase::OnWebAppInstalled(const AppId& app_id) {
   const WebApp* web_app = GetWebApp(app_id);
   if (web_app && Accepts(app_id)) {
@@ -109,8 +113,6 @@
   DCHECK(provider_);
 
   registrar_observation_.Observe(&provider_->registrar());
-  content_settings_observation_.Observe(
-      HostContentSettingsMapFactory::GetForProfile(profile_));
 
   PublisherBase::Initialize(app_service, app_type_);
   app_service_ = app_service.get();
@@ -183,38 +185,6 @@
   Publish(std::move(app), subscribers_);
 }
 
-void WebAppsBase::OnContentSettingChanged(
-    const ContentSettingsPattern& primary_pattern,
-    const ContentSettingsPattern& secondary_pattern,
-    ContentSettingsType content_type) {
-  // If content_type is not one of the supported permissions, do nothing.
-  if (!WebAppPublisherHelper::IsSupportedWebAppPermissionType(content_type)) {
-    return;
-  }
-
-  if (!profile_) {
-    return;
-  }
-
-  const WebAppRegistrar* registrar = GetRegistrar();
-  // Can be nullptr in tests.
-  if (!registrar) {
-    return;
-  }
-
-  for (const WebApp& web_app : registrar->GetApps()) {
-    if (primary_pattern.Matches(web_app.start_url()) &&
-        Accepts(web_app.app_id())) {
-      apps::mojom::AppPtr app = apps::mojom::App::New();
-      app->app_type = app_type_;
-      app->app_id = web_app.app_id();
-      publisher_helper().PopulateWebAppPermissions(&web_app, &app->permissions);
-
-      Publish(std::move(app), subscribers_);
-    }
-  }
-}
-
 void WebAppsBase::OnWebAppLastLaunchTimeChanged(
     const std::string& app_id,
     const base::Time& last_launch_time) {
diff --git a/chrome/browser/web_applications/app_service/web_apps_base.h b/chrome/browser/web_applications/app_service/web_apps_base.h
index f40f3da..10988aa 100644
--- a/chrome/browser/web_applications/app_service/web_apps_base.h
+++ b/chrome/browser/web_applications/app_service/web_apps_base.h
@@ -15,8 +15,6 @@
 #include "chrome/browser/web_applications/components/app_registrar.h"
 #include "chrome/browser/web_applications/components/app_registrar_observer.h"
 #include "chrome/browser/web_applications/components/web_app_id.h"
-#include "components/content_settings/core/browser/content_settings_observer.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/services/app_service/public/cpp/publisher_base.h"
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -40,8 +38,7 @@
 class WebAppsBase : public apps::PublisherBase,
                     public WebAppPublisherHelper::Delegate,
                     public base::SupportsWeakPtr<WebAppsBase>,
-                    public AppRegistrarObserver,
-                    public content_settings::Observer {
+                    public AppRegistrarObserver {
  public:
   WebAppsBase(const mojo::Remote<apps::mojom::AppService>& app_service,
               Profile* profile);
@@ -54,6 +51,8 @@
  protected:
   const WebApp* GetWebApp(const AppId& app_id) const;
 
+  bool Accepts(const std::string& app_id) const;
+
   // AppRegistrarObserver:
   void OnWebAppInstalled(const AppId& app_id) override;
   void OnWebAppWillBeUninstalled(const AppId& app_id) override;
@@ -108,11 +107,6 @@
   // WebAppPublisherHelper::Delegate overrides.
   void PublishWebApp(apps::mojom::AppPtr app) override;
 
-  // content_settings::Observer overrides.
-  void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
-                               const ContentSettingsPattern& secondary_pattern,
-                               ContentSettingsType content_type) override;
-
   // AppRegistrarObserver:
   void OnWebAppManifestUpdated(const AppId& app_id,
                                base::StringPiece old_name) override;
@@ -127,8 +121,6 @@
   void StartPublishingWebApps(
       mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote);
 
-  virtual bool Accepts(const std::string& app_id) = 0;
-
   mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 
   Profile* const profile_;
@@ -136,9 +128,6 @@
   base::ScopedObservation<AppRegistrar, AppRegistrarObserver>
       registrar_observation_{this};
 
-  base::ScopedObservation<HostContentSettingsMap, content_settings::Observer>
-      content_settings_observation_{this};
-
   WebAppProvider* provider_ = nullptr;
 
   // app_service_ is owned by the object that owns this object.
diff --git a/chrome/browser/web_applications/app_service/web_apps_chromeos.cc b/chrome/browser/web_applications/app_service/web_apps_chromeos.cc
index 974db3b..b1d96d82 100644
--- a/chrome/browser/web_applications/app_service/web_apps_chromeos.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_chromeos.cc
@@ -24,7 +24,6 @@
 #include "chrome/browser/apps/app_service/menu_util.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/arc_web_contents_data.h"
-#include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/badging/badge_manager_factory.h"
 #include "chrome/browser/chromeos/extensions/gfx_utils.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
@@ -673,11 +672,6 @@
   }
 }
 
-bool WebAppsChromeOs::Accepts(const std::string& app_id) {
-  // Crostini Terminal System App is handled by Crostini Apps.
-  return app_id != crostini::kCrostiniTerminalSystemAppId;
-}
-
 apps::mojom::OptionalBool WebAppsChromeOs::ShouldShowBadge(
     const std::string& app_id,
     apps::mojom::OptionalBool has_notification) {
diff --git a/chrome/browser/web_applications/app_service/web_apps_chromeos.h b/chrome/browser/web_applications/app_service/web_apps_chromeos.h
index 0b5cdce9..1c06c4fcf 100644
--- a/chrome/browser/web_applications/app_service/web_apps_chromeos.h
+++ b/chrome/browser/web_applications/app_service/web_apps_chromeos.h
@@ -154,8 +154,6 @@
   // remove the Chrome app badge.
   void ApplyChromeBadge(const std::string& arc_package_name);
 
-  bool Accepts(const std::string& app_id) override;
-
   // Returns whether the app should show a badge.
   apps::mojom::OptionalBool ShouldShowBadge(
       const std::string& app_id,
diff --git a/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc b/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc
index 0f288854..8d2a8089 100644
--- a/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc
@@ -8,7 +8,6 @@
 #include "base/feature_list.h"
 #include "base/one_shot_event.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
-#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app.h"
@@ -62,8 +61,10 @@
       FROM_HERE, base::BindOnce(&WebAppsPublisherHost::OnReady,
                                 weak_ptr_factory_.GetWeakPtr()));
   registrar_observation_.Observe(&registrar());
-  content_settings_observation_.Observe(
-      HostContentSettingsMapFactory::GetForProfile(profile()));
+}
+
+void WebAppsPublisherHost::Shutdown() {
+  publisher_helper().Shutdown();
 }
 
 WebAppRegistrar& WebAppsPublisherHost::registrar() const {
@@ -225,27 +226,6 @@
   PublishWebApp(publisher_helper().ConvertLaunchedWebApp(web_app));
 }
 
-void WebAppsPublisherHost::OnContentSettingChanged(
-    const ContentSettingsPattern& primary_pattern,
-    const ContentSettingsPattern& secondary_pattern,
-    ContentSettingsType content_type) {
-  // If content_type is not one of the supported permissions, do nothing.
-  if (!WebAppPublisherHelper::IsSupportedWebAppPermissionType(content_type)) {
-    return;
-  }
-
-  for (const WebApp& web_app : registrar().GetApps()) {
-    if (primary_pattern.Matches(web_app.start_url())) {
-      apps::mojom::AppPtr app = apps::mojom::App::New();
-      app->app_type = apps::mojom::AppType::kWeb;
-      app->app_id = web_app.app_id();
-      publisher_helper().PopulateWebAppPermissions(&web_app, &app->permissions);
-
-      PublishWebApp(std::move(app));
-    }
-  }
-}
-
 void WebAppsPublisherHost::OnRequestUpdate(
     int render_process_id,
     int render_frame_id,
diff --git a/chrome/browser/web_applications/app_service/web_apps_publisher_host.h b/chrome/browser/web_applications/app_service/web_apps_publisher_host.h
index 7e60613..0ec15372 100644
--- a/chrome/browser/web_applications/app_service/web_apps_publisher_host.h
+++ b/chrome/browser/web_applications/app_service/web_apps_publisher_host.h
@@ -20,14 +20,11 @@
 #include "chrome/browser/web_applications/components/app_registrar_observer.h"
 #include "chrome/browser/web_applications/components/web_app_id.h"
 #include "chromeos/crosapi/mojom/app_service.mojom.h"
-#include "components/content_settings/core/browser/content_settings_observer.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-class ContentSettingsPattern;
 class Profile;
 
 namespace content {
@@ -45,7 +42,6 @@
 class WebAppsPublisherHost : public crosapi::mojom::AppController,
                              public WebAppPublisherHelper::Delegate,
                              public AppRegistrarObserver,
-                             public content_settings::Observer,
                              public MediaCaptureDevicesDispatcher::Observer,
                              public apps::AppWebContentsData::Client {
  public:
@@ -58,6 +54,8 @@
 
   void Init();
 
+  void Shutdown();
+
   Profile* profile() { return profile_; }
   WebAppRegistrar& registrar() const;
 
@@ -118,11 +116,6 @@
       const std::string& app_id,
       const base::Time& last_launch_time) override;
 
-  // content_settings::Observer:
-  void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
-                               const ContentSettingsPattern& secondary_pattern,
-                               ContentSettingsType content_type) override;
-
   // TODO(crbug.com/1194709): Add more overrides, guided by WebAppsChromeOs.
 
   // MediaCaptureDevicesDispatcher::Observer:
@@ -152,9 +145,6 @@
   base::ScopedObservation<AppRegistrar, AppRegistrarObserver>
       registrar_observation_{this};
 
-  base::ScopedObservation<HostContentSettingsMap, content_settings::Observer>
-      content_settings_observation_{this};
-
   base::ScopedObservation<MediaCaptureDevicesDispatcher,
                           MediaCaptureDevicesDispatcher::Observer>
       media_dispatcher_{this};
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index b0fe476b..0f69be95 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -260,13 +260,13 @@
 
       if (!is_official_build) {
         sources += [
-          "$root_gen_dir/ash/ash_file_manager_resources.pak",
+          "$root_gen_dir/ash/content/file_manager/resources/file_manager_swa_resources.pak",
           "$root_gen_dir/chromeos/chromeos_demo_mode_app_resources.pak",
           "$root_gen_dir/chromeos/chromeos_sample_system_web_app_resources.pak",
           "$root_gen_dir/chromeos/chromeos_telemetry_extension_resources.pak",
         ]
         deps += [
-          "//ash/components/resources:file_manager_resources",
+          "//ash/content/file_manager/resources:file_manager_swa_resources",
           "//chromeos/resources:demo_mode_app_resources",
           "//chromeos/resources:sample_system_web_app_resources",
           "//chromeos/resources:telemetry_extension_resources",
diff --git a/chrome/credential_provider/gaiacp/strings/gaia_resources_am.xtb b/chrome/credential_provider/gaiacp/strings/gaia_resources_am.xtb
index 328a3cf..3661308 100644
--- a/chrome/credential_provider/gaiacp/strings/gaia_resources_am.xtb
+++ b/chrome/credential_provider/gaiacp/strings/gaia_resources_am.xtb
@@ -24,7 +24,7 @@
 <translation id="6243062314475217481">የእርስዎ የሥራ መለያ የይለፍ ቃል ለWindows ከሚያስፈልገው የውስብስብነት መስፈርቶች ጋር አይዛመድም። እገዛ ለማግኘት የእርስዎን አስተዳዳሪ ያነጋግሩ።</translation>
 <translation id="6463752215771576050">ይህን ኮምፒውተር ለድርጅት አስተዳደር ማስመዝገብ አልተቻለም።  እባክዎ በተለየ የስራ መለያ ይግቡ።</translation>
 <translation id="6582876473835446261">የWindows ይለፍ ቃል ልክ ያልኾነ ነው። እንደገና ይሞክሩ።</translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6976261330898712570">ይህ መሣሪያ ከድርጅትዎ የመሣሪያ አስተዳደር ጋር አልተመዘገበም። በሥራ መለያዎ ይግቡ።</translation>
 <translation id="7209941495304122410">የ Windows ን የይለፍ ቃል ያስገቡ</translation>
 <translation id="74122330823428762">ይህን መሣሪያ የቆለፈ ተጠቃሚ ብቻ ነው በመለያ መግባት የሚችለው</translation>
diff --git a/chrome/credential_provider/gaiacp/strings/gaia_resources_el.xtb b/chrome/credential_provider/gaiacp/strings/gaia_resources_el.xtb
index 43b5c5b..1af60507 100644
--- a/chrome/credential_provider/gaiacp/strings/gaia_resources_el.xtb
+++ b/chrome/credential_provider/gaiacp/strings/gaia_resources_el.xtb
@@ -24,7 +24,7 @@
 <translation id="6243062314475217481">Ο κωδικός πρόσβασης του λογαριασμού εργασίας δεν συμφωνεί με τις απαιτήσεις πολυπλοκότητας για τα Windows. Επικοινωνήστε με τον διαχειριστή σας για βοήθεια.</translation>
 <translation id="6463752215771576050">Δεν ήταν δυνατή η εγγραφή αυτού του υπολογιστή για διαχείριση επιχειρήσεων.  Συνδεθείτε με έναν άλλο λογαριασμό εργασίας.</translation>
 <translation id="6582876473835446261">Ο κωδικός πρόσβασης των Windows είναι εσφαλμένος. Επανάληψη.</translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6976261330898712570">Αυτή η συσκευή δεν έχει εγγραφεί ακόμη με τη διαχείριση συσκευών του οργανισμού σας. Συνδεθείτε με τον λογαριασμό εργασίας σας.</translation>
 <translation id="7209941495304122410">Εισαγάγετε τον κωδικό πρόσβασης των Windows</translation>
 <translation id="74122330823428762">Μόνο ο χρήστης που έχει κλειδώσει αυτήν τη συσκευή μπορεί να συνδεθεί.</translation>
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index fa3aa17..06a587f 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -178,8 +178,10 @@
                              IDR_TERMINAL_PRIVATE_CUSTOM_BINDINGS_JS);
 
   // IME service on Chrome OS.
-  source_map->RegisterSource("chromeos.ime.mojom.input_engine.mojom",
+  source_map->RegisterSource("chromeos.ime.mojom.ime_service.mojom",
                              IDR_IME_SERVICE_MOJOM_JS);
+  source_map->RegisterSource("chromeos.ime.mojom.input_engine.mojom",
+                             IDR_IME_SERVICE_INPUT_ENGINE_MOJOM_JS);
   source_map->RegisterSource("chromeos.ime.service",
                              IDR_IME_SERVICE_BINDINGS_JS);
 
diff --git a/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js b/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js
index 8874c23..aa2ceca 100644
--- a/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js
+++ b/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js
@@ -9,6 +9,7 @@
 }
 mojo.config.autoLoadMojomDeps = false;
 
+loadScript('chromeos.ime.mojom.ime_service.mojom');
 loadScript('chromeos.ime.mojom.input_engine.mojom');
 
 /**
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index 98bd2f4..facb587 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -67,7 +67,8 @@
 
           <!-- ChromeOS IME Mojo service and bindings. -->
           <include name="IDR_IME_SERVICE_BINDINGS_JS" file="extensions\chromeos_ime_service_bindings.js" type="BINDATA" />
-          <include name="IDR_IME_SERVICE_MOJOM_JS" file="${mojom_root}\chromeos\services\ime\public\mojom\input_engine.mojom.js" use_base_dir="false" type="BINDATA" />
+          <include name="IDR_IME_SERVICE_MOJOM_JS" file="${mojom_root}\chromeos\services\ime\public\mojom\ime_service.mojom.js" use_base_dir="false" type="BINDATA" />
+          <include name="IDR_IME_SERVICE_INPUT_ENGINE_MOJOM_JS" file="${mojom_root}\chromeos\services\ime\public\mojom\input_engine.mojom.js" use_base_dir="false" type="BINDATA" />
 
           <!-- Remote Apps bindings. -->
           <include name="IDR_REMOTE_APPS_BINDINGS_JS" file="extensions\remote_apps\remote_apps_bindings.js" type="BINDATA" />
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index cc5d0b7..bc6b430 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1352,6 +1352,7 @@
       "../browser/component_updater/component_patcher_operation_browsertest.cc",
       "../browser/content_index/content_index_browsertest.cc",
       "../browser/content_settings/content_settings_browsertest.cc",
+      "../browser/content_settings/sound_content_setting_observer_browsertest.cc",
       "../browser/crash_recovery_browsertest.cc",
       "../browser/custom_handlers/protocol_handler_registry_browsertest.cc",
       "../browser/data_saver/data_saver_browsertest.cc",
@@ -1833,6 +1834,7 @@
       "../browser/ui/views/content_test_utils.cc",
       "../browser/ui/views/content_test_utils.h",
       "../browser/ui/views/device_chooser_browsertest.cc",
+      "../browser/ui/views/direct_sockets_connection_bubble_dialog_browsertest.cc",
       "../browser/ui/views/eye_dropper/eye_dropper_browsertest.cc",
       "../browser/ui/views/hats/hats_browsertest.cc",
       "../browser/ui/views/intent_picker_bubble_view_browsertest.cc",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 2087cd8..e1a007a 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -5695,6 +5695,11 @@
 
   "RebootAfterUpdate": {},
 
+  "DeviceScheduledReboot": {
+    "os": ["chromeos"],
+    "test_policy": { "DeviceScheduledReboot": {"reboot_time" : {"hour": 22, "minute": 30}, "frequency": "WEEKLY", "day_of_week": "TUESDAY" }}
+  },
+
   "AttestationEnabledForDevice": {},
 
   "AttestationForContentProtectionEnabled": {},
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn b/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
index 4dd23e6..a06deab 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
@@ -24,6 +24,7 @@
   deps = [
     "../..:chai_assert",
     "//ash/content/shimless_rma/resources:fake_shimless_rma_service",
+    "//ash/content/shimless_rma/resources:shimless_rma_types",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
 }
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
index 0d6b6ea..56cd05b 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
-import {CalibrationComponent, CalibrationObserver, ComponentRepairState, ComponentType, ErrorObserver, HardwareWriteProtectionStateObserver, PowerCableStateObserver, ProvisioningObserver, ProvisioningStep, RmadErrorCode, RmaState, ShimlessRmaServiceInterface} from 'chrome://shimless-rma/shimless_rma_types.js';
+import {CalibrationComponent, CalibrationObserverRemote, ComponentRepairState, ComponentType, ErrorObserverRemote, HardwareWriteProtectionStateObserverRemote, PowerCableStateObserverRemote, ProvisioningObserverRemote, ProvisioningStep, RmadErrorCode, RmaState, ShimlessRmaServiceInterface} from 'chrome://shimless-rma/shimless_rma_types.js';
 
 import {assertDeepEquals, assertEquals, assertGE, assertLE} from '../../chai_assert.js';
 
@@ -696,10 +696,10 @@
   });
 
   test('ObserveError', () => {
-    /** @type {!ErrorObserver} */
-    const errorObserver = /** @type {!ErrorObserver} */ ({
+    /** @type {!ErrorObserverRemote} */
+    const errorObserver = /** @type {!ErrorObserverRemote} */ ({
       /**
-       * Implements ErrorObserver.onError()
+       * Implements ErrorObserverRemote.onError()
        * @param {!RmadErrorCode} error
        */
       onError(error) {
@@ -710,11 +710,11 @@
     return service.triggerErrorObserver(RmadErrorCode.kRequestInvalid, 0);
   });
 
-  test('ObserveCalibrationUpdate', () => {
-    /** @type {!CalibrationObserver} */
-    const calibrationObserver = /** @type {!CalibrationObserver} */ ({
+  test('ObserveCalibrationUpdated', () => {
+    /** @type {!CalibrationObserverRemote} */
+    const calibrationObserver = /** @type {!CalibrationObserverRemote} */ ({
       /**
-       * Implements CalibrationObserver.onCalibrationUpdated()
+       * Implements CalibrationObserverRemote.onCalibrationUpdated()
        * @param {!CalibrationComponent} component
        * @param {number} progress
        */
@@ -723,36 +723,36 @@
         assertEquals(progress, 0.5);
       }
     });
-    service.observeCalibration(calibrationObserver);
+    service.observeCalibrationProgress(calibrationObserver);
     return service.triggerCalibrationObserver(
         CalibrationComponent.kAccelerometer, 0.5, 0);
   });
 
-  test('ObserveProvisioningUpdate', () => {
-    /** @type {!ProvisioningObserver} */
-    const provisioningObserver = /** @type {!ProvisioningObserver} */ ({
+  test('ObserveProvisioningUpdated', () => {
+    /** @type {!ProvisioningObserverRemote} */
+    const provisioningObserver = /** @type {!ProvisioningObserverRemote} */ ({
       /**
-       * Implements ProvisioningObserver.onProvisioningUpdated()
+       * Implements ProvisioningObserverRemote.onProvisioningUpdated()
        * @param {!ProvisioningStep} step
        * @param {number} progress
        */
       onProvisioningUpdated(step, progress) {
-        assertEquals(step, ProvisioningStep.kTwiddleSettings);
+        assertEquals(step, ProvisioningStep.kInProgress);
         assertEquals(progress, 0.25);
       }
     });
-    service.observeProvisioning(provisioningObserver);
+    service.observeProvisioningProgress(provisioningObserver);
     return service.triggerProvisioningObserver(
-        ProvisioningStep.kTwiddleSettings, 0.25, 0);
+        ProvisioningStep.kInProgress, 0.25, 0);
   });
 
   test('ObserveHardwareWriteProtectionStateChange', () => {
-    /** @type {!HardwareWriteProtectionStateObserver} */
+    /** @type {!HardwareWriteProtectionStateObserverRemote} */
     const hardwareWriteProtectionStateObserver =
-        /** @type {!HardwareWriteProtectionStateObserver} */ ({
+        /** @type {!HardwareWriteProtectionStateObserverRemote} */ ({
           /**
            * Implements
-           * HardwareWriteProtectionStateObserver.
+           * HardwareWriteProtectionStateObserverRemote.
            *     onHardwareWriteProtectionStateChanged()
            * @param {boolean} enable
            */
@@ -766,16 +766,17 @@
   });
 
   test('ObservePowerCableStateChange', () => {
-    /** @type {!PowerCableStateObserver} */
-    const powerCableStateObserver = /** @type {!PowerCableStateObserver} */ ({
-      /**
-       * Implements PowerCableStateObserver.onPowerCableStateChanged()
-       * @param {boolean} enable
-       */
-      onPowerCableStateChanged(enable) {
-        assertEquals(enable, true);
-      }
-    });
+    /** @type {!PowerCableStateObserverRemote} */
+    const powerCableStateObserver =
+        /** @type {!PowerCableStateObserverRemote} */ ({
+          /**
+           * Implements PowerCableStateObserverRemote.onPowerCableStateChanged()
+           * @param {boolean} enable
+           */
+          onPowerCableStateChanged(enable) {
+            assertEquals(enable, true);
+          }
+        });
     service.observePowerCableState(powerCableStateObserver);
     return service.triggerPowerCableObserver(true, 0);
   });
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_bg.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_bg.xtb
index 30393d460..c33841ba 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_bg.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_bg.xtb
@@ -38,6 +38,7 @@
 <translation id="3227137524299004712">Микрофон</translation>
 <translation id="3240426699337459095">Връзката е копирана</translation>
 <translation id="3259149966178251584">Разделителна способност на камерата</translation>
+<translation id="3448774564454087943">Видеоклипът не е запазен, тъй като е прекалено кратък</translation>
 <translation id="3517926952904427380">Не може да се направи вертикална снимка</translation>
 <translation id="3569311554794739032">Наистина ли искате да премахнете „<ph name="FILE" />“?</translation>
 <translation id="3733597664308256288">Налице са допълнителни контроли за камерата. За достъп натиснете клавиша „търсене“ + стрелката за надясно.</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_km.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_km.xtb
index 26e04d76..2d023c80 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_km.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_km.xtb
@@ -38,6 +38,7 @@
 <translation id="3227137524299004712">ម៉ៃក្រូហ្វូន</translation>
 <translation id="3240426699337459095">បានចម្លងតំណ</translation>
 <translation id="3259149966178251584">កម្រិតច្បាស់កាមេរ៉ា</translation>
+<translation id="3448774564454087943">វីដេអូមិនត្រូវ​បានរក្សាទុក​ទេ ដោយសារ​វាខ្លីពេក</translation>
 <translation id="3517926952904427380">មិនអាច​ថតរូប​បញ្ឈរ​បានទេ</translation>
 <translation id="3569311554794739032">តើអ្នកពិតជា​ចង់លុប <ph name="FILE" /> មែនឬ?</translation>
 <translation id="3733597664308256288">មាន​ការគ្រប់គ្រង​កាមេរ៉ាបន្ថែម។ Search + ព្រួញទៅ​ស្ដាំ ដើម្បីចូលប្រើ។</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_mn.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_mn.xtb
index 34dfd7b..6f871f8 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_mn.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_mn.xtb
@@ -38,6 +38,7 @@
 <translation id="3227137524299004712">Микрофон</translation>
 <translation id="3240426699337459095">Холбоосыг хуулсан</translation>
 <translation id="3259149966178251584">Камерын нягтрал</translation>
+<translation id="3448774564454087943">Видеог хэт богино байсны улмаас хадгалаагүй</translation>
 <translation id="3517926952904427380">Хөрөг зураг авах боломжгүй байна</translation>
 <translation id="3569311554794739032">Та <ph name="FILE" />-г устгахдаа итгэлтэй байна уу?</translation>
 <translation id="3733597664308256288">Камерын нэмэлт хяналт боломжтой. Хандахын тулд Хайлт + Баруун сумыг дарна уу.</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_my.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_my.xtb
index 4053040..c6c4d561 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_my.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_my.xtb
@@ -38,6 +38,7 @@
 <translation id="3227137524299004712">မိုက်ခရိုဖုန်း</translation>
 <translation id="3240426699337459095">လင့်ခ်ကူးယူပြီးပါပြီ</translation>
 <translation id="3259149966178251584">ကင်မရာ ပုံရိပ်ပြတ်သားကိန်း</translation>
+<translation id="3448774564454087943">ဗီဒီယိုအလွန်တိုသဖြင့် သိမ်းမထားပါ</translation>
 <translation id="3517926952904427380">ထောင်လိုက်ဓာတ်ပုံ ရိုက်၍မရပါ</translation>
 <translation id="3569311554794739032">"<ph name="FILE" />" ကို သင် တကယ် ဖယ်ရှားလိုသလား။</translation>
 <translation id="3733597664308256288">နောက်ထပ် ကင်မရာအထိန်းအချုပ်များ ရနိုင်သည်။ ကြည့်ရန် Search + ‘ညာညွှန်မြား’ နှိပ်ပါ။</translation>
diff --git a/chromeos/components/camera_app_ui/resources/strings/camera_strings_uz.xtb b/chromeos/components/camera_app_ui/resources/strings/camera_strings_uz.xtb
index f0bedb28..bf91af351 100644
--- a/chromeos/components/camera_app_ui/resources/strings/camera_strings_uz.xtb
+++ b/chromeos/components/camera_app_ui/resources/strings/camera_strings_uz.xtb
@@ -38,6 +38,7 @@
 <translation id="3227137524299004712">Mikrofon</translation>
 <translation id="3240426699337459095">Nusxalandi</translation>
 <translation id="3259149966178251584">Kameraning tasviri aniqligi</translation>
+<translation id="3448774564454087943">Video juda qisqaligi uchun saqlanmadi</translation>
 <translation id="3517926952904427380">Portret rejimida suratga olinmadi</translation>
 <translation id="3569311554794739032"><ph name="FILE" /> olib tashlansinmi?</translation>
 <translation id="3733597664308256288">Kamerani tomonlarga burish mumkin. Ochish uchun Search + O'ngga strelka tugmalarini bosing.</translation>
diff --git a/chromeos/crosapi/DEPS b/chromeos/crosapi/DEPS
index 0d28ce94e..19bce7c9 100644
--- a/chromeos/crosapi/DEPS
+++ b/chromeos/crosapi/DEPS
@@ -4,3 +4,9 @@
 include_rules = [
   "+components/services/app_service/public",
 ]
+
+specific_include_rules = {
+  "app_service_types_traits_unittest\.cc": [
+    "+ui/gfx/image/image_unittest_util.h"
+  ]
+}
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index b0c010d..e29dbe1 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -82,6 +82,11 @@
           mojom = "crosapi.mojom.IconType"
           cpp = "::apps::mojom::IconType"
         },
+        {
+          mojom = "crosapi.mojom.IconValue"
+          cpp = "::apps::mojom::IconValuePtr"
+          move_only = true
+        },
       ]
       traits_headers = [
         "//chromeos/crosapi/mojom/app_service_types_mojom_traits.h",
@@ -106,5 +111,6 @@
     "//components/services/app_service/public/mojom:mojom",
     "//mojo/public/cpp/test_support:test_utils",
     "//testing/gtest",
+    "//ui/gfx:test_support",
   ]
 }
diff --git a/chromeos/crosapi/mojom/app_service_types.mojom b/chromeos/crosapi/mojom/app_service_types.mojom
index 905d2fa..d04c461d 100644
--- a/chromeos/crosapi/mojom/app_service_types.mojom
+++ b/chromeos/crosapi/mojom/app_service_types.mojom
@@ -7,6 +7,7 @@
 module crosapi.mojom;
 
 import "mojo/public/mojom/base/time.mojom";
+import "ui/gfx/image/mojom/image.mojom";
 
 // Information about an app. See components/services/app_service/README.md.
 
@@ -226,3 +227,16 @@
   // applied. This is the default suggested icon type.
   kStandard,
 };
+
+// The icon value for each app.
+[Stable]
+struct IconValue {
+  // The icon format and whether it uses Chrome OS mask.
+  IconType icon_type;
+  // The uncompressed icon data in gfx::ImageSkia format.
+  gfx.mojom.ImageSkia? uncompressed;
+  // The compressed icon data in PNG format.
+  array<uint8>? compressed;
+  // Whether this icon data is a placeholder icon.
+  bool is_placeholder_icon;
+};
diff --git a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
index 476e973..281f2d77 100644
--- a/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
+++ b/chromeos/crosapi/mojom/app_service_types_mojom_traits.cc
@@ -594,4 +594,29 @@
   return false;
 }
 
+bool StructTraits<
+    crosapi::mojom::IconValueDataView,
+    apps::mojom::IconValuePtr>::Read(crosapi::mojom::IconValueDataView data,
+                                     apps::mojom::IconValuePtr* out) {
+  apps::mojom::IconType icon_type;
+  if (!data.ReadIconType(&icon_type))
+    return false;
+
+  gfx::ImageSkia uncompressed;
+  if (!data.ReadUncompressed(&uncompressed))
+    return false;
+
+  absl::optional<std::vector<uint8_t>> compressed;
+  if (!data.ReadCompressed(&compressed))
+    return false;
+
+  auto icon_value = apps::mojom::IconValue::New();
+  icon_value->icon_type = icon_type;
+  icon_value->uncompressed = std::move(uncompressed);
+  icon_value->compressed = std::move(compressed);
+  icon_value->is_placeholder_icon = data.is_placeholder_icon();
+  *out = std::move(icon_value);
+  return true;
+}
+
 }  // namespace mojo
diff --git a/chromeos/crosapi/mojom/app_service_types_mojom_traits.h b/chromeos/crosapi/mojom/app_service_types_mojom_traits.h
index 3f388457..5da5b4e 100644
--- a/chromeos/crosapi/mojom/app_service_types_mojom_traits.h
+++ b/chromeos/crosapi/mojom/app_service_types_mojom_traits.h
@@ -278,6 +278,31 @@
                         apps::mojom::IconType* output);
 };
 
+template <>
+struct StructTraits<crosapi::mojom::IconValueDataView,
+                    apps::mojom::IconValuePtr> {
+  static apps::mojom::IconType icon_type(const apps::mojom::IconValuePtr& r) {
+    return r->icon_type;
+  }
+
+  static const gfx::ImageSkia& uncompressed(
+      const apps::mojom::IconValuePtr& r) {
+    return r->uncompressed;
+  }
+
+  static const absl::optional<std::vector<uint8_t>>& compressed(
+      const apps::mojom::IconValuePtr& r) {
+    return r->compressed;
+  }
+
+  static bool is_placeholder_icon(const apps::mojom::IconValuePtr& r) {
+    return r->is_placeholder_icon;
+  }
+
+  static bool Read(crosapi::mojom::IconValueDataView,
+                   apps::mojom::IconValuePtr* out);
+};
+
 }  // namespace mojo
 
 #endif  // CHROMEOS_CROSAPI_MOJOM_APP_SERVICE_TYPES_MOJOM_TRAITS_H_
diff --git a/chromeos/crosapi/mojom/app_service_types_traits_unittest.cc b/chromeos/crosapi/mojom/app_service_types_traits_unittest.cc
index b7ab196..6472fe9 100644
--- a/chromeos/crosapi/mojom/app_service_types_traits_unittest.cc
+++ b/chromeos/crosapi/mojom/app_service_types_traits_unittest.cc
@@ -12,6 +12,7 @@
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/image/image_unittest_util.h"
 
 // Test that every field in apps::mojom::App in correctly converted.
 TEST(AppServiceTypesTraitsTest, RoundTrip) {
@@ -677,3 +678,67 @@
     EXPECT_EQ(output, apps::mojom::IconType::kStandard);
   }
 }
+
+// Test that serialization and deserialization works with icon value.
+TEST(AppServiceTypesTraitsTest, RoundTripIconValue) {
+  {
+    auto input = apps::mojom::IconValue::New();
+    input->icon_type = apps::mojom::IconType::kUnknown;
+
+    std::vector<float> scales;
+    scales.push_back(1.0f);
+    gfx::ImageSkia::SetSupportedScales(scales);
+
+    gfx::ImageSkia image = gfx::test::CreateImageSkia(1, 2);
+    input->uncompressed = image;
+
+    input->compressed = {1u, 2u};
+    input->is_placeholder_icon = true;
+
+    apps::mojom::IconValuePtr output;
+    ASSERT_TRUE(mojo::test::SerializeAndDeserialize<crosapi::mojom::IconValue>(
+        input, output));
+
+    EXPECT_EQ(output->icon_type, apps::mojom::IconType::kUnknown);
+    EXPECT_TRUE(gfx::test::AreImagesEqual(gfx::Image(output->uncompressed),
+                                          gfx::Image(image)));
+    EXPECT_EQ(output->compressed, std::vector<uint8_t>({1u, 2u}));
+    EXPECT_TRUE(output->is_placeholder_icon);
+  }
+  {
+    auto input = apps::mojom::IconValue::New();
+    input->icon_type = apps::mojom::IconType::kUncompressed;
+
+    std::vector<float> scales;
+    scales.push_back(1.0f);
+    gfx::ImageSkia::SetSupportedScales(scales);
+
+    gfx::ImageSkia image = gfx::test::CreateImageSkia(3, 4);
+    input->uncompressed = image;
+    input->is_placeholder_icon = false;
+
+    apps::mojom::IconValuePtr output;
+    ASSERT_TRUE(mojo::test::SerializeAndDeserialize<crosapi::mojom::IconValue>(
+        input, output));
+
+    EXPECT_EQ(output->icon_type, apps::mojom::IconType::kUncompressed);
+    EXPECT_TRUE(gfx::test::AreImagesEqual(gfx::Image(output->uncompressed),
+                                          gfx::Image(image)));
+    EXPECT_FALSE(output->is_placeholder_icon);
+  }
+  {
+    auto input = apps::mojom::IconValue::New();
+    input->icon_type = apps::mojom::IconType::kCompressed;
+
+    input->compressed = {3u, 4u};
+    input->is_placeholder_icon = true;
+
+    apps::mojom::IconValuePtr output;
+    ASSERT_TRUE(mojo::test::SerializeAndDeserialize<crosapi::mojom::IconValue>(
+        input, output));
+
+    EXPECT_EQ(output->icon_type, apps::mojom::IconType::kCompressed);
+    EXPECT_EQ(output->compressed, std::vector<uint8_t>({3u, 4u}));
+    EXPECT_TRUE(output->is_placeholder_icon);
+  }
+}
diff --git a/chromeos/dbus/shill/fake_shill_manager_client.cc b/chromeos/dbus/shill/fake_shill_manager_client.cc
index 3705b22..acb5a70 100644
--- a/chromeos/dbus/shill/fake_shill_manager_client.cc
+++ b/chromeos/dbus/shill/fake_shill_manager_client.cc
@@ -494,7 +494,7 @@
 void FakeShillManagerClient::RemoveDevice(const std::string& device_path) {
   base::Value device_path_value(device_path);
   if (GetListProperty(shill::kDevicesProperty)
-          ->Remove(device_path_value, nullptr)) {
+          ->EraseListValue(device_path_value)) {
     CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
   }
 }
@@ -520,11 +520,11 @@
 void FakeShillManagerClient::RemoveTechnology(const std::string& type) {
   base::Value type_value(type);
   if (GetListProperty(shill::kAvailableTechnologiesProperty)
-          ->Remove(type_value, nullptr)) {
+          ->EraseListValue(type_value)) {
     CallNotifyObserversPropertyChanged(shill::kAvailableTechnologiesProperty);
   }
   if (GetListProperty(shill::kEnabledTechnologiesProperty)
-          ->Remove(type_value, nullptr)) {
+          ->EraseListValue(type_value)) {
     CallNotifyObserversPropertyChanged(shill::kEnabledTechnologiesProperty);
   }
 }
@@ -540,7 +540,7 @@
     }
   } else {
     if (GetListProperty(shill::kUninitializedTechnologiesProperty)
-            ->Remove(base::Value(type), nullptr)) {
+            ->EraseListValue(base::Value(type))) {
       CallNotifyObserversPropertyChanged(
           shill::kUninitializedTechnologiesProperty);
     }
@@ -617,7 +617,7 @@
   VLOG(2) << "RemoveManagerService: " << service_path;
   base::Value service_path_value(service_path);
   GetListProperty(shill::kServiceCompleteListProperty)
-      ->Remove(service_path_value, nullptr);
+      ->EraseListValue(service_path_value);
   CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
 }
 
@@ -1127,7 +1127,7 @@
   if (enabled)
     AppendIfNotPresent(enabled_list, base::Value(type));
   else
-    enabled_list->Remove(base::Value(type), nullptr);
+    enabled_list->EraseListValue(base::Value(type));
   CallNotifyObserversPropertyChanged(shill::kEnabledTechnologiesProperty);
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
   // May affect available services.
diff --git a/chromeos/dbus/shill/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc
index b1308c6..f4f77371 100644
--- a/chromeos/dbus/shill/fake_shill_service_client.cc
+++ b/chromeos/dbus/shill/fake_shill_service_client.cc
@@ -365,22 +365,15 @@
     const dbus::ObjectPath& service_path,
     ListValueCallback callback,
     ErrorCallback error_callback) {
-  base::Value traffic_counters(base::Value::Type::LIST);
-
-  base::Value chrome_dict(base::Value::Type::DICTIONARY);
-  chrome_dict.SetKey("source", base::Value(shill::kTrafficCounterSourceChrome));
-  chrome_dict.SetKey("rx_bytes", base::Value(12));
-  chrome_dict.SetKey("tx_bytes", base::Value(32));
-  traffic_counters.Append(std::move(chrome_dict));
-
-  base::Value user_dict(base::Value::Type::DICTIONARY);
-  user_dict.SetKey("source", base::Value(shill::kTrafficCounterSourceUser));
-  user_dict.SetKey("rx_bytes", base::Value(90));
-  user_dict.SetKey("tx_bytes", base::Value(87));
-  traffic_counters.Append(std::move(user_dict));
-
   std::move(callback).Run(
-      base::Value::AsListValue(std::move(traffic_counters)));
+      base::Value::AsListValue(fake_traffic_counters_.Clone()));
+}
+
+void FakeShillServiceClient::ResetTrafficCounters(
+    const dbus::ObjectPath& service_path,
+    base::OnceClosure callback,
+    ErrorCallback error_callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
 }
 
 ShillServiceClient::TestInterface* FakeShillServiceClient::GetTestInterface() {
@@ -807,4 +800,13 @@
   }
 }
 
+void FakeShillServiceClient::SetFakeTrafficCounters(
+    base::Value fake_traffic_counters) {
+  if (!fake_traffic_counters.is_list()) {
+    LOG(ERROR) << "Fake traffic counters must be a list";
+    return;
+  }
+  fake_traffic_counters_ = std::move(fake_traffic_counters);
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/shill/fake_shill_service_client.h b/chromeos/dbus/shill/fake_shill_service_client.h
index b6fa731..b25bb1c 100644
--- a/chromeos/dbus/shill/fake_shill_service_client.h
+++ b/chromeos/dbus/shill/fake_shill_service_client.h
@@ -76,6 +76,9 @@
   void RequestTrafficCounters(const dbus::ObjectPath& service_path,
                               ListValueCallback callback,
                               ErrorCallback error_callback) override;
+  void ResetTrafficCounters(const dbus::ObjectPath& service_path,
+                            base::OnceClosure callback,
+                            ErrorCallback error_callback) override;
   ShillServiceClient::TestInterface* GetTestInterface() override;
 
   // ShillServiceClient::TestInterface overrides.
@@ -116,6 +119,7 @@
   void SetHoldBackServicePropertyUpdates(bool hold_back) override;
   void SetRequireServiceToGetProperties(
       bool require_service_to_get_properties) override;
+  void SetFakeTrafficCounters(base::Value fake_traffic_counters) override;
 
  private:
   typedef base::ObserverList<ShillPropertyChangedObserver>::Unchecked
@@ -158,6 +162,8 @@
   // unknown service.
   bool require_service_to_get_properties_ = false;
 
+  base::Value fake_traffic_counters_{base::Value::Type::LIST};
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<FakeShillServiceClient> weak_ptr_factory_{this};
diff --git a/chromeos/dbus/shill/shill_service_client.cc b/chromeos/dbus/shill/shill_service_client.cc
index b343ccc0..d50ddbce 100644
--- a/chromeos/dbus/shill/shill_service_client.cc
+++ b/chromeos/dbus/shill/shill_service_client.cc
@@ -224,6 +224,17 @@
             &method_call, std::move(callback), std::move(error_callback));
   }
 
+  void ResetTrafficCounters(const dbus::ObjectPath& service_path,
+                            base::OnceClosure callback,
+                            ErrorCallback error_callback) override {
+    dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
+                                 shill::kResetTrafficCountersFunction);
+
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
+                                          std::move(error_callback));
+  }
+
   ShillServiceClient::TestInterface* GetTestInterface() override {
     return nullptr;
   }
diff --git a/chromeos/dbus/shill/shill_service_client.h b/chromeos/dbus/shill/shill_service_client.h
index 77caac1..9ef99d8 100644
--- a/chromeos/dbus/shill/shill_service_client.h
+++ b/chromeos/dbus/shill/shill_service_client.h
@@ -116,6 +116,9 @@
     virtual void SetRequireServiceToGetProperties(
         bool require_service_to_get_properties) = 0;
 
+    // Sets a fake traffic counters that can be used in tests.
+    virtual void SetFakeTrafficCounters(base::Value fake_traffic_counters) = 0;
+
    protected:
     virtual ~TestInterface() {}
   };
@@ -219,6 +222,12 @@
                                       ListValueCallback callback,
                                       ErrorCallback error_callback) = 0;
 
+  // Calls the ResetTrafficCounters method.
+  // |callback| is called after the method call succeeds.
+  virtual void ResetTrafficCounters(const dbus::ObjectPath& service_path,
+                                    base::OnceClosure callback,
+                                    ErrorCallback error_callback) = 0;
+
   // Returns an interface for testing (stub only), or returns null.
   virtual TestInterface* GetTestInterface() = 0;
 
diff --git a/chromeos/dbus/shill/shill_service_client_unittest.cc b/chromeos/dbus/shill/shill_service_client_unittest.cc
index eb4211b..bc592812 100644
--- a/chromeos/dbus/shill/shill_service_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_service_client_unittest.cc
@@ -330,4 +330,23 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(ShillServiceClientTest, ResetTrafficCounters) {
+  // Create response.
+  std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
+
+  // Set expectations.
+  PrepareForMethodCall(shill::kResetTrafficCountersFunction,
+                       base::BindRepeating(&ExpectNoArgument), response.get());
+  // Call method.
+  base::MockCallback<base::OnceClosure> mock_closure;
+  base::MockCallback<ShillServiceClient::ErrorCallback> mock_error_callback;
+  client_->ResetTrafficCounters(dbus::ObjectPath(kExampleServicePath),
+                                mock_closure.Get(), mock_error_callback.Get());
+  EXPECT_CALL(mock_closure, Run()).Times(1);
+  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
+
+  // Run the message loop.
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/userdataauth/fake_install_attributes_client.h b/chromeos/dbus/userdataauth/fake_install_attributes_client.h
index 58e573c..c18fdeb 100644
--- a/chromeos/dbus/userdataauth/fake_install_attributes_client.h
+++ b/chromeos/dbus/userdataauth/fake_install_attributes_client.h
@@ -121,4 +121,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::FakeInstallAttributesClient;
+}
+
 #endif  // CHROMEOS_DBUS_USERDATAAUTH_FAKE_INSTALL_ATTRIBUTES_CLIENT_H_
diff --git a/chromeos/geolocation/geoposition.h b/chromeos/geolocation/geoposition.h
index 95b0dbbc..048e778d 100644
--- a/chromeos/geolocation/geoposition.h
+++ b/chromeos/geolocation/geoposition.h
@@ -63,4 +63,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::Geoposition;
+}
+
 #endif  // CHROMEOS_GEOLOCATION_GEOPOSITION_H_
diff --git a/chromeos/geolocation/simple_geolocation_provider.h b/chromeos/geolocation/simple_geolocation_provider.h
index fd288b0..160647c 100644
--- a/chromeos/geolocation/simple_geolocation_provider.h
+++ b/chromeos/geolocation/simple_geolocation_provider.h
@@ -87,4 +87,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::SimpleGeolocationProvider;
+}
+
 #endif  // CHROMEOS_GEOLOCATION_SIMPLE_GEOLOCATION_PROVIDER_H_
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc
index bb5eaba3..918298ac 100644
--- a/chromeos/network/shill_property_handler.cc
+++ b/chromeos/network/shill_property_handler.cc
@@ -300,6 +300,35 @@
   NOTREACHED();
 }
 
+void ShillPropertyHandler::RequestTrafficCounters(
+    const std::string& service_path,
+    ShillServiceClient::ListValueCallback callback) {
+  ShillServiceClient::Get()->RequestTrafficCounters(
+      dbus::ObjectPath(service_path),
+      base::BindOnce(
+          [](const std::string* sp, ShillServiceClient::ListValueCallback cb,
+             const base::ListValue& traffic_counters) {
+            NET_LOG(EVENT) << "Received traffic counters for "
+                           << NetworkPathId(*sp);
+            std::move(cb).Run(traffic_counters);
+          },
+          &service_path, std::move(callback)),
+      base::BindOnce(&network_handler::ShillErrorCallbackFunction,
+                     "RequestTrafficCounters Failed", service_path,
+                     network_handler::ErrorCallback()));
+}
+
+void ShillPropertyHandler::ResetTrafficCounters(
+    const std::string& service_path) {
+  NET_LOG(EVENT) << "ResetTrafficCounters: Success";
+
+  ShillServiceClient::Get()->ResetTrafficCounters(
+      dbus::ObjectPath(service_path), base::DoNothing(),
+      base::BindOnce(&network_handler::ShillErrorCallbackFunction,
+                     "ResetTrafficCounters Failed", service_path,
+                     network_handler::ErrorCallback()));
+}
+
 void ShillPropertyHandler::OnPropertyChanged(const std::string& key,
                                              const base::Value& value) {
   ManagerPropertyChanged(key, value);
diff --git a/chromeos/network/shill_property_handler.h b/chromeos/network/shill_property_handler.h
index 9e9ed969..95715ad 100644
--- a/chromeos/network/shill_property_handler.h
+++ b/chromeos/network/shill_property_handler.h
@@ -16,6 +16,7 @@
 #include "base/values.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/shill/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/managed_state.h"
 #include "chromeos/network/network_handler_callbacks.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -157,6 +158,14 @@
   void RequestProperties(ManagedState::ManagedType type,
                          const std::string& path);
 
+  // Requests traffic counters for a Service denoted by |service_path|.
+  // Traffic counters are returned via |callback|.
+  void RequestTrafficCounters(const std::string& service_path,
+                              ShillServiceClient::ListValueCallback callback);
+
+  // Resets traffic counters for a Service denoted by |service_path|.
+  void ResetTrafficCounters(const std::string& service_path);
+
   // ShillPropertyChangedObserver overrides
   void OnPropertyChanged(const std::string& key,
                          const base::Value& value) override;
diff --git a/chromeos/network/shill_property_handler_unittest.cc b/chromeos/network/shill_property_handler_unittest.cc
index d319cc81..808652c 100644
--- a/chromeos/network/shill_property_handler_unittest.cc
+++ b/chromeos/network/shill_property_handler_unittest.cc
@@ -32,6 +32,8 @@
 
 namespace {
 
+const char kStubWiFi1[] = "stub_wifi1";
+
 void ErrorCallbackFunction(const std::string& error_name,
                            const std::string& error_message) {
   LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
@@ -268,7 +270,7 @@
     AddDevice(shill::kTypeCellular, "stub_cellular_device1");
     service_test_->ClearServices();
     AddService(shill::kTypeEthernet, "stub_ethernet", shill::kStateOnline);
-    AddService(shill::kTypeWifi, "stub_wifi1", shill::kStateOnline);
+    AddService(shill::kTypeWifi, kStubWiFi1, shill::kStateOnline);
     AddService(shill::kTypeWifi, "stub_wifi2", shill::kStateIdle);
     AddService(shill::kTypeCellular, "stub_cellular1", shill::kStateIdle);
   }
@@ -579,4 +581,39 @@
       shill_property_handler_->IsTechnologyEnabled(shill::kTypeEthernet));
 }
 
+TEST_F(ShillPropertyHandlerTest, RequestTrafficCounters) {
+  // Set up the traffic counters.
+  base::Value traffic_counters(base::Value::Type::LIST);
+
+  base::Value chrome_dict(base::Value::Type::DICTIONARY);
+  chrome_dict.SetKey("source", base::Value(shill::kTrafficCounterSourceChrome));
+  chrome_dict.SetKey("rx_bytes", base::Value(12));
+  chrome_dict.SetKey("tx_bytes", base::Value(32));
+  traffic_counters.Append(std::move(chrome_dict));
+
+  base::Value user_dict(base::Value::Type::DICTIONARY);
+  user_dict.SetKey("source", base::Value(shill::kTrafficCounterSourceUser));
+  user_dict.SetKey("rx_bytes", base::Value(90));
+  user_dict.SetKey("tx_bytes", base::Value(87));
+  traffic_counters.Append(std::move(user_dict));
+
+  service_test_->SetFakeTrafficCounters(traffic_counters.Clone());
+  ASSERT_TRUE(traffic_counters.is_list());
+
+  base::RunLoop run_loop;
+  shill_property_handler_->RequestTrafficCounters(
+      kStubWiFi1,
+      base::BindOnce(
+          [](base::Value* expected_traffic_counters,
+             base::OnceClosure quit_closure,
+             const base::ListValue& actual_traffic_counters) {
+            EXPECT_EQ(base::Value::AsListValue(*expected_traffic_counters),
+                      actual_traffic_counters);
+            std::move(quit_closure).Run();
+          },
+          &traffic_counters, run_loop.QuitClosure()));
+
+  run_loop.Run();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom b/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
index 6ccc0b8..313fac1 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
+++ b/chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom
@@ -37,6 +37,7 @@
   kSystem,
   kNetwork,
   kAudio,
+  kBootPerformance,
 };
 
 // An enumeration of the different categories of errors that can occur when
@@ -553,6 +554,22 @@
   uint32 severe_underruns;
 };
 
+// Boot performance result.
+union BootPerformanceResult {
+  // Valid BootPerformanceInfo.
+  BootPerformanceInfo boot_performance_info;
+  // The error that occurred attempting to retrieve the BootPerformanceInfo.
+  ProbeError error;
+};
+
+// Boot performance information.
+struct BootPerformanceInfo {
+  // Total time since power on to login screen prompt.
+  double boot_up_seconds;
+  // The timestamp when power on.
+  double boot_up_timestamp;
+};
+
 // A collection of all the device's telemetry information that cros_healthd is
 // capable of reporting. Note that every field in TelemetryInfo is nullable, and
 // the response for a particular ProbeTelemetryInfo request will only contain
@@ -600,4 +617,7 @@
   // Information about the audio devices. Only present when kAudio was included
   // in the categories input to ProbeTelemetryInfo.
   AudioResult? audio_result;
+  // Information about boot performance. Only present when kBootPerformance was
+  // included in the categories input to ProbeTelemetryInfo.
+  BootPerformanceResult? boot_performance_result;
 };
diff --git a/chromeos/services/ime/ime_service.cc b/chromeos/services/ime/ime_service.cc
index 1000749..b266ef5e 100644
--- a/chromeos/services/ime/ime_service.cc
+++ b/chromeos/services/ime/ime_service.cc
@@ -93,13 +93,9 @@
 void ImeService::ConnectToInputMethod(
     const std::string& ime_spec,
     mojo::PendingReceiver<mojom::InputChannel> to_engine,
-    mojo::PendingRemote<mojom::InputChannel> from_engine,
     ConnectToInputMethodCallback callback) {
-  auto rule_based_engine = std::make_unique<InputEngine>();
-  bool bound = rule_based_engine->BindRequest(
-      ime_spec, std::move(to_engine), std::move(from_engine), /*extra=*/{});
-  input_engine_ = std::move(rule_based_engine);
-  std::move(callback).Run(bound);
+  input_engine_ = InputEngine::Create(ime_spec, std::move(to_engine));
+  std::move(callback).Run(/*bound=*/input_engine_ != nullptr);
 }
 
 const char* ImeService::GetImeBundleDir() {
diff --git a/chromeos/services/ime/ime_service.h b/chromeos/services/ime/ime_service.h
index f15a5d64..7aab78e 100644
--- a/chromeos/services/ime/ime_service.h
+++ b/chromeos/services/ime/ime_service.h
@@ -46,7 +46,6 @@
   void ConnectToInputMethod(
       const std::string& ime_spec,
       mojo::PendingReceiver<mojom::InputChannel> to_engine,
-      mojo::PendingRemote<mojom::InputChannel> from_engine,
       ConnectToInputMethodCallback callback) override;
 
   // ImeCrosPlatform overrides:
diff --git a/chromeos/services/ime/ime_service_unittest.cc b/chromeos/services/ime/ime_service_unittest.cc
index 16a26d2..ac54bd70 100644
--- a/chromeos/services/ime/ime_service_unittest.cc
+++ b/chromeos/services/ime/ime_service_unittest.cc
@@ -82,12 +82,10 @@
 
 TEST_F(ImeServiceTest, RuleBasedDoesNotHandleModifierKeys) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:ar", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -112,12 +110,10 @@
 
 TEST_F(ImeServiceTest, RuleBasedDoesNotHandleCtrlShortCut) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:ar", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -142,12 +138,10 @@
 
 TEST_F(ImeServiceTest, RuleBasedDoesNotHandleAltShortCut) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:ar", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -172,12 +166,10 @@
 
 TEST_F(ImeServiceTest, RuleBasedHandlesAltRight) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:ar", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -203,12 +195,10 @@
 // Tests that the rule-based Arabic keyboard can work correctly.
 TEST_F(ImeServiceTest, RuleBasedArabic) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:ar", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -274,12 +264,10 @@
 // Tests that the rule-based DevaPhone keyboard can work correctly.
 TEST_F(ImeServiceTest, RuleBasedDevaPhone) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:deva_phone", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -352,12 +340,10 @@
 // Tests escapable characters. See https://crbug.com/1014384.
 TEST_F(ImeServiceTest, RuleBasedDoesNotEscapeCharacters) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:deva_phone", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
@@ -410,12 +396,10 @@
 // Tests that AltGr works with rule-based. See crbug.com/1035145.
 TEST_F(ImeServiceTest, KhmerKeyboardAltGr) {
   bool success = false;
-  MockInputChannel test_channel;
   mojo::Remote<mojom::InputChannel> to_engine_remote;
 
   remote_manager_->ConnectToInputMethod(
       "m17n:km", to_engine_remote.BindNewPipeAndPassReceiver(),
-      test_channel.CreatePendingRemote(),
       base::BindOnce(&ConnectCallback, &success));
   remote_manager_.FlushForTesting();
   EXPECT_TRUE(success);
diff --git a/chromeos/services/ime/input_engine.cc b/chromeos/services/ime/input_engine.cc
index 13244e5..5536513 100644
--- a/chromeos/services/ime/input_engine.cc
+++ b/chromeos/services/ime/input_engine.cc
@@ -66,34 +66,24 @@
          key_code == "CapsLock";
 }
 
-}  // namespace
-
-InputEngine::InputEngine() : receiver_(this) {}
-
-InputEngine::~InputEngine() = default;
-
-bool InputEngine::BindRequest(
-    const std::string& ime_spec,
-    mojo::PendingReceiver<mojom::InputChannel> receiver,
-    mojo::PendingRemote<mojom::InputChannel> remote,
-    const std::vector<uint8_t>& extra) {
-  if (!IsImeSupportedByRulebased(ime_spec))
-    return false;
-
-  engine_ = std::make_unique<rulebased::Engine>();
-  engine_->Activate(GetIdFromImeSpec(ime_spec));
-
-  receiver_.reset();
-  receiver_.Bind(std::move(receiver));
-
-  return true;
-  // TODO(https://crbug.com/837156): Registry connection error handler.
-}
-
-bool InputEngine::IsImeSupportedByRulebased(const std::string& ime_spec) {
+// Returns whether the given ime_spec is supported by rulebased engine.
+bool IsImeSupportedByRulebased(const std::string& ime_spec) {
   return rulebased::Engine::IsImeSupported(GetIdFromImeSpec(ime_spec));
 }
 
+}  // namespace
+
+std::unique_ptr<InputEngine> InputEngine::Create(
+    const std::string& ime_spec,
+    mojo::PendingReceiver<mojom::InputChannel> receiver) {
+  // InputEngine constructor is private, so have to use WrapUnique here.
+  return IsImeSupportedByRulebased(ime_spec)
+             ? base::WrapUnique(new InputEngine(ime_spec, std::move(receiver)))
+             : nullptr;
+}
+
+InputEngine::~InputEngine() = default;
+
 void InputEngine::ProcessMessage(const std::vector<uint8_t>& message,
                                  ProcessMessageCallback callback) {
   NOTIMPLEMENTED();  // Protobuf message is not used in the rulebased engine.
@@ -216,5 +206,16 @@
   NOTIMPLEMENTED();  // Not used in the rulebased engine.
 }
 
+InputEngine::InputEngine(const std::string& ime_spec,
+                         mojo::PendingReceiver<mojom::InputChannel> receiver)
+    : receiver_(this, std::move(receiver)),
+      engine_(std::make_unique<rulebased::Engine>()) {
+  DCHECK(IsImeSupportedByRulebased(ime_spec));
+
+  engine_->Activate(GetIdFromImeSpec(ime_spec));
+
+  // TODO(https://crbug.com/837156): Registry connection error handler.
+}
+
 }  // namespace ime
 }  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.h b/chromeos/services/ime/input_engine.h
index 4600a39..686ce7a 100644
--- a/chromeos/services/ime/input_engine.h
+++ b/chromeos/services/ime/input_engine.h
@@ -22,17 +22,14 @@
 // TODO(https://crbug.com/1019541): Rename this to RuleBasedEngine.
 class InputEngine : public mojom::InputChannel {
  public:
-  InputEngine();
-  InputEngine(const InputEngine&) = delete;
-  InputEngine& operator=(const InputEngine&) = delete;
-  ~InputEngine() override;
+  // Returns nullptr if |ime_spec| is not valid for this InputEngine.
+  static std::unique_ptr<InputEngine> Create(
+      const std::string& ime_spec,
+      mojo::PendingReceiver<mojom::InputChannel> receiver);
 
-  // Binds the mojom::InputChannel interface to this object and returns true if
-  // the given ime_spec is supported by the engine.
-  bool BindRequest(const std::string& ime_spec,
-                   mojo::PendingReceiver<mojom::InputChannel> receiver,
-                   mojo::PendingRemote<mojom::InputChannel> remote,
-                   const std::vector<uint8_t>& extra);
+  InputEngine(const InputEngine& other) = delete;
+  InputEngine& operator=(const InputEngine& other) = delete;
+  ~InputEngine() override;
 
   // mojom::InputChannel overrides:
   void ProcessMessage(const std::vector<uint8_t>& message,
@@ -68,11 +65,10 @@
 
   // TODO(https://crbug.com/837156): Implement a state for the interface.
 
- protected:
-  // Returns whether the given ime_spec is supported by rulebased engine.
-  bool IsImeSupportedByRulebased(const std::string& ime_spec);
-
  private:
+  InputEngine(const std::string& ime_spec,
+              mojo::PendingReceiver<mojom::InputChannel> receiver);
+
   mojo::Receiver<mojom::InputChannel> receiver_;
   std::unique_ptr<rulebased::Engine> engine_;
 
diff --git a/chromeos/services/ime/public/mojom/ime_service.mojom b/chromeos/services/ime/public/mojom/ime_service.mojom
index fbca777..cbe91de3 100644
--- a/chromeos/services/ime/public/mojom/ime_service.mojom
+++ b/chromeos/services/ime/public/mojom/ime_service.mojom
@@ -36,12 +36,10 @@
 
   // Connects to the native input method identified by |ime_spec|.
   // On success, return |success| as true, and |to_engine| can be used to
-  // interact with the input method. The interface |from_engine| is implemented
-  // on the client and used to receive data sent from the engine.
+  // interact with the input method.
   // On failure (e.g. |ime_spec| is not valid), |success| is false.
   ConnectToInputMethod(string ime_spec,
-                       pending_receiver<InputChannel> to_engine,
-                       pending_remote<InputChannel> from_engine)
+                       pending_receiver<InputChannel> to_engine)
                        => (bool success);
 };
 
diff --git a/chromeos/strings/chromeos_strings_am.xtb b/chromeos/strings/chromeos_strings_am.xtb
index 4094620..433cf3b7 100644
--- a/chromeos/strings/chromeos_strings_am.xtb
+++ b/chromeos/strings/chromeos_strings_am.xtb
@@ -274,7 +274,7 @@
 <translation id="6618744767048954150">በማሄድ ላይ</translation>
 <translation id="6620487321149975369">የህትመት ስራዎች በሰው ካልተወገዱ በቀር በታሪክ ውስጥ ይታያሉ</translation>
 <translation id="6643016212128521049">አጽዳ</translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6704062477274546131">የዲኤንኤስ መፍትሔ</translation>
 <translation id="6747215703636344499">ቆሟል - ውፅዓት ሞልቷል</translation>
 <translation id="6756731097889387912">መቃኘትን መሰረዝ አልተቻለም</translation>
diff --git a/chromeos/strings/chromeos_strings_el.xtb b/chromeos/strings/chromeos_strings_el.xtb
index bcea695a..d1884dc 100644
--- a/chromeos/strings/chromeos_strings_el.xtb
+++ b/chromeos/strings/chromeos_strings_el.xtb
@@ -274,7 +274,7 @@
 <translation id="6618744767048954150">Σε εξέλιξη</translation>
 <translation id="6620487321149975369">Οι εργασίες εκτύπωσης θα εμφανίζονται στο ιστορικό, εκτός εάν καταργηθούν μη αυτόματα.</translation>
 <translation id="6643016212128521049">Διαγραφή</translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6704062477274546131">Επίλυση DNS</translation>
 <translation id="6747215703636344499">Διακοπή - Ο δίσκος εξόδου είναι γεμάτος</translation>
 <translation id="6756731097889387912">Δεν ήταν δυνατή η ακύρωση της σάρωσης.</translation>
diff --git a/chromeos/strings/chromeos_strings_ro.xtb b/chromeos/strings/chromeos_strings_ro.xtb
index b3602dd0..a71a9b8 100644
--- a/chromeos/strings/chromeos_strings_ro.xtb
+++ b/chromeos/strings/chromeos_strings_ro.xtb
@@ -352,7 +352,7 @@
 <translation id="8475690821716466388">Rețeaua Wi-Fi este securizată cu protocolul slab WEP PSK</translation>
 <translation id="8477551185774834963">Latența DNS depășește ușor pragul permisibil</translation>
 <translation id="8483248364096924578">Adresă IP</translation>
-<translation id="8503813439785031346">Nume utilizator</translation>
+<translation id="8503813439785031346">Nume de utilizator</translation>
 <translation id="8503836310948963452">Mai sunt câteva minute…</translation>
 <translation id="8575298406870537639">Operatorul poate solicita această opțiune ca să te conectezi la rețeaua respectivă. Contactează operatorul pentru detalii.</translation>
 <translation id="8576249514688522074">Neinițializată</translation>
diff --git a/chromeos/strings/chromeos_strings_zh-HK.xtb b/chromeos/strings/chromeos_strings_zh-HK.xtb
index 9b29f2c..487c8f2 100644
--- a/chromeos/strings/chromeos_strings_zh-HK.xtb
+++ b/chromeos/strings/chromeos_strings_zh-HK.xtb
@@ -352,7 +352,7 @@
 <translation id="8475690821716466388">已使用防護力較弱的通訊協定 WEP PSK 保護 Wi-Fi 網絡</translation>
 <translation id="8477551185774834963">DNS 延遲時間稍微超過允許的門檻</translation>
 <translation id="8483248364096924578">IP 位址</translation>
-<translation id="8503813439785031346">使用者名稱</translation>
+<translation id="8503813439785031346">用戶名稱</translation>
 <translation id="8503836310948963452">只需多幾分鐘…</translation>
 <translation id="8575298406870537639">流動網絡供應商可能會要求您必須選擇此選項,才能連接他們的網絡。詳情請聯絡流動網絡供應商。</translation>
 <translation id="8576249514688522074">未初始化</translation>
diff --git a/chromeos/system/statistics_provider.h b/chromeos/system/statistics_provider.h
index f8570be..68e42b57 100644
--- a/chromeos/system/statistics_provider.h
+++ b/chromeos/system/statistics_provider.h
@@ -187,7 +187,9 @@
 using ::chromeos::system::kActivateDateKey;
 using ::chromeos::system::kBlockDevModeKey;
 using ::chromeos::system::kCheckEnrollmentKey;
+using ::chromeos::system::kEnterpriseManagementEmbargoEndDateKey;
 using ::chromeos::system::kOemKeyboardDrivenOobeKey;
+using ::chromeos::system::kRlzBrandCodeKey;
 using ::chromeos::system::kSerialNumberKeyForTest;
 using ::chromeos::system::StatisticsProvider;
 }  // namespace system
diff --git a/chromeos/timezone/timezone_provider.h b/chromeos/timezone/timezone_provider.h
index 8a260bd8..edc559e1 100644
--- a/chromeos/timezone/timezone_provider.h
+++ b/chromeos/timezone/timezone_provider.h
@@ -64,4 +64,10 @@
 
 }  // namespace chromeos
 
+// TODO(https://crbug.com/1164001): remove after the //chrome/browser/chromeos
+// source migration is finished.
+namespace ash {
+using ::chromeos::TimeZoneProvider;
+}
+
 #endif  // CHROMEOS_TIMEZONE_TIMEZONE_PROVIDER_H_
diff --git a/chromeos/timezone/timezone_request.h b/chromeos/timezone/timezone_request.h
index e5f27cbb..7972f178 100644
--- a/chromeos/timezone/timezone_request.h
+++ b/chromeos/timezone/timezone_request.h
@@ -136,6 +136,7 @@
 
 // TODO(https://crbug.com/1164001): remove when moved to ash.
 namespace ash {
+using ::chromeos::DefaultTimezoneProviderURL;
 using ::chromeos::TimeZoneResponseData;
 }
 
diff --git a/chromeos/ui/frame/BUILD.gn b/chromeos/ui/frame/BUILD.gn
index 96aea81..fc75919 100644
--- a/chromeos/ui/frame/BUILD.gn
+++ b/chromeos/ui/frame/BUILD.gn
@@ -17,6 +17,8 @@
     "caption_buttons/frame_back_button.h",
     "caption_buttons/frame_caption_button_container_view.cc",
     "caption_buttons/frame_caption_button_container_view.h",
+    "caption_buttons/frame_center_button.cc",
+    "caption_buttons/frame_center_button.h",
     "caption_buttons/frame_size_button.cc",
     "caption_buttons/frame_size_button.h",
     "caption_buttons/frame_size_button_delegate.h",
diff --git a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
index 4a3d988..040115f 100644
--- a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
+++ b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -127,6 +127,7 @@
       case views::CAPTION_BUTTON_ICON_BACK:
       case views::CAPTION_BUTTON_ICON_MENU:
       case views::CAPTION_BUTTON_ICON_ZOOM:
+      case views::CAPTION_BUTTON_ICON_CENTER:
         return false;
       case views::CAPTION_BUTTON_ICON_LOCATION:
         // not used
diff --git a/chromeos/ui/frame/caption_buttons/frame_center_button.cc b/chromeos/ui/frame/caption_buttons/frame_center_button.cc
new file mode 100644
index 0000000..6dd10a3
--- /dev/null
+++ b/chromeos/ui/frame/caption_buttons/frame_center_button.cc
@@ -0,0 +1,191 @@
+// 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 "chromeos/ui/frame/caption_buttons/frame_center_button.h"
+
+#include "chromeos/ui/vector_icons/vector_icons.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/text_constants.h"
+#include "ui/gfx/text_utils.h"
+#include "ui/strings/grit/ui_strings.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/window/caption_button_layout_constants.h"
+#include "ui/views/window/custom_frame_view.h"
+#include "ui/views/window/frame_caption_button.h"
+
+namespace chromeos {
+
+namespace {
+
+// The margin between the contents inside the button if several of them are set.
+constexpr int kMarginBetweenContents = 3;
+
+}  // namespace
+
+FrameCenterButton::FrameCenterButton(PressedCallback callback)
+    : FrameCaptionButton(callback, views::CAPTION_BUTTON_ICON_CENTER, HTMENU) {
+  SetAccessibleName(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CENTER));
+  background_color_changed_subscription_ = AddBackgroundColorChangedCallback(
+      base::BindRepeating(&FrameCenterButton::OnBackgroundColorChanged,
+                          base::Unretained(this)));
+}
+
+FrameCenterButton::~FrameCenterButton() = default;
+
+gfx::Size FrameCenterButton::GetMinimumSize() const {
+  gfx::Size size = GetPreferredSize();
+  // Similar to CalculatePreferredSize(), but allow the text width to be zero.
+  size.set_width((sub_icon_image_
+                      ? icon_image().width() / 2 + kMarginBetweenContents +
+                            sub_icon_image_->width() / 2
+                      : 0) +
+                 views::kCaptionButtonWidth);
+  return size;
+}
+
+void FrameCenterButton::SetSubImage(const gfx::VectorIcon& icon_definition) {
+  gfx::ImageSkia new_icon_image = gfx::CreateVectorIcon(
+      icon_definition, GetButtonColor(GetBackgroundColor()));
+  if (sub_icon_image_ &&
+      new_icon_image.BackedBySameObjectAs(*sub_icon_image_)) {
+    return;
+  }
+  sub_icon_definition_ = &icon_definition;
+  sub_icon_image_ = new_icon_image;
+
+  if (parent())
+    parent()->InvalidateLayout();
+}
+
+void FrameCenterButton::SetText(absl::optional<std::u16string> text) {
+  if (text_ && text_->text() == text)
+    return;
+
+  if (!text) {
+    if (text_)
+      text_.reset();
+    return;
+  }
+
+  if (!text_) {
+    std::unique_ptr<gfx::RenderText> render_text =
+        gfx::RenderText::CreateRenderText();
+    render_text->SetFontList(views::CustomFrameView::GetWindowTitleFontList());
+    render_text->SetColor(GetButtonColor(GetBackgroundColor()));
+    render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+    render_text->SetVerticalAlignment(gfx::ALIGN_MIDDLE);
+    text_ = std::move(render_text);
+  }
+  text_->SetText(*text);
+
+  if (parent())
+    parent()->InvalidateLayout();
+}
+
+// |--------------[FrameCaptionButton width]--------------|
+// | (i) |  (ii)  | (iii)  | (iv) |  (v)   | (vi) | (vii) |
+// | primary icon | margin | text | margin |   sub icon   |
+//
+// (i) The left semicircle (views::kCaptionButtonWidth / 2)
+// (ii) The right semicircle of the primary icon (icon_image().width() / 2)
+// (iii) The margin between the primary icon and the text if set
+//       (kMarginBetweenContents)
+// (iv) The text if set (text_->GetStringSize().width())
+// (v) The margin between the text and the sub icon (kMarginBetweenContents)
+// (vi) The left semicircle of the sub icon (sub_icon_image_->width() / 2)
+// (vii) The right semicircle of the sub icon (views::kCaptionButtonWidth / 2)
+gfx::Size FrameCenterButton::CalculatePreferredSize() const {
+  gfx::Size size = views::View::CalculatePreferredSize();
+
+  size.set_width(
+      (text_ || sub_icon_image_ ? icon_image().width() / 2 : 0) +
+      (text_ ? kMarginBetweenContents + text_->GetStringSize().width() : 0) +
+      (sub_icon_image_ ? kMarginBetweenContents + sub_icon_image_->width() / 2
+                       : 0) +
+      views::kCaptionButtonWidth);
+  return size;
+}
+
+void FrameCenterButton::DrawHighlight(gfx::Canvas* canvas,
+                                      cc::PaintFlags flags) {
+  const gfx::Size ink_drop_size = GetInkDropSize();
+  int centered_origin_x = (width() - ink_drop_size.width()) / 2;
+  int centered_origin_y = (height() - ink_drop_size.height()) / 2;
+  canvas->DrawRoundRect(
+      gfx::Rect(centered_origin_x, centered_origin_y, ink_drop_size.width(),
+                ink_drop_size.height()),
+      GetInkDropCornerRadius(), flags);
+}
+
+void FrameCenterButton::DrawIconContents(gfx::Canvas* canvas,
+                                         gfx::ImageSkia image,
+                                         int x,
+                                         int y,
+                                         cc::PaintFlags flags) {
+  int full_content_width =
+      icon_image().width() +
+      (text_ ? kMarginBetweenContents + text_->GetStringSize().width() : 0) +
+      (sub_icon_image_ ? kMarginBetweenContents + sub_icon_image_->width() : 0);
+  // The width available is basically the same as width(), but we need to
+  // adjust the corner radius on both sides from views::kCaptionButtonWidth to
+  // the actual content radius.
+  int available_content_width = width() - views::kCaptionButtonWidth +
+                                icon_image().width() / 2 +
+                                (sub_icon_image_ ? sub_icon_image_->width() / 2
+                                                 : icon_image().width() / 2);
+  int content_width = std::min(full_content_width, available_content_width);
+  int current_offset = (width() - content_width) / 2;
+
+  canvas->DrawImageInt(icon_image(), current_offset, y, flags);
+  current_offset += icon_image().width() + kMarginBetweenContents;
+
+  if (text_) {
+    int available_text_width =
+        content_width - icon_image().width() - kMarginBetweenContents -
+        (sub_icon_image_ ? kMarginBetweenContents + sub_icon_image_->width()
+                         : 0);
+    gfx::Rect text_bounds = gfx::Rect(
+        current_offset, (height() - text_->GetStringSize().height()) / 2,
+        std::min(text_->GetStringSize().width(), available_text_width),
+        text_->GetStringSize().height());
+    text_->SetDisplayRect(text_bounds);
+    text_->Draw(canvas);
+    current_offset += text_bounds.width() + kMarginBetweenContents;
+  }
+
+  if (sub_icon_image_) {
+    canvas->DrawImageInt(*sub_icon_image_, current_offset,
+                         (height() - sub_icon_image_->height()) / 2, flags);
+  }
+}
+
+// The width calculated here is the same as that of CalculatePreferredSize()
+// except that |ink_drop_corner_radius_| is used instead of
+// |views::kCaptionButtonWidth|.
+// See CalculatePreferredSize() for more details.
+gfx::Size FrameCenterButton::GetInkDropSize() const {
+  int full_width = 2 * GetInkDropCornerRadius();
+  if (text_ || sub_icon_image_)
+    full_width += icon_image().width() / 2;
+  if (text_)
+    full_width += kMarginBetweenContents + text_->GetStringSize().width();
+  if (sub_icon_image_)
+    full_width += kMarginBetweenContents + sub_icon_image_->width() / 2;
+  return gfx::Size(std::min(full_width, width()), 2 * GetInkDropCornerRadius());
+}
+
+void FrameCenterButton::OnBackgroundColorChanged() {
+  if (sub_icon_definition_)
+    SetSubImage(*sub_icon_definition_);
+  if (text_)
+    text_->SetColor(GetButtonColor(GetBackgroundColor()));
+}
+
+}  // namespace chromeos
diff --git a/chromeos/ui/frame/caption_buttons/frame_center_button.h b/chromeos/ui/frame/caption_buttons/frame_center_button.h
new file mode 100644
index 0000000..1d5ba47
--- /dev/null
+++ b/chromeos/ui/frame/caption_buttons/frame_center_button.h
@@ -0,0 +1,71 @@
+// 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 CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_CENTER_BUTTON_H_
+#define CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_CENTER_BUTTON_H_
+
+#include "base/component_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/render_text.h"
+#include "ui/views/window/frame_caption_button.h"
+
+namespace chromeos {
+
+// A button to be shown at the center of the caption. The client of this class
+// is responsible for managing the instance of this class, setting the primary
+// image, and optionally setting a text and sub image.
+class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) FrameCenterButton
+    : public views::FrameCaptionButton {
+ public:
+  FrameCenterButton(PressedCallback callback);
+  FrameCenterButton(const FrameCenterButton&) = delete;
+  FrameCenterButton& operator=(const FrameCenterButton&) = delete;
+  ~FrameCenterButton() override;
+
+  // views::View override:
+  gfx::Size GetMinimumSize() const override;
+
+  // Set the text to be painted next to the main icon. The text must be short
+  // enough to fit the caption. Otherwise, the button wouldn't be drawn
+  // properly.
+  void SetText(absl::optional<std::u16string> text);
+  // Set the sub image to be painted next to the main icon and text.
+  void SetSubImage(const gfx::VectorIcon& icon_image);
+
+ protected:
+  // views::View override:
+  // Unlike other caption buttons, the size should be calculated dynamically as
+  // this class may have an optional text and sub image.
+  gfx::Size CalculatePreferredSize() const override;
+
+  // views::FrameCaptionButton override:
+  void DrawHighlight(gfx::Canvas* canvas, cc::PaintFlags flags) override;
+  void DrawIconContents(gfx::Canvas* canvas,
+                        gfx::ImageSkia image,
+                        int x,
+                        int y,
+                        cc::PaintFlags flags) override;
+  // Returns the size of the inkdrop ripple. If the extra text and sub image
+  // aren't set, it's simply the size of a circle with the radius of
+  // |ink_drop_corner_radius_|.
+  gfx::Size GetInkDropSize() const override;
+
+ private:
+  void OnBackgroundColorChanged();
+
+  // The extra text shown in the button if set.
+  std::unique_ptr<gfx::RenderText> text_;
+
+  // The image id and image used to paint the sub icon if set.
+  absl::optional<gfx::ImageSkia> sub_icon_image_;
+  const gfx::VectorIcon* sub_icon_definition_ = nullptr;
+
+  // Used to update the color of the optional contents when the background
+  // color is updated.
+  base::CallbackListSubscription background_color_changed_subscription_;
+};
+
+}  // namespace chromeos
+
+#endif  //  CHROMEOS_UI_FRAME_CAPTION_BUTTONS_FRAME_CENTER_BUTTON_H_
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
index 6c08be3..d0fdcf4a 100644
--- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc
+++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -56,6 +56,7 @@
       case views::CAPTION_BUTTON_ICON_LOCATION:
       case views::CAPTION_BUTTON_ICON_MENU:
       case views::CAPTION_BUTTON_ICON_ZOOM:
+      case views::CAPTION_BUTTON_ICON_CENTER:
       case views::CAPTION_BUTTON_ICON_COUNT:
         NOTREACHED();
         break;
diff --git a/chromeos/ui/frame/frame_header.cc b/chromeos/ui/frame/frame_header.cc
index bd3b52e2..cda4c8d0 100644
--- a/chromeos/ui/frame/frame_header.cc
+++ b/chromeos/ui/frame/frame_header.cc
@@ -191,7 +191,8 @@
   // Ensure we have enough space for the window icon and buttons. We allow
   // the title string to collapse to zero width.
   return GetTitleBounds().x() +
-         caption_button_container_->GetMinimumSize().width();
+         caption_button_container_->GetMinimumSize().width() +
+         (GetCenterButton() ? GetCenterButton()->GetMinimumSize().width() : 0);
 }
 
 void FrameHeader::PaintHeader(gfx::Canvas* canvas) {
@@ -238,6 +239,8 @@
   caption_button_container_->SetPaintAsActive(paint_as_active);
   if (back_button_)
     back_button_->SetPaintAsActive(paint_as_active);
+  if (center_button_)
+    center_button_->SetPaintAsActive(paint_as_active);
   UpdateCaptionButtonColors();
 }
 
@@ -262,10 +265,20 @@
   }
 }
 
+void FrameHeader::SetCenterButton(chromeos::FrameCenterButton* center_button) {
+  center_button_ = center_button;
+  if (center_button_)
+    center_button_->SetBackgroundColor(GetCurrentFrameColor());
+}
+
 views::FrameCaptionButton* FrameHeader::GetBackButton() const {
   return back_button_;
 }
 
+chromeos::FrameCenterButton* FrameHeader::GetCenterButton() const {
+  return center_button_;
+}
+
 const chromeos::CaptionButtonModel* FrameHeader::GetCaptionButtonModel() const {
   return caption_button_container_->model();
 }
@@ -304,6 +317,8 @@
   caption_button_container_->SetBackgroundColor(frame_color);
   if (back_button_)
     back_button_->SetBackgroundColor(frame_color);
+  if (center_button_)
+    center_button_->SetBackgroundColor(frame_color);
 }
 
 void FrameHeader::PaintTitleBar(gfx::Canvas* canvas) {
@@ -404,6 +419,19 @@
     constexpr int kLeftViewXInset = 9;
     left_header_view_->SetBounds(kLeftViewXInset + origin, icon_offset_y,
                                  icon_size.width(), icon_size.height());
+    origin = left_header_view_->bounds().right();
+  }
+
+  if (center_button_) {
+    constexpr int kCenterButtonSpacing = 5;
+    int full_width = center_button_->GetPreferredSize().width();
+    const gfx::Range range(
+        std::max((view_->width() - full_width) / 2,
+                 origin + kCenterButtonSpacing),
+        std::min((view_->width() + full_width) / 2,
+                 caption_button_container_->x() - kCenterButtonSpacing));
+    center_button_->SetBounds(range.start(), 0, range.end() - range.start(),
+                              caption_button_container_size.height());
   }
 }
 
diff --git a/chromeos/ui/frame/frame_header.h b/chromeos/ui/frame/frame_header.h
index f868723d..d144166 100644
--- a/chromeos/ui/frame/frame_header.h
+++ b/chromeos/ui/frame/frame_header.h
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/component_export.h"
 #include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "chromeos/ui/frame/caption_buttons/frame_center_button.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_types.h"
@@ -121,7 +122,9 @@
 
   void SetLeftHeaderView(views::View* view);
   void SetBackButton(views::FrameCaptionButton* view);
+  void SetCenterButton(chromeos::FrameCenterButton* view);
   views::FrameCaptionButton* GetBackButton() const;
+  chromeos::FrameCenterButton* GetCenterButton() const;
   const chromeos::CaptionButtonModel* GetCaptionButtonModel() const;
 
   // Updates the frame header painting to reflect a change in frame colors.
@@ -191,6 +194,7 @@
   chromeos::FrameCaptionButtonContainerView* caption_button_container_ =
       nullptr;
   FrameAnimatorView* frame_animator_ = nullptr;  // owned by view tree.
+  chromeos::FrameCenterButton* center_button_ = nullptr;  // May remain nullptr.
 
   // The height of the header to paint.
   int painted_height_ = 0;
diff --git a/components/arc/compat_mode/arc_resize_lock_manager.cc b/components/arc/compat_mode/arc_resize_lock_manager.cc
index 1ca4aef..0e31eba 100644
--- a/components/arc/compat_mode/arc_resize_lock_manager.cc
+++ b/components/arc/compat_mode/arc_resize_lock_manager.cc
@@ -67,16 +67,24 @@
 void ArcResizeLockManager::OnWindowPropertyChanged(aura::Window* window,
                                                    const void* key,
                                                    intptr_t old) {
-  if (key != ash::kArcResizeLockKey)
+  if (key != ash::kArcResizeLockKey && key != ash::kAppIDKey)
     return;
 
-  const bool current_value = window->GetProperty(ash::kArcResizeLockKey);
-  if (current_value == static_cast<bool>(old))
-    return;
+  const bool current_resize_lock_value =
+      window->GetProperty(ash::kArcResizeLockKey);
+  const bool resize_lock_changed =
+      (key == ash::kArcResizeLockKey &&
+       current_resize_lock_value != static_cast<bool>(old));
+  const bool has_app_id = window->GetProperty(ash::kAppIDKey) != nullptr;
+  const bool app_id_changed = key == ash::kAppIDKey;
 
-  if (current_value)
+  // Both the resize lock value and app id are needed to enable resize lock.
+  if (has_app_id && current_resize_lock_value &&
+      (app_id_changed || resize_lock_changed)) {
     EnableResizeLock(window);
-  else
+  }
+
+  if (resize_lock_changed && !current_resize_lock_value)
     DisableResizeLock(window);
 }
 
diff --git a/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc b/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
index e6f0725..361fcb3 100644
--- a/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
+++ b/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
@@ -85,6 +85,10 @@
 
   EXPECT_FALSE(IsResizeLockEnabled(arc_window));
 
+  // App id needs to be set to toogle resize lock state.
+  arc_window->SetProperty(ash::kAppIDKey, new std::string("app-id"));
+  EXPECT_FALSE(IsResizeLockEnabled(arc_window));
+
   // Test EnableResizeLock will be called by the property change.
   arc_window->SetProperty(ash::kArcResizeLockKey, true);
   EXPECT_TRUE(IsResizeLockEnabled(arc_window));
diff --git a/components/arc/compat_mode/resize_toggle_menu.cc b/components/arc/compat_mode/resize_toggle_menu.cc
index fa07fed2..6c3f4036 100644
--- a/components/arc/compat_mode/resize_toggle_menu.cc
+++ b/components/arc/compat_mode/resize_toggle_menu.cc
@@ -4,15 +4,23 @@
 
 #include "components/arc/compat_mode/resize_toggle_menu.h"
 
-#include <memory>
-
 #include "ash/resources/vector_icons/vector_icons.h"
+#include "base/bind.h"
 #include "base/notreached.h"
 #include "components/arc/compat_mode/resize_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/text_constants.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_provider.h"
+#include "ui/views/style/platform_style.h"
 #include "ui/views/widget/widget.h"
 
 namespace arc {
@@ -35,69 +43,187 @@
   return absl::nullopt;
 }
 
+class MenuButtonView : public views::Button {
+ public:
+  static constexpr int kBorderThicknessDp = 1;
+
+  MenuButtonView(PressedCallback callback,
+                 const gfx::VectorIcon& icon,
+                 int title_string_id,
+                 bool is_selected)
+      : views::Button(std::move(callback)),
+        icon_(icon),
+        is_selected_(is_selected) {
+    if (is_selected_)
+      SetState(views::Button::ButtonState::STATE_DISABLED);
+
+    AddChildView(
+        views::Builder<views::ImageView>().CopyAddressTo(&icon_view_).Build());
+    AddChildView(views::Builder<views::Label>()
+                     .CopyAddressTo(&title_)
+                     .SetBackgroundColor(SK_ColorTRANSPARENT)
+                     .SetText(l10n_util::GetStringUTF16(title_string_id))
+                     .SetVerticalAlignment(gfx::ALIGN_BOTTOM)
+                     .SetLineHeight(20)
+                     .SetMultiLine(true)
+                     .SetMaxLines(2)
+                     .Build());
+    SetBorder(views::CreateEmptyBorder(gfx::Insets(kBorderThicknessDp)));
+    SetPreferredSize(gfx::Size(96, 86));
+  }
+  MenuButtonView(const MenuButtonView&) = delete;
+  MenuButtonView& operator=(const MenuButtonView&) = delete;
+  ~MenuButtonView() override = default;
+
+ private:
+  void Layout() override {
+    constexpr int kIconSize = 24;
+    constexpr int kIconTopPadding = 17;
+
+    gfx::Rect content_bounds_with_padding = GetContentsBounds();
+    content_bounds_with_padding.Inset(gfx::Insets(kIconTopPadding, 0));
+
+    gfx::Rect icon_rect(GetContentsBounds());
+    icon_rect.ClampToCenteredSize(gfx::Size(kIconSize, kIconSize));
+    icon_rect.set_y(content_bounds_with_padding.y());
+    icon_view_->SetBoundsRect(icon_rect);
+    title_->SetBoundsRect(content_bounds_with_padding);
+  }
+
+  void OnFocus() override { SchedulePaint(); }
+
+  void OnBlur() override { SchedulePaint(); }
+
+  void OnThemeChanged() override {
+    views::Button::OnThemeChanged();
+    const auto color = GetNativeTheme()->GetSystemColor(
+        is_selected_ ? ui::NativeTheme::kColorId_ProminentButtonColor
+                     : ui::NativeTheme::kColorId_LabelEnabledColor);
+    icon_view_->SetImage(gfx::CreateVectorIcon(icon_, color));
+    title_->SetEnabledColor(color);
+  }
+
+  void PaintButtonContents(gfx::Canvas* canvas) override {
+    auto* const provider = views::LayoutProvider::Get();
+    const int round_radius =
+        provider->GetCornerRadiusMetric(views::Emphasis::kHigh);
+
+    const gfx::Rect content_bounds = GetContentsBounds();
+    cc::PaintFlags flags;
+    flags.setAntiAlias(true);
+    if (is_selected_) {
+      flags.setColor(GetNativeTheme()->GetSystemColor(
+          ui::NativeTheme::kColorId_MenuItemTargetAlertBackgroundColor));
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      canvas->DrawRoundRect(content_bounds, round_radius, flags);
+    } else {
+      flags.setColor(SK_ColorTRANSPARENT);
+      flags.setStyle(cc::PaintFlags::kFill_Style);
+      canvas->DrawRoundRect(content_bounds, round_radius, flags);
+
+      flags.setColor(GetNativeTheme()->GetSystemColor(
+          ui::NativeTheme::kColorId_MenuBorderColor));
+      flags.setStrokeWidth(kBorderThicknessDp);
+      flags.setStyle(cc::PaintFlags::Style::kStroke_Style);
+      canvas->DrawRoundRect(content_bounds, round_radius, flags);
+    }
+  }
+
+  // Owned by views hierarchy.
+  views::ImageView* icon_view_{nullptr};
+  views::Label* title_{nullptr};
+
+  const gfx::VectorIcon& icon_;
+  const bool is_selected_;
+};
+
+class RoundedCornerBubbleDialogDelegateView
+    : public views::BubbleDialogDelegateView {
+ public:
+  explicit RoundedCornerBubbleDialogDelegateView(int corner_radius)
+      : corner_radius_(corner_radius) {}
+
+  // views::View:
+  void AddedToWidget() override {
+    auto* const frame = GetBubbleFrameView();
+    if (frame)
+      frame->SetCornerRadius(corner_radius_);
+  }
+
+ private:
+  const int corner_radius_;
+};
+
 }  // namespace
 
 ResizeToggleMenu::ResizeToggleMenu(views::Widget* widget,
                                    ArcResizeLockPrefDelegate* pref_delegate)
     : widget_(widget), pref_delegate_(pref_delegate) {
-  model_ = MakeMenuModel();
-  adapter_ = std::make_unique<views::MenuModelAdapter>(model_.get());
-  root_view_ = adapter_->CreateMenu();
-
-  const auto currentMode = PredictCurrentMode(widget_);
-  if (currentMode) {
-    auto* item = root_view_->GetMenuItemByID(*currentMode);
-    item->SetSelected(true);
-    item->SetMinorIcon(ui::ImageModel::FromVectorIcon(
-        ash::kHollowCheckCircleIcon,
-        ui::NativeTheme::kColorId_ProminentButtonColor));
-  }
-
-  menu_runner_ = std::make_unique<views::MenuRunner>(
-      root_view_, views::MenuRunner::CONTEXT_MENU |
-                      views::MenuRunner::USE_TOUCHABLE_LAYOUT |
-                      views::MenuRunner::FIXED_ANCHOR);
-
   const gfx::Rect client_view_rect =
       widget_->client_view()->GetBoundsInScreen();
-  // Anchored to the right edge of the client_view.
+  // Anchored to the top edge of the client_view with padding.
+  constexpr auto kMarginTopDp = 8;
   const gfx::Rect anchor_rect =
-      gfx::Rect(client_view_rect.right(), client_view_rect.y(), 0,
-                client_view_rect.height());
-  menu_runner_->RunMenuAt(
-      /*widget_owner=*/widget_, /*menu_button_controller=*/nullptr, anchor_rect,
-      views::MenuAnchorPosition::kBubbleLeft, ui::MENU_SOURCE_MOUSE);
+      gfx::Rect(client_view_rect.x(), client_view_rect.y() + kMarginTopDp,
+                client_view_rect.width(), 0);
+
+  bubble_widget_ =
+      views::BubbleDialogDelegateView::CreateBubble(MakeBubbleDelegateView(
+          widget_, anchor_rect,
+          base::BindRepeating(&ResizeToggleMenu::ExecuteCommand,
+                              base::Unretained(this))));
+  bubble_widget_->Show();
 }
 
-ResizeToggleMenu::~ResizeToggleMenu() {
-  menu_runner_->Cancel();
+ResizeToggleMenu::~ResizeToggleMenu() = default;
+
+std::unique_ptr<views::BubbleDialogDelegateView>
+ResizeToggleMenu::MakeBubbleDelegateView(
+    views::Widget* parent,
+    gfx::Rect anchor_rect,
+    base::RepeatingCallback<void(CommandId)> command_handler) {
+  constexpr int kCornerRadius = 16;
+
+  auto delegate_view =
+      std::make_unique<RoundedCornerBubbleDialogDelegateView>(kCornerRadius);
+
+  // Setup delegate.
+  delegate_view->SetArrow(views::BubbleBorder::Arrow::TOP_CENTER);
+  delegate_view->SetButtons(ui::DIALOG_BUTTON_NONE);
+  delegate_view->set_parent_window(parent->GetNativeView());
+  delegate_view->set_title_margins(gfx::Insets());
+  delegate_view->set_margins(gfx::Insets());
+  delegate_view->SetAnchorRect(anchor_rect);
+
+  // Setup view.
+  auto* const provider = views::LayoutProvider::Get();
+  delegate_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kHorizontal,
+      provider->GetInsetsMetric(views::INSETS_DIALOG),
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL)));
+
+  const auto selected_mode = PredictCurrentMode(widget_);
+  const auto add_menu_button =
+      [&delegate_view, &command_handler, &selected_mode](
+          CommandId command_id, const gfx::VectorIcon& icon, int string_id) {
+        return delegate_view->AddChildView(std::make_unique<MenuButtonView>(
+            base::BindRepeating(command_handler, command_id), icon, string_id,
+            selected_mode && *selected_mode == command_id));
+      };
+  phone_button_ =
+      add_menu_button(CommandId::kResizePhone, ash::kSystemMenuPhoneIcon,
+                      IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE);
+  tablet_button_ =
+      add_menu_button(CommandId::kResizeTablet, ash::kSystemMenuTabletIcon,
+                      IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET);
+  desktop_button_ =
+      add_menu_button(CommandId::kResizeDesktop, ash::kSystemMenuComputerIcon,
+                      IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP);
+
+  return delegate_view;
 }
 
-std::unique_ptr<ui::SimpleMenuModel> ResizeToggleMenu::MakeMenuModel() {
-  auto model = std::make_unique<ui::SimpleMenuModel>(this);
-
-  model->AddItemWithStringIdAndIcon(
-      CommandId::kResizePhone, IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE,
-      ui::ImageModel::FromVectorIcon(ash::kSystemMenuPhoneIcon));
-
-  model->AddItemWithStringIdAndIcon(
-      CommandId::kResizeTablet, IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET,
-      ui::ImageModel::FromVectorIcon(ash::kSystemMenuTabletIcon));
-
-  model->AddItemWithStringIdAndIcon(
-      CommandId::kResizeDesktop, IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP,
-      ui::ImageModel::FromVectorIcon(ash::kSystemMenuComputerIcon));
-
-  model->AddSeparator(ui::NORMAL_SEPARATOR);
-
-  model->AddItemWithStringIdAndIcon(
-      CommandId::kOpenSettings,
-      IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS,
-      ui::ImageModel::FromVectorIcon(ash::kSystemMenuSettingsIcon));
-  return model;
-}
-
-void ResizeToggleMenu::ExecuteCommand(int command_id, int event_flags) {
+void ResizeToggleMenu::ExecuteCommand(CommandId command_id) {
   switch (command_id) {
     case CommandId::kResizePhone:
       ResizeToPhoneWithConfirmationIfNeeded(widget_, pref_delegate_);
@@ -112,9 +238,6 @@
       // TODO(b/181614585): Implement this.
       NOTIMPLEMENTED();
       break;
-    default:
-      NOTREACHED();
-      break;
   }
 }
 
diff --git a/components/arc/compat_mode/resize_toggle_menu.h b/components/arc/compat_mode/resize_toggle_menu.h
index 463cf48..50b0b8a 100644
--- a/components/arc/compat_mode/resize_toggle_menu.h
+++ b/components/arc/compat_mode/resize_toggle_menu.h
@@ -5,54 +5,58 @@
 #ifndef COMPONENTS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_H_
 #define COMPONENTS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_H_
 
-#include "ui/base/models/menu_model_delegate.h"
-#include "ui/base/models/simple_menu_model.h"
-#include "ui/views/controls/menu/menu_model_adapter.h"
+#include <memory>
+
+#include "base/callback_forward.h"
+
+namespace gfx {
+class Rect;
+}  // namespace gfx
 
 namespace views {
+class BubbleDialogDelegateView;
+class Button;
 class Widget;
-class MenuItemView;
 }  // namespace views
 
 namespace arc {
 
 class ArcResizeLockPrefDelegate;
 
-class ResizeToggleMenu : public ui::SimpleMenuModel::Delegate {
+class ResizeToggleMenu {
  public:
-  enum CommandId {
-    kResizePhone = 1,  // Starting from 1 to avoid the conflict with "separator
-                       // item" because its command id is 0.
-    kResizeTablet = 2,
-    kResizeDesktop = 3,
-    kOpenSettings = 4,
-    kMaxValue = kOpenSettings,
+  enum class CommandId {
+    kResizePhone,
+    kResizeTablet,
+    kResizeDesktop,
+    kOpenSettings,
   };
 
   ResizeToggleMenu(views::Widget* widget,
                    ArcResizeLockPrefDelegate* pref_delegate);
   ResizeToggleMenu(const ResizeToggleMenu&) = delete;
   ResizeToggleMenu& operator=(const ResizeToggleMenu&) = delete;
-  ~ResizeToggleMenu() override;
-
-  // ui::SimpleMenuModel::Delegate:
-  void ExecuteCommand(int command_id, int event_flags) override;
+  ~ResizeToggleMenu();
 
  private:
   friend class ResizeToggleMenuTest;
 
-  std::unique_ptr<ui::SimpleMenuModel> MakeMenuModel();
+  void ExecuteCommand(CommandId command_id);
+
+  std::unique_ptr<views::BubbleDialogDelegateView> MakeBubbleDelegateView(
+      views::Widget* parent,
+      gfx::Rect anchor_rect,
+      base::RepeatingCallback<void(CommandId)> command_handler);
 
   views::Widget* widget_;
 
   ArcResizeLockPrefDelegate* pref_delegate_;
 
-  // Owned by |menu_runner_|. Store this here only for testing.
-  views::MenuItemView* root_view_ = nullptr;
-
-  std::unique_ptr<ui::SimpleMenuModel> model_;
-  std::unique_ptr<views::MenuModelAdapter> adapter_;
-  std::unique_ptr<views::MenuRunner> menu_runner_;
+  // Store only for testing.
+  views::Widget* bubble_widget_{nullptr};
+  views::Button* phone_button_{nullptr};
+  views::Button* tablet_button_{nullptr};
+  views::Button* desktop_button_{nullptr};
 };
 
 }  // namespace arc
diff --git a/components/arc/compat_mode/resize_toggle_menu_unittest.cc b/components/arc/compat_mode/resize_toggle_menu_unittest.cc
index cd56699b..f98bb47 100644
--- a/components/arc/compat_mode/resize_toggle_menu_unittest.cc
+++ b/components/arc/compat_mode/resize_toggle_menu_unittest.cc
@@ -9,9 +9,13 @@
 #include "ash/public/cpp/window_properties.h"
 #include "components/arc/compat_mode/arc_resize_lock_pref_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/views/controls/button/button.h"
 #include "ui/views/test/views_test_base.h"
+#include "ui/views/test/widget_test.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_utils.h"
 
 namespace arc {
 namespace {
@@ -46,6 +50,7 @@
     widget_ = CreateTestWidget(views::Widget::InitParams::TYPE_WINDOW);
     widget_->GetNativeWindow()->SetProperty(ash::kAppIDKey,
                                             std::string(kTestAppId));
+    widget_->Show();
     resize_toggle_menu_ =
         std::make_unique<ResizeToggleMenu>(widget_.get(), &pref_delegate);
   }
@@ -55,7 +60,7 @@
   }
 
   bool IsMenuRunning() {
-    return resize_toggle_menu_->menu_runner_->IsRunning();
+    return resize_toggle_menu_->bubble_widget_->IsVisible();
   }
 
   // Re-show the menu. This might close the running menu if any.
@@ -65,32 +70,35 @@
         std::make_unique<ResizeToggleMenu>(widget_.get(), &pref_delegate);
   }
 
-  bool IsOnlyOneItemSelected(ResizeToggleMenu::CommandId target_command_id) {
-    if (!resize_toggle_menu_->root_view_->GetMenuItemByID(target_command_id)) {
-      // The target item is NOT in the menu.
-      return false;
-    }
-    for (int id = ResizeToggleMenu::CommandId::kResizePhone;
-         id <= ResizeToggleMenu::CommandId::kMaxValue; ++id) {
-      const auto* menu_item_view =
-          resize_toggle_menu_->root_view_->GetMenuItemByID(id);
-      const bool is_selected = menu_item_view->IsSelected();
-      if (id == target_command_id && !is_selected) {
-        // The target item is NOT selected.
-        return false;
-      }
-      if (id != target_command_id && is_selected) {
-        // The NON-target item is wrongly selected.
-        return false;
-      }
-    }
-    return true;
+  bool IsCommandButtonDisabled(ResizeToggleMenu::CommandId command_id) {
+    return GetButtonByCommandId(command_id)->GetState() ==
+           views::Button::ButtonState::STATE_DISABLED;
   }
 
-  ResizeToggleMenu* resize_toggle_menu() { return resize_toggle_menu_.get(); }
+  void ClickButton(ResizeToggleMenu::CommandId command_id) {
+    const auto* button = GetButtonByCommandId(command_id);
+    ui::test::EventGenerator event_generator(GetRootWindow(widget_.get()));
+    event_generator.MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
+    event_generator.ClickLeftButton();
+  }
+
   views::Widget* widget() { return widget_.get(); }
 
  private:
+  views::Button* GetButtonByCommandId(ResizeToggleMenu::CommandId command_id) {
+    switch (command_id) {
+      case ResizeToggleMenu::CommandId::kResizePhone:
+        return resize_toggle_menu_->phone_button_;
+      case ResizeToggleMenu::CommandId::kResizeTablet:
+        return resize_toggle_menu_->tablet_button_;
+      case ResizeToggleMenu::CommandId::kResizeDesktop:
+        return resize_toggle_menu_->desktop_button_;
+      case ResizeToggleMenu::CommandId::kOpenSettings:
+        ADD_FAILURE() << "Not implemented";
+        return nullptr;
+    }
+  }
+
   TestArcResizeLockPrefDelegate pref_delegate;
   std::unique_ptr<views::Widget> widget_;
   std::unique_ptr<ResizeToggleMenu> resize_toggle_menu_;
@@ -107,8 +115,7 @@
   EXPECT_TRUE(widget()->IsMaximized());
 
   // Test that resize command is properly handled.
-  resize_toggle_menu()->ExecuteCommand(
-      ResizeToggleMenu::CommandId::kResizePhone, 0);
+  ClickButton(ResizeToggleMenu::CommandId::kResizePhone);
   EXPECT_FALSE(widget()->IsMaximized());
   EXPECT_LT(widget()->GetWindowBoundsInScreen().width(),
             widget()->GetWindowBoundsInScreen().height());
@@ -116,7 +123,12 @@
   // Test that the item is selected after the resize.
   ReshowMenu();
   EXPECT_TRUE(IsMenuRunning());
-  EXPECT_TRUE(IsOnlyOneItemSelected(ResizeToggleMenu::CommandId::kResizePhone));
+  EXPECT_TRUE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizePhone));
+  EXPECT_FALSE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizeTablet));
+  EXPECT_FALSE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizeDesktop));
 }
 
 TEST_F(ResizeToggleMenuTest, TestResizeTablet) {
@@ -126,8 +138,7 @@
   EXPECT_TRUE(widget()->IsMaximized());
 
   // Test that resize command is properly handled.
-  resize_toggle_menu()->ExecuteCommand(
-      ResizeToggleMenu::CommandId::kResizeTablet, 0);
+  ClickButton(ResizeToggleMenu::CommandId::kResizeTablet);
   EXPECT_FALSE(widget()->IsMaximized());
   EXPECT_GT(widget()->GetWindowBoundsInScreen().width(),
             widget()->GetWindowBoundsInScreen().height());
@@ -135,8 +146,12 @@
   // Test that the item is selected after the resize.
   ReshowMenu();
   EXPECT_TRUE(IsMenuRunning());
+  EXPECT_FALSE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizePhone));
   EXPECT_TRUE(
-      IsOnlyOneItemSelected(ResizeToggleMenu::CommandId::kResizeTablet));
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizeTablet));
+  EXPECT_FALSE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizeDesktop));
 }
 
 TEST_F(ResizeToggleMenuTest, TestResizeDesktop) {
@@ -145,15 +160,18 @@
   EXPECT_FALSE(widget()->IsMaximized());
 
   // Test that resize command is properly handled.
-  resize_toggle_menu()->ExecuteCommand(
-      ResizeToggleMenu::CommandId::kResizeDesktop, 0);
+  ClickButton(ResizeToggleMenu::CommandId::kResizeDesktop);
   EXPECT_TRUE(widget()->IsMaximized());
 
   // Test that the item is selected after the resize.
   ReshowMenu();
   EXPECT_TRUE(IsMenuRunning());
+  EXPECT_FALSE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizePhone));
+  EXPECT_FALSE(
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizeTablet));
   EXPECT_TRUE(
-      IsOnlyOneItemSelected(ResizeToggleMenu::CommandId::kResizeDesktop));
+      IsCommandButtonDisabled(ResizeToggleMenu::CommandId::kResizeDesktop));
 }
 
 }  // namespace arc
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index e8337c3..289bd7d7 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -1446,35 +1446,6 @@
   was_parsed_for_autocomplete_attributes_ = true;
 }
 
-std::set<std::u16string> FormStructure::PossibleValues(ServerFieldType type) {
-  std::set<std::u16string> values;
-  AutofillType target_type(type);
-  for (const auto& field : fields_) {
-    if (field->Type().GetStorableType() != target_type.GetStorableType() ||
-        field->Type().group() != target_type.group()) {
-      continue;
-    }
-
-    // No option values; anything goes.
-    if (field->option_values.empty()) {
-      values.clear();
-      break;
-    }
-
-    for (const std::u16string& val : field->option_values) {
-      if (!val.empty())
-        values.insert(base::i18n::ToUpper(val));
-    }
-
-    for (const std::u16string& content : field->option_contents) {
-      if (!content.empty())
-        values.insert(base::i18n::ToUpper(content));
-    }
-  }
-
-  return values;
-}
-
 const AutofillField* FormStructure::field(size_t index) const {
   if (index >= fields_.size()) {
     NOTREACHED();
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index 1d69fb87..b87c65f2 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -5103,51 +5103,6 @@
   EXPECT_EQ(expected_query_string, encoded_query_string);
 }
 
-TEST_F(FormStructureTestImpl, PossibleValues) {
-  FormData form_data;
-  form_data.url = GURL("http://www.foo.com/");
-
-  FormFieldData field;
-  field.autocomplete_attribute = "billing country";
-  field.option_contents.push_back(u"Down Under");
-  field.option_values.push_back(u"AU");
-  field.option_contents.push_back(u"Fr");
-  field.option_values.push_back(u"");
-  field.option_contents.push_back(u"Germany");
-  field.option_values.push_back(u"GRMNY");
-  field.unique_renderer_id = MakeFieldRendererId();
-  form_data.fields.push_back(field);
-
-  FormStructure form_structure(form_data);
-
-  form_structure.ParseFieldTypesFromAutocompleteAttributes();
-
-  // All values in <option> value= or contents are returned, set to upper case.
-  std::set<std::u16string> possible_values =
-      form_structure.PossibleValues(ADDRESS_BILLING_COUNTRY);
-  EXPECT_EQ(5U, possible_values.size());
-  EXPECT_EQ(1U, possible_values.count(u"AU"));
-  EXPECT_EQ(1U, possible_values.count(u"FR"));
-  EXPECT_EQ(1U, possible_values.count(u"DOWN UNDER"));
-  EXPECT_EQ(1U, possible_values.count(u"GERMANY"));
-  EXPECT_EQ(1U, possible_values.count(u"GRMNY"));
-  EXPECT_EQ(0U, possible_values.count(u"Fr"));
-  EXPECT_EQ(0U, possible_values.count(u"DE"));
-
-  // No field for the given type; empty value set.
-  EXPECT_EQ(0U, form_structure.PossibleValues(ADDRESS_HOME_COUNTRY).size());
-
-  // A freeform input (<input>) allows any value (overriding other <select>s).
-  FormFieldData freeform_field;
-  freeform_field.autocomplete_attribute = "billing country";
-  field.unique_renderer_id = MakeFieldRendererId();
-  form_data.fields.push_back(freeform_field);
-
-  FormStructure form_structure2(form_data);
-  form_structure2.ParseFieldTypesFromAutocompleteAttributes();
-  EXPECT_EQ(0U, form_structure2.PossibleValues(ADDRESS_BILLING_COUNTRY).size());
-}
-
 // Test that server predictions get precedence over htmll types if they are
 // overrides.
 TEST_F(FormStructureTestImpl, ParseQueryResponse_ServerPredictionIsOverride) {
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index 1c861f9..e2eb5f0 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -423,6 +423,8 @@
     "trigger_scripts/static_trigger_conditions_unittest.cc",
     "trigger_scripts/trigger_script_coordinator_unittest.cc",
     "trigger_scripts/trigger_script_unittest.cc",
+    "ukm_test_util.cc",
+    "ukm_test_util.h",
     "url_utils_unittest.cc",
     "user_data_util_unittest.cc",
     "user_model_unittest.cc",
diff --git a/components/autofill_assistant/browser/starter_platform_delegate.h b/components/autofill_assistant/browser/starter_platform_delegate.h
index 16bad47..4a06c56b 100644
--- a/components/autofill_assistant/browser/starter_platform_delegate.h
+++ b/components/autofill_assistant/browser/starter_platform_delegate.h
@@ -38,9 +38,9 @@
       std::unique_ptr<TriggerContext> trigger_context,
       const absl::optional<TriggerScriptProto>& trigger_script) = 0;
   // Returns whether a regular script is currently running.
-  virtual bool IsRegularScriptRunning() const;
+  virtual bool IsRegularScriptRunning() const = 0;
   // Returns whether a regular script is currently showing UI to the user.
-  virtual bool IsRegularScriptVisible() const;
+  virtual bool IsRegularScriptVisible() const = 0;
 
   // Access to the login manager.
   virtual WebsiteLoginManager* GetWebsiteLoginManager() const = 0;
diff --git a/components/autofill_assistant/browser/starter_unittest.cc b/components/autofill_assistant/browser/starter_unittest.cc
index 3c9ade6..7cba2319 100644
--- a/components/autofill_assistant/browser/starter_unittest.cc
+++ b/components/autofill_assistant/browser/starter_unittest.cc
@@ -26,6 +26,7 @@
 #include "components/autofill_assistant/browser/trigger_context.h"
 #include "components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h"
 #include "components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h"
+#include "components/autofill_assistant/browser/ukm_test_util.h"
 #include "components/ukm/content/source_url_recorder.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "content/public/test/browser_task_environment.h"
@@ -41,6 +42,7 @@
 using ::base::test::RunOnceCallback;
 using ::testing::_;
 using ::testing::AllOf;
+using ::testing::ElementsAreArray;
 using ::testing::Eq;
 using ::testing::IsEmpty;
 using ::testing::NiceMock;
@@ -65,8 +67,7 @@
   void SetUp() override {
     RenderViewHostTestHarness::SetUp();
     ukm::InitializeSourceUrlRecorderForWebContents(web_contents());
-    content::WebContentsTester::For(web_contents())
-        ->NavigateAndCommit(GURL(kExampleDeeplink));
+    SimulateNavigateToUrl(GURL(kExampleDeeplink));
     PrepareTriggerScriptUiDelegate();
     PrepareTriggerScriptRequestSender();
     fake_platform_delegate_.website_login_manager_ =
@@ -138,9 +139,11 @@
 
   // Returns a base64-encoded trigger script response, as created by
   // |CreateTriggerScriptResponseForTest|.
-  std::string CreateBase64TriggerScriptResponseForTest() {
+  std::string CreateBase64TriggerScriptResponseForTest(
+      TriggerScriptProto::TriggerUIType trigger_ui_type =
+          TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE) {
     std::string serialized_get_trigger_scripts_response =
-        CreateTriggerScriptResponseForTest();
+        CreateTriggerScriptResponseForTest(trigger_ui_type);
     std::string base64_get_trigger_scripts_response;
     base::Base64UrlEncode(serialized_get_trigger_scripts_response,
                           base::Base64UrlEncodePolicy::INCLUDE_PADDING,
@@ -163,106 +166,6 @@
     return serialized_get_trigger_scripts_response;
   }
 
-  // Returns true if all |expected_impressions| were recorded, and there were no
-  // other impressions for the same metric. |expected_impressions| may contain
-  // duplicate values if multiple equivalent impressions are expected.
-  // Impressions can be specified in any order.
-  bool RecordedUkmMetric(
-      base::StringPiece entry_name,
-      base::StringPiece metric_name,
-      const std::vector<std::pair<GURL, int64_t>>& expected_impressions) {
-    auto entries = ukm_recorder_.GetEntriesByName(entry_name);
-    if (entries.size() != expected_impressions.size()) {
-      LOG(ERROR) << "Expected " << expected_impressions.size()
-                 << " impressions, but got " << entries.size();
-      return false;
-    }
-
-    auto remaining_impressions = expected_impressions;
-    while (!remaining_impressions.empty()) {
-      auto it =
-          std::find_if(entries.begin(), entries.end(), [&](const auto& entry) {
-            const ukm::UkmSource* src =
-                ukm_recorder_.GetSourceForSourceId(entry->source_id);
-            CHECK(src != nullptr);
-            return *ukm_recorder_.GetEntryMetric(entry, metric_name) ==
-                       remaining_impressions.begin()->second &&
-                   src->url() == remaining_impressions.begin()->first;
-          });
-      if (it == entries.end()) {
-        LOG(ERROR) << "Impression not recorded: "
-                   << remaining_impressions.begin()->first << ": "
-                   << remaining_impressions.begin()->second;
-        return false;
-      }
-
-      remaining_impressions.erase(remaining_impressions.begin());
-    }
-    return true;
-  }
-
-  // Returns whether anything was recorded for |entry_name|.
-  bool RecordedUkmMetric(base::StringPiece entry_name) {
-    return !ukm_recorder_.GetEntriesByName(entry_name).empty();
-  }
-
-  bool UkmTriggerScriptStarted(
-      Metrics::TriggerScriptStarted state,
-      const GURL& source_url = GURL(kExampleDeeplink)) {
-    return RecordedUkmMetric("AutofillAssistant.LiteScriptStarted",
-                             "LiteScriptStarted",
-                             {{source_url, static_cast<int64_t>(state)}});
-  }
-
-  bool UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState state,
-      const GURL& source_url = GURL(kExampleDeeplink)) {
-    return RecordedUkmMetric("AutofillAssistant.LiteScriptFinished",
-                             "LiteScriptFinished",
-                             {{source_url, static_cast<int64_t>(state)}});
-  }
-
-  bool UkmTriggerScriptOnboarding(
-      Metrics::TriggerScriptOnboarding result,
-      const GURL& source_url = GURL(kExampleDeeplink)) {
-    return RecordedUkmMetric("AutofillAssistant.LiteScriptOnboarding",
-                             "LiteScriptOnboarding",
-                             {{source_url, static_cast<int64_t>(result)}});
-  }
-
-  bool UkmInChromeTriggerAction(
-      const std::vector<std::pair<GURL, Metrics::InChromeTriggerAction>>&
-          expected_impressions) {
-    std::vector<std::pair<GURL, int64_t>> transformed_expected_impressions;
-    std::transform(expected_impressions.begin(), expected_impressions.end(),
-                   std::back_inserter(transformed_expected_impressions),
-                   [&](const auto& impression) {
-                     return std::make_pair(
-                         impression.first,
-                         static_cast<int64_t>(impression.second));
-                   });
-
-    return RecordedUkmMetric("AutofillAssistant.InChromeTriggering",
-                             "InChromeTriggerAction",
-                             transformed_expected_impressions);
-  }
-
-  bool UkmTriggerScriptStarted() {
-    return RecordedUkmMetric("AutofillAssistant.LiteScriptStarted");
-  }
-
-  bool UkmTriggerScriptFinished() {
-    return RecordedUkmMetric("AutofillAssistant.LiteScriptFinished");
-  }
-
-  bool UkmTriggerScriptOnboarding() {
-    return RecordedUkmMetric("AutofillAssistant.LiteScriptOnboarding");
-  }
-
-  bool UkmInChromeTriggerAction() {
-    return RecordedUkmMetric("AutofillAssistant.InChromeTriggering");
-  }
-
   // Simulates a navigation from the last committed URL to urls[size-1] along
   // the intermediate redirect-hops in |urls|.
   void SimulateRedirectToUrl(const std::vector<GURL>& urls) {
@@ -275,6 +178,14 @@
       simulator->Redirect(url);
     }
     simulator->Commit();
+    navigation_ids_.emplace_back(
+        ukm::GetSourceIdForWebContentsDocument(web_contents()));
+  }
+
+  void SimulateNavigateToUrl(const GURL& url) {
+    content::WebContentsTester::For(web_contents())->NavigateAndCommit(url);
+    navigation_ids_.emplace_back(
+        ukm::GetSourceIdForWebContentsDocument(web_contents()));
   }
 
   // Each request sender is only good for one trigger script. This call will
@@ -327,6 +238,7 @@
       const absl::optional<TriggerScriptProto>& trigger_script)>>
       mock_start_regular_script_callback_;
   std::unique_ptr<base::test::ScopedFeatureList> enable_fake_heuristic_;
+  std::vector<ukm::SourceId> navigation_ids_;
 };
 
 TEST_F(StarterTest, RegularScriptFailsWithoutInitialUrl) {
@@ -338,9 +250,9 @@
   starter_->Start(std::make_unique<TriggerContext>(
       std::make_unique<ScriptParameters>(params), options));
 
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -358,10 +270,12 @@
   starter_->Start(std::make_unique<TriggerContext>(
       std::make_unique<ScriptParameters>(params), options));
 
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::NO_INITIAL_URL));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::NO_INITIAL_URL}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -379,10 +293,13 @@
   starter_->Start(std::make_unique<TriggerContext>(
       std::make_unique<ScriptParameters>(params), options));
 
-  EXPECT_TRUE(UkmTriggerScriptStarted(
-      Metrics::TriggerScriptStarted::MANDATORY_PARAMETER_MISSING));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(
+      GetUkmTriggerScriptStarted(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptStarted::MANDATORY_PARAMETER_MISSING}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -404,10 +321,12 @@
   starter_->Start(std::make_unique<TriggerContext>(
       std::make_unique<ScriptParameters>(params), options));
 
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FEATURE_DISABLED));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::FEATURE_DISABLED}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -435,9 +354,9 @@
               Eq(0));
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(0));
   EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(true));
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -468,9 +387,9 @@
               Eq(1));
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
   EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(true));
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_SUCCEEDED,
@@ -562,9 +481,9 @@
               Eq(1));
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(0));
   EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(false));
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_FAILED,
@@ -590,9 +509,9 @@
       std::make_unique<ScriptParameters>(script_parameters), options));
 
   EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(false));
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -619,10 +538,13 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options()));
 
-  EXPECT_TRUE(UkmTriggerScriptStarted(
-      Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(
+      GetUkmTriggerScriptStarted(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -646,10 +568,13 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options()));
 
-  EXPECT_TRUE(UkmTriggerScriptStarted(
-      Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(
+      GetUkmTriggerScriptStarted(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -708,12 +633,21 @@
       std::make_unique<ScriptParameters>(script_parameters), options));
 
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FIRST_TIME_USER));
-  EXPECT_TRUE(UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED));
-  EXPECT_TRUE(UkmTriggerScriptOnboarding(
-      Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED));
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::FIRST_TIME_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+                     TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER}}})));
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED,
+             TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER}}})));
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -738,11 +672,16 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options()));
 
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER));
-  EXPECT_TRUE(UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState::BASE64_DECODING_ERROR));
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::BASE64_DECODING_ERROR,
+                     TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -768,10 +707,13 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options()));
 
-  EXPECT_TRUE(UkmTriggerScriptStarted(
-      Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(
+      GetUkmTriggerScriptStarted(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -791,7 +733,9 @@
   std::map<std::string, std::string> script_parameters = {
       {"ENABLED", "true"},
       {"START_IMMEDIATELY", "false"},
-      {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+      {"TRIGGER_SCRIPTS_BASE64",
+       CreateBase64TriggerScriptResponseForTest(
+           TriggerScriptProto::SHOPPING_CART_RETURNING_USER)},
       {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
   TriggerContext::Options options;
   options.initial_url = "https://redirect.com/to/www/example/com";
@@ -811,12 +755,21 @@
       std::make_unique<ScriptParameters>(script_parameters), options));
 
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FIRST_TIME_USER));
-  EXPECT_TRUE(UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED));
-  EXPECT_TRUE(UkmTriggerScriptOnboarding(
-      Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED));
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::FIRST_TIME_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -845,11 +798,17 @@
   EXPECT_CALL(*mock_trigger_script_ui_delegate_, HideTriggerScript);
   fake_platform_delegate_.is_custom_tab_ = false;
   starter_->CheckSettings();
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER));
-  EXPECT_TRUE(UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState::CCT_TO_TAB_NOT_SUPPORTED));
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::RETURNING_USER}}})));
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::CCT_TO_TAB_NOT_SUPPORTED,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
 }
 
 TEST_F(StarterTest, CancelPendingTriggerScriptWhenHandlingNewStartupRequest) {
@@ -874,8 +833,12 @@
   starter_->Start(std::make_unique<TriggerContext>(
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options{}));
-  EXPECT_TRUE(
-      UkmTriggerScriptFinished(Metrics::TriggerScriptFinishedState::CANCELED));
+
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::CANCELED,
+                     TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(StarterTest, RegularStartupFailsIfNavigationDuringOnboarding) {
@@ -894,11 +857,10 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options{}));
 
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.different.com"));
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  SimulateNavigateToUrl(GURL("https://www.different.com"));
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -920,7 +882,9 @@
   std::map<std::string, std::string> script_parameters = {
       {"ENABLED", "true"},
       {"START_IMMEDIATELY", "false"},
-      {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+      {"TRIGGER_SCRIPTS_BASE64",
+       CreateBase64TriggerScriptResponseForTest(
+           TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER)},
       {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
   EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
       .WillOnce([&]() {
@@ -933,16 +897,24 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options{}));
 
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.different.com"));
+  SimulateNavigateToUrl(GURL("https://www.different.com"));
 
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FIRST_TIME_USER));
-  EXPECT_TRUE(UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE));
-  EXPECT_TRUE(UkmTriggerScriptOnboarding(
-      Metrics::TriggerScriptOnboarding::
-          ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION));
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptStarted::FIRST_TIME_USER}}})));
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE,
+             TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptOnboarding::
+                         ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION,
+                     TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER}}})));
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -974,12 +946,11 @@
                                      0u);
 
   // Navigating to a different domain will cancel the onboarding.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.different.com"));
+  SimulateNavigateToUrl(GURL("https://www.different.com"));
 
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -999,8 +970,7 @@
   // Note: the starter does not actually care about the last committed URL at
   // the time of startup. All that matters is that it has received the startup
   // intent, and that there is a valid ORIGINAL_DEEPLINK to expect.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.ignored.com"));
+  SimulateNavigateToUrl(GURL("https://www.ignored.com"));
   std::map<std::string, std::string> script_parameters = {
       {"ENABLED", "true"},
       {"START_IMMEDIATELY", "true"},
@@ -1010,9 +980,9 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options{}));
 
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -1060,24 +1030,31 @@
           testing::Ne(absl::nullopt)));
 
   // Implicit startup by navigating to an autofill-assistant-enabled site.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/cart"));
   task_environment()->RunUntilIdle();
 
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER,
-                              GURL("https://www.some-website.com/cart")));
-  EXPECT_TRUE(UkmTriggerScriptFinished(
-      Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
-      GURL("https://www.some-website.com/cart")));
-  EXPECT_TRUE(UkmTriggerScriptOnboarding(
-      Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED,
-      GURL("https://www.some-website.com/cart")));
-  EXPECT_TRUE(UkmInChromeTriggerAction(
-      {{GURL(kExampleDeeplink),
-        Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[1],
+                    {Metrics::TriggerScriptStarted::RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[1],
+                    {Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[1],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(
+      GetUkmInChromeTriggering(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH}},
+           {navigation_ids_[1],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}})));
 
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
@@ -1096,11 +1073,9 @@
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/cart"));
   task_environment()->RunUntilIdle();
-
-  EXPECT_FALSE(UkmInChromeTriggerAction());
+  EXPECT_THAT(GetUkmInChromeTriggering(ukm_recorder_), IsEmpty());
 }
 
 TEST_F(StarterTest, ImplicitStartupOnCurrentUrlAfterSettingEnabled) {
@@ -1113,8 +1088,7 @@
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/cart"));
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_,
               OnSendRequest(
@@ -1129,14 +1103,17 @@
   starter_->CheckSettings();
   task_environment()->RunUntilIdle();
 
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER,
-                              GURL("https://www.some-website.com/cart")));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
-  EXPECT_TRUE(UkmInChromeTriggerAction(
-      {{GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[1],
+                    {Metrics::TriggerScriptStarted::RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(
+      GetUkmInChromeTriggering(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[1],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}})));
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -1160,8 +1137,7 @@
 
   // Simulate a real flow that starts on some trigger site, which then redirects
   // to the deeplink.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+  SimulateNavigateToUrl(GURL("https://some-trigger-site.com"));
 
   // Start the flow before the trigger site has had a chance to navigate to the
   // target domain. This commonly happens due to android intent handling
@@ -1171,23 +1147,15 @@
 
   EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript);
 
-  std::unique_ptr<content::NavigationSimulator> simulator =
-      content::NavigationSimulator::CreateRendererInitiated(
-          web_contents()->GetLastCommittedURL(),
-          web_contents()->GetMainFrame());
-  simulator->Start();
-  simulator->Redirect(GURL("https://redirect.com/to/www/example/com"));
-  simulator->Redirect(GURL(kExampleDeeplink));
-  // To spice things up a bit more, we redirect to a subdomain of the target
-  // domain instead.
-  simulator->Redirect(GURL("https://signin.example.com"));
-  simulator->Commit();
-
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER,
-                              GURL("https://signin.example.com")));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  SimulateRedirectToUrl({GURL("https://redirect.com/to/www/example/com"),
+                         GURL(kExampleDeeplink),
+                         GURL("https://signin.example.com")});
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[2],
+                    {Metrics::TriggerScriptStarted::RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -1211,8 +1179,7 @@
 
   // Simulate a real flow that starts on some trigger site, which then redirects
   // to the deeplink.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+  SimulateNavigateToUrl(GURL("https://some-trigger-site.com"));
 
   starter_->Start(std::make_unique<TriggerContext>(
       std::make_unique<ScriptParameters>(script_parameters), options));
@@ -1227,15 +1194,18 @@
   simulator->Redirect(GURL("https://redirect.com/to/www/example/com"));
   simulator->Fail(net::ERR_BLOCKED_BY_CLIENT);
   simulator->CommitErrorPage();
+  navigation_ids_.emplace_back(
+      ukm::GetSourceIdForWebContentsDocument(web_contents()));
 
   // Note that this impression is recorded for the last URL that a navigation-
   // start event occurred for. We never reached the target domain, so this is
   // unfortunately the best we can do.
-  EXPECT_TRUE(
-      UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::NAVIGATION_ERROR,
-                              GURL("https://redirect.com/to/www/example/com")));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[2],
+                    {Metrics::TriggerScriptStarted::NAVIGATION_ERROR}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -1258,8 +1228,7 @@
 
   // Simulate a real flow that starts on some trigger site, which then redirects
   // to the deeplink.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+  SimulateNavigateToUrl(GURL("https://some-trigger-site.com"));
 
   // Begin a navigation, then start the flow before the navigation is committed.
   // UKM should still be recorded for the final URL, not the redirect URL.
@@ -1274,11 +1243,15 @@
       std::make_unique<ScriptParameters>(script_parameters), options));
   simulator->Redirect(GURL(kExampleDeeplink));
   simulator->Commit();
+  navigation_ids_.emplace_back(
+      ukm::GetSourceIdForWebContentsDocument(web_contents()));
 
-  EXPECT_TRUE(UkmTriggerScriptStarted(
-      Metrics::TriggerScriptStarted::RETURNING_USER, GURL(kExampleDeeplink)));
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[2],
+                    {Metrics::TriggerScriptStarted::RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -1295,8 +1268,7 @@
       {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
   TriggerContext::Options options;
 
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+  SimulateNavigateToUrl(GURL("https://some-trigger-site.com"));
   std::unique_ptr<content::NavigationSimulator> simulator =
       content::NavigationSimulator::CreateRendererInitiated(
           web_contents()->GetLastCommittedURL(),
@@ -1314,9 +1286,9 @@
   simulator->Redirect(GURL(kExampleDeeplink));
   simulator->Commit();
 
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Android.AutofillAssistant.FeatureModuleInstallation",
       Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
@@ -1340,14 +1312,14 @@
   TriggerContext::Options options;
 
   EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
 
   task_environment()->RunUntilIdle();
-  EXPECT_FALSE(UkmTriggerScriptStarted());
-  EXPECT_FALSE(UkmTriggerScriptFinished());
-  EXPECT_FALSE(UkmTriggerScriptOnboarding());
-  EXPECT_FALSE(UkmInChromeTriggerAction());
+  EXPECT_THAT(GetUkmTriggerScriptStarted(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmTriggerScriptOnboarding(ukm_recorder_), IsEmpty());
+  EXPECT_THAT(GetUkmInChromeTriggering(ukm_recorder_), IsEmpty());
+
   histogram_tester_.ExpectTotalCount(
       "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
   histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
@@ -1371,8 +1343,7 @@
   EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
 
   // Implicit startup by navigating to an autofill-assistant-enabled site.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/cart"));
   task_environment()->RunUntilIdle();
   EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
               UnorderedElementsAre(
@@ -1384,39 +1355,33 @@
   PrepareTriggerScriptRequestSender();
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/checkout"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-website.com/signin"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://signin.some-website.com"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/checkout"));
+  SimulateNavigateToUrl(GURL("https://some-website.com/signin"));
+  SimulateNavigateToUrl(GURL("https://signin.some-website.com"));
   task_environment()->RunUntilIdle();
 
   // Navigations to different autofill-assistant-enabled URLs will still trigger
   // implicit startup.
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(1);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.different-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.different-website.com/cart"));
   task_environment()->RunUntilIdle();
 
-  EXPECT_TRUE(UkmInChromeTriggerAction(
-      {{GURL(kExampleDeeplink),
-        Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
-       {GURL("https://www.some-website.com/checkout"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://some-website.com/signin"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://signin.some-website.com"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://www.different-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+  EXPECT_THAT(
+      GetUkmInChromeTriggering(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH}},
+           {navigation_ids_[1],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}},
+           {navigation_ids_[2],
+            {Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}},
+           {navigation_ids_[3],
+            {Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}},
+           {navigation_ids_[4],
+            {Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}},
+           {navigation_ids_[5],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}})));
 }
 
 TEST_F(StarterTest,
@@ -1440,8 +1405,7 @@
       });
 
   // Implicit startup by navigating to an autofill-assistant-enabled site.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/cart"));
   task_environment()->RunUntilIdle();
   EXPECT_THAT(*GetUserDenylistedCacheForTest(),
               UnorderedElementsAre(
@@ -1453,39 +1417,33 @@
   PrepareTriggerScriptRequestSender();
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/checkout"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-website.com/signin"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://signin.some-website.com"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/checkout"));
+  SimulateNavigateToUrl(GURL("https://some-website.com/signin"));
+  SimulateNavigateToUrl(GURL("https://signin.some-website.com"));
   task_environment()->RunUntilIdle();
 
   // Navigations to different autofill-assistant-enabled URLs will still trigger
   // implicit startup.
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(1);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.different-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.different-website.com/cart"));
   task_environment()->RunUntilIdle();
 
-  EXPECT_TRUE(UkmInChromeTriggerAction(
-      {{GURL(kExampleDeeplink),
-        Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
-       {GURL("https://www.some-website.com/checkout"),
-        Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
-       {GURL("https://some-website.com/signin"),
-        Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
-       {GURL("https://signin.some-website.com"),
-        Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
-       {GURL("https://www.different-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+  EXPECT_THAT(
+      GetUkmInChromeTriggering(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH}},
+           {navigation_ids_[1],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}},
+           {navigation_ids_[2],
+            {Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN}},
+           {navigation_ids_[3],
+            {Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN}},
+           {navigation_ids_[4],
+            {Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN}},
+           {navigation_ids_[5],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}})));
 }
 
 TEST_F(StarterTest, EmptyTriggerScriptFetchesForImplicitStartupAreCached) {
@@ -1505,8 +1463,7 @@
           }));
 
   // Implicit startup by navigating to an autofill-assistant-enabled site.
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/cart"));
   task_environment()->RunUntilIdle();
   EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
               UnorderedElementsAre(
@@ -1518,14 +1475,9 @@
   PrepareTriggerScriptRequestSender();
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/checkout"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://some-website.com/signin"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://signin.some-website.com"));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.some-website.com/checkout"));
+  SimulateNavigateToUrl(GURL("https://some-website.com/signin"));
+  SimulateNavigateToUrl(GURL("https://signin.some-website.com"));
   task_environment()->RunUntilIdle();
 
   // However, explicit requests still communicate with the backend.
@@ -1540,19 +1492,19 @@
       std::make_unique<ScriptParameters>(script_parameters),
       TriggerContext::Options{}));
 
-  EXPECT_TRUE(UkmInChromeTriggerAction(
-      {{GURL(kExampleDeeplink),
-        Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
-       {GURL("https://www.some-website.com/checkout"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://some-website.com/signin"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://signin.some-website.com"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
-       {GURL("https://www.some-website.com/cart"),
-        Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}}));
+  EXPECT_THAT(
+      GetUkmInChromeTriggering(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH}},
+           {navigation_ids_[1],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}},
+           {navigation_ids_[2],
+            {Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}},
+           {navigation_ids_[3],
+            {Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}},
+           {navigation_ids_[4],
+            {Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}}})));
 }
 
 TEST_F(StarterTest, FailedExplicitTriggerFetchesAreCached) {
@@ -1564,8 +1516,7 @@
       "https://www.example.com", "https://signing.example.com",
       "https://different.com", "https://different.com/test?q=12345"};
   for (const auto& url : unsupported_sites) {
-    content::WebContentsTester::For(web_contents())
-        ->NavigateAndCommit(GURL(url));
+    SimulateNavigateToUrl(GURL(url));
     PrepareTriggerScriptRequestSender();
     PrepareTriggerScriptUiDelegate();
     // Send empty response == no trigger script available. Note that explicit
@@ -1584,7 +1535,7 @@
   EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
               UnorderedElementsAre(Pair("example.com", now_ticks),
                                    Pair("different.com", now_ticks)));
-  EXPECT_FALSE(UkmInChromeTriggerAction());
+  EXPECT_THAT(GetUkmInChromeTriggering(ukm_recorder_), IsEmpty());
 }
 
 TEST_F(StarterTest, FailedImplicitTriggerFetchesAreCached) {
@@ -1602,8 +1553,7 @@
     // Send empty response == no trigger script available.
     EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
         .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
-    content::WebContentsTester::For(web_contents())
-        ->NavigateAndCommit(GURL(url));
+    SimulateNavigateToUrl(GURL(url));
     task_environment()->RunUntilIdle();
   }
   // Failed attempts to start implicitly are added to the cache.
@@ -1613,13 +1563,15 @@
       *GetFailedTriggerFetchesCacheForTest(),
       UnorderedElementsAre(Pair("example-shopping-site.com", now_ticks),
                            Pair("different-shopping-site.com", now_ticks)));
-  EXPECT_TRUE(UkmInChromeTriggerAction(
-      {{GURL(kExampleDeeplink),
-        Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
-       {GURL("https://www.example-shopping-site.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
-       {GURL("https://different-shopping-site.com/cart"),
-        Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+  EXPECT_THAT(
+      GetUkmInChromeTriggering(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH}},
+           {navigation_ids_[1],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}},
+           {navigation_ids_[2],
+            {Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}})));
 }
 
 TEST_F(StarterTest, FailedTriggerFetchesCacheEntriesExpire) {
@@ -1632,15 +1584,13 @@
       "example.com", task_environment()->GetMockTickClock()->NowTicks());
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
   task_environment()->FastForwardBy(base::TimeDelta::FromHours(1));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 
   // Since the request failed again, the cache entry should be updated with the
@@ -1665,8 +1615,7 @@
         trigger_script_coordinator_->PerformTriggerScriptAction(
             TriggerScriptProto::CANCEL_SESSION);
       });
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
   EXPECT_THAT(
       *GetUserDenylistedCacheForTest(),
@@ -1677,8 +1626,7 @@
   PrepareTriggerScriptUiDelegate();
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
@@ -1690,8 +1638,7 @@
             TriggerScriptProto::CANCEL_SESSION);
       });
   task_environment()->FastForwardBy(base::TimeDelta::FromHours(1));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 
   // Since the request was cancelled again, the cache entry should have been
@@ -1712,8 +1659,7 @@
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
@@ -1744,8 +1690,7 @@
   starter_->CheckSettings();
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 }
 
@@ -1758,8 +1703,7 @@
   starter_->CheckSettings();
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 }
 
@@ -1773,8 +1717,7 @@
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 }
 
@@ -1788,8 +1731,7 @@
 
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .Times(0);
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 }
 
@@ -1862,8 +1804,7 @@
   base::TimeTicks t2 = task_environment()->GetMockTickClock()->NowTicks();
   EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
       .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://www.example.com/cart"));
   task_environment()->RunUntilIdle();
 
   // failed-t0.com should have been removed from the cache due to going stale.
@@ -1887,8 +1828,7 @@
         trigger_script_coordinator_->PerformTriggerScriptAction(
             TriggerScriptProto::CANCEL_SESSION);
       });
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://supported.com/cart"));
+  SimulateNavigateToUrl(GURL("https://supported.com/cart"));
   task_environment()->RunUntilIdle();
 
   // No change to the failed fetches cache.
@@ -1956,8 +1896,7 @@
                       Property(&ScriptParameterProto::value, "NEW_INTENT"))));
       }));
 
-  content::WebContentsTester::For(web_contents())
-      ->NavigateAndCommit(GURL("https://example.com/cart"));
+  SimulateNavigateToUrl(GURL("https://example.com/cart"));
   task_environment()->RunUntilIdle();
 }
 
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
index 0aa54eaa..3aef615 100644
--- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
+++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h"
 
+#include <map>
+#include <vector>
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
@@ -17,6 +19,7 @@
 #include "components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h"
 #include "components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h"
 #include "components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h"
+#include "components/autofill_assistant/browser/ukm_test_util.h"
 #include "components/autofill_assistant/browser/web/mock_web_controller.h"
 #include "components/ukm/content/source_url_recorder.h"
 #include "components/ukm/test_ukm_recorder.h"
@@ -31,6 +34,7 @@
 
 using ::base::test::RunOnceCallback;
 using ::testing::_;
+using ::testing::ElementsAreArray;
 using ::testing::Eq;
 using ::testing::NiceMock;
 using ::testing::Return;
@@ -117,58 +121,8 @@
     content::NavigationSimulator::NavigateAndCommitFromDocument(
         url, web_contents()->GetMainFrame());
     content::WebContentsTester::For(web_contents())->TestSetIsLoading(false);
-  }
-
-  void AssertRecordedFinishedState(TriggerScriptProto::TriggerUIType type,
-                                   Metrics::TriggerScriptFinishedState state,
-                                   GURL url = GURL(kFakeDeepLink)) {
-    auto entries =
-        ukm_recorder_.GetEntriesByName("AutofillAssistant.LiteScriptFinished");
-    ASSERT_THAT(entries.size(), Eq(1u));
-    ukm_recorder_.ExpectEntrySourceHasUrl(entries[0], url);
-    EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entries[0], "TriggerUIType"),
-              static_cast<int64_t>(type));
-    EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entries[0], "LiteScriptFinished"),
-              static_cast<int64_t>(state));
-  }
-
-  // Make sure that an UKM entry with |state| has been recorded
-  // |expected_times|, and has been associated each time with |type|.
-  void AssertRecordedShownToUserState(TriggerScriptProto::TriggerUIType type,
-                                      Metrics::TriggerScriptShownToUser state,
-                                      int expected_times) {
-    auto entries = ukm_recorder_.GetEntriesByName(
-        "AutofillAssistant.LiteScriptShownToUser");
-    ukm_recorder_.ExpectEntrySourceHasUrl(entries[0], GURL(kFakeDeepLink));
-    int actual_times = 0;
-    for (const auto* entry : entries) {
-      if (*ukm_recorder_.GetEntryMetric(entry, "LiteScriptShownToUser") ==
-          static_cast<int64_t>(state)) {
-        EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entry, "TriggerUIType"),
-                  static_cast<int64_t>(type));
-        actual_times++;
-      }
-    }
-    EXPECT_EQ(expected_times, actual_times);
-  }
-
-  void AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::TriggerUIType type,
-      Metrics::TriggerScriptOnboarding state,
-      int expected_times) {
-    auto entries = ukm_recorder_.GetEntriesByName(
-        "AutofillAssistant.LiteScriptOnboarding");
-    ukm_recorder_.ExpectEntrySourceHasUrl(entries[0], GURL(kFakeDeepLink));
-    int actual_times = 0;
-    for (const auto* entry : entries) {
-      if (*ukm_recorder_.GetEntryMetric(entry, "LiteScriptOnboarding") ==
-          static_cast<int64_t>(state)) {
-        EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entry, "TriggerUIType"),
-                  static_cast<int64_t>(type));
-        actual_times++;
-      }
-    }
-    EXPECT_EQ(expected_times, actual_times);
+    navigation_ids_.emplace_back(
+        ukm::GetSourceIdForWebContentsDocument(web_contents()));
   }
 
  protected:
@@ -185,6 +139,7 @@
   std::unique_ptr<TriggerScriptCoordinator> coordinator_;
   NiceMock<MockStaticTriggerConditions>* mock_static_trigger_conditions_;
   NiceMock<MockDynamicTriggerConditions>* mock_dynamic_trigger_conditions_;
+  std::vector<ukm::SourceId> navigation_ids_;
 };
 
 TEST_F(TriggerScriptCoordinatorTest, StartSendsOnlyApprovedFields) {
@@ -247,9 +202,11 @@
       Run(Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED, _, _));
   coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
                       mock_callback_.Get());
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED);
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED,
+                     TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, StopOnParsingError) {
@@ -260,9 +217,12 @@
       Run(Metrics::TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR, _, _));
   coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
                       mock_callback_.Get());
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, StopOnNoTriggerScriptsAvailable) {
@@ -274,9 +234,12 @@
           _));
   coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
                       mock_callback_.Get());
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, StartChecksStaticAndDynamicConditions) {
@@ -448,9 +411,12 @@
           _));
   EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
   coordinator_->PerformTriggerScriptAction(TriggerScriptProto::CANCEL_SESSION);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionCancelForever) {
@@ -478,9 +444,12 @@
           _));
   EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
   coordinator_->PerformTriggerScriptAction(TriggerScriptProto::CANCEL_FOREVER);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_FOREVER);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_FOREVER,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionAccept) {
@@ -545,10 +514,12 @@
       Run(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE, _, _));
   SimulateNavigateToUrl(GURL("https://example.different.com/page"));
   // UKM is recorded for the last seen URL that was still on a supported domain.
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE,
-      GURL("https://subdomain.other-example.com/page"));
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[4],
+            {Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, IgnoreNavigationEventsWhileNotStarted) {
@@ -591,9 +562,12 @@
       Run(Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE, _,
           _));
   SimulateWebContentsVisibilityChanged(content::Visibility::VISIBLE);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, BottomSheetClosedWithSwipe) {
@@ -614,9 +588,20 @@
 
   EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
   coordinator_->OnBottomSheetClosedWithSwipe();
-  AssertRecordedShownToUserState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptShownToUser::SWIPE_DISMISSED, 1);
+  EXPECT_THAT(GetUkmTriggerScriptShownToUsers(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptShownToUser::RUNNING,
+                     TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}},
+                   {navigation_ids_[0],
+                    {Metrics::TriggerScriptShownToUser::SHOWN_TO_USER,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}},
+                   {navigation_ids_[0],
+                    {Metrics::TriggerScriptShownToUser::SWIPE_DISMISSED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}},
+                   {navigation_ids_[0],
+                    {Metrics::TriggerScriptShownToUser::NOT_NOW,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, TimeoutAfterInvisibleForTooLong) {
@@ -652,9 +637,12 @@
       Run(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT, _,
           _));
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, TimeoutResetsAfterTriggerScriptShown) {
@@ -698,9 +686,12 @@
       Run(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT, _,
           _));
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, NoTimeoutByDefault) {
@@ -772,9 +763,12 @@
       Run(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT, _,
           _));
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
+  EXPECT_THAT(
+      GetUkmTriggerScriptFinished(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT,
+             TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, UrlChangeOutOfScheduleCheckPathMatch) {
@@ -883,9 +877,11 @@
               Run(Metrics::TriggerScriptFinishedState::FAILED_TO_SHOW, _, _));
   coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
                       mock_callback_.Get());
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::FAILED_TO_SHOW);
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::FAILED_TO_SHOW,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, OnProactiveHelpSettingDisabled) {
@@ -911,9 +907,12 @@
   fake_platform_delegate_.proactive_help_enabled_ = false;
   SimulateWebContentsInteractabilityChanged(false);
   SimulateWebContentsInteractabilityChanged(true);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
-      Metrics::TriggerScriptFinishedState::DISABLED_PROACTIVE_HELP_SETTING);
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::
+                         DISABLED_PROACTIVE_HELP_SETTING,
+                     TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, PauseAndResumeOnTabSwitch) {
@@ -983,12 +982,17 @@
   coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
 
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
-  AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED, 1);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED);
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest,
@@ -1034,20 +1038,27 @@
   coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
 
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(4));
-  AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED, 1);
-  AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED, 1);
-  AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptOnboarding::
-          ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION,
-      1);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED);
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}},
+           {navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_DISMISSED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}},
+           {navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::
+                 ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}},
+           {navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest,
@@ -1080,12 +1091,18 @@
   coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
 
   EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
-  AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED, 1);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::BOTTOMSHEET_ONBOARDING_REJECTED);
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::
+                         BOTTOMSHEET_ONBOARDING_REJECTED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 TEST_F(TriggerScriptCoordinatorTest, OnboardingNotShown) {
@@ -1111,12 +1128,53 @@
   fake_platform_delegate_.show_onboarding_result_shown_ = false;
   coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
 
-  AssertRecordedTriggerScriptOnboardingState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED, 1);
-  AssertRecordedFinishedState(
-      TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
-      Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED);
+  EXPECT_THAT(
+      GetUkmTriggerScriptOnboarding(ukm_recorder_),
+      ElementsAreArray(ToHumanReadableMetrics(
+          {{navigation_ids_[0],
+            {Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED,
+             TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+  EXPECT_THAT(GetUkmTriggerScriptFinished(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
+}
+
+TEST_F(TriggerScriptCoordinatorTest, RecordUkmsForCurrentUrlIfPossible) {
+  GetTriggerScriptsResponseProto response;
+  response.add_additional_allowed_domains("other-example.com");
+  TriggerScriptProto* script = response.add_trigger_scripts();
+  script->mutable_trigger_condition()->set_path_pattern(".*cart.*");
+  script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
+  std::string serialized_response;
+  response.SerializeToString(&serialized_response);
+
+  EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
+      .WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
+  ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
+      .WillByDefault(RunOnceCallback<1>());
+  EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(0);
+  coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+                      mock_callback_.Get());
+
+  // Navigating to cart page should trigger.
+  EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+  EXPECT_CALL(*mock_dynamic_trigger_conditions_,
+              GetPathPatternMatches(".*cart.*"))
+      .WillOnce(Return(true));
+  SimulateNavigateToUrl(GURL("https://example.com/cart"));
+
+  EXPECT_THAT(GetUkmTriggerScriptShownToUsers(ukm_recorder_),
+              ElementsAreArray(ToHumanReadableMetrics(
+                  {{navigation_ids_[0],
+                    {Metrics::TriggerScriptShownToUser::RUNNING,
+                     TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}},
+                   {navigation_ids_[1],
+                    {Metrics::TriggerScriptShownToUser::SHOWN_TO_USER,
+                     TriggerScriptProto::SHOPPING_CART_RETURNING_USER}}})));
 }
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/ukm_test_util.cc b/components/autofill_assistant/browser/ukm_test_util.cc
new file mode 100644
index 0000000..411a9a90
--- /dev/null
+++ b/components/autofill_assistant/browser/ukm_test_util.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 "components/autofill_assistant/browser/ukm_test_util.h"
+#include <set>
+
+namespace autofill_assistant {
+
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptShownToUsers(ukm::TestAutoSetUkmRecorder& ukm_recorder) {
+  return ukm_recorder.GetEntries(kTriggerScriptShownToUserEntry,
+                                 {kTriggerScriptShownToUser, kTriggerUiType});
+}
+
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptStarted(ukm::TestAutoSetUkmRecorder& ukm_recorder) {
+  return ukm_recorder.GetEntries(kTriggerScriptStartedEntry,
+                                 {kTriggerScriptStarted});
+}
+
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptFinished(ukm::TestAutoSetUkmRecorder& ukm_recorder) {
+  return ukm_recorder.GetEntries(kTriggerScriptFinishedEntry,
+                                 {kTriggerScriptFinished, kTriggerUiType});
+}
+
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptOnboarding(ukm::TestAutoSetUkmRecorder& ukm_recorder) {
+  return ukm_recorder.GetEntries(kTriggerScriptOnboardingEntry,
+                                 {kTriggerScriptOnboarding, kTriggerUiType});
+}
+
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmInChromeTriggering(ukm::TestAutoSetUkmRecorder& ukm_recorder) {
+  return ukm_recorder.GetEntries(kInChromeTriggeringEntry,
+                                 {kInChromeTriggerAction});
+}
+
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> ToHumanReadableMetrics(
+    const std::vector<std::pair<ukm::SourceId, std::vector<UkmEnumVariant>>>&
+        input) {
+  std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> output;
+  std::transform(
+      input.begin(), input.end(), std::back_inserter(output),
+      [&](const auto& impression) {
+        ukm::TestUkmRecorder::HumanReadableUkmEntry transformed_impression;
+        transformed_impression.source_id = impression.first;
+        for (const auto& metric : impression.second) {
+          transformed_impression.metrics.emplace(
+              kUkmEnumMetricNames[metric.index()],
+              absl::visit(GenericConvertToInt64(), metric));
+        }
+        return transformed_impression;
+      });
+  return output;
+}
+
+}  // namespace autofill_assistant
+
+namespace ukm {
+
+std::ostream& operator<<(
+    std::ostream& out,
+    const ukm::TestUkmRecorder::HumanReadableUkmEntry& input) {
+  out << "source-id = " << input.source_id << ", metrics = [";
+  std::string deliminator;
+  for (const auto& metric : input.metrics) {
+    out << deliminator << metric.first << " = " << metric.second;
+    deliminator = ", ";
+  }
+  out << "]";
+  return out;
+}
+
+}  // namespace ukm
diff --git a/components/autofill_assistant/browser/ukm_test_util.h b/components/autofill_assistant/browser/ukm_test_util.h
new file mode 100644
index 0000000..5e21ee8
--- /dev/null
+++ b/components/autofill_assistant/browser/ukm_test_util.h
@@ -0,0 +1,99 @@
+// 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_AUTOFILL_ASSISTANT_BROWSER_UKM_TEST_UTIL_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_UKM_TEST_UTIL_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "components/autofill_assistant/browser/metrics.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+
+namespace autofill_assistant {
+
+// The identifiers for all UKM entries that we currently record/test.
+const char kTriggerScriptShownToUserEntry[] =
+    "AutofillAssistant.LiteScriptShownToUser";
+const char kTriggerScriptStartedEntry[] = "AutofillAssistant.LiteScriptStarted";
+const char kTriggerScriptFinishedEntry[] =
+    "AutofillAssistant.LiteScriptFinished";
+const char kTriggerScriptOnboardingEntry[] =
+    "AutofillAssistant.LiteScriptOnboarding";
+const char kInChromeTriggeringEntry[] = "AutofillAssistant.InChromeTriggering";
+
+// The identifiers for all UKM metrics that we currently record/test.
+const char kTriggerUiType[] = "TriggerUIType";
+const char kTriggerScriptShownToUser[] = "LiteScriptShownToUser";
+const char kTriggerScriptStarted[] = "LiteScriptStarted";
+const char kTriggerScriptFinished[] = "LiteScriptFinished";
+const char kTriggerScriptOnboarding[] = "LiteScriptOnboarding";
+const char kInChromeTriggerAction[] = "InChromeTriggerAction";
+
+// Convenience accessors for UKM metrics.
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptShownToUsers(ukm::TestAutoSetUkmRecorder& ukm_recorder);
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptStarted(ukm::TestAutoSetUkmRecorder& ukm_recorder);
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptFinished(ukm::TestAutoSetUkmRecorder& ukm_recorder);
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmTriggerScriptOnboarding(ukm::TestAutoSetUkmRecorder& ukm_recorder);
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>
+GetUkmInChromeTriggering(ukm::TestAutoSetUkmRecorder& ukm_recorder);
+
+// Variant containing all UKM enums that we currently record/test.
+// NOTE: When adding entries, remember to also modify kUkmEnumMetricNames!
+using UkmEnumVariant = absl::variant<TriggerScriptProto::TriggerUIType,
+                                     Metrics::TriggerScriptShownToUser,
+                                     Metrics::TriggerScriptStarted,
+                                     Metrics::TriggerScriptFinishedState,
+                                     Metrics::TriggerScriptOnboarding,
+                                     Metrics::InChromeTriggerAction>;
+
+// The metric names corresponding to the variant alternatives of UkmEnumVariant.
+// NOTE: When adding entries, remember to also modify UkmEnumVariant!
+const std::vector<std::string> kUkmEnumMetricNames = {
+    kTriggerUiType,         kTriggerScriptShownToUser, kTriggerScriptStarted,
+    kTriggerScriptFinished, kTriggerScriptOnboarding,  kInChromeTriggerAction};
+
+// Intended to be used to convert a UkmEnumVariant to int64_t using a visitor.
+// Usage:
+// UkmEnumVariant v = Metrics::TriggerScriptShownToUser::SHOWN_TO_USER;
+// int64_t i = absl::visit(GenericConvertToInt64(), v);
+struct GenericConvertToInt64 {
+  template <typename T>
+  int64_t operator()(const T& input) {
+    return static_cast<int64_t>(input);
+  }
+};
+
+// Converts |metrics| into a vector of ukm readable metrics that can be used
+// directly in test expectations.
+// Usage:
+// EXPECT_THAT(
+//     ukm_recorder.GetEntries("SomeEntry", {"MetricA", "MetricB"}),
+//     ElementsAreArray(ToHumanReadableMetrics(
+//       {navigation_ids[0], {MetricA::X, MetricB::Q}},
+//       {navigation_ids[1], {MetricA::Y, MetricB::P}})));
+std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> ToHumanReadableMetrics(
+    const std::vector<std::pair<ukm::SourceId, std::vector<UkmEnumVariant>>>&
+        metrics);
+
+}  // namespace autofill_assistant
+
+namespace ukm {
+// Despite its name, a HumanReadableUkmEntry is not actually readable unless we
+// define a custom output operator for it.
+std::ostream& operator<<(
+    std::ostream& out,
+    const ukm::TestUkmRecorder::HumanReadableUkmEntry& input);
+}  // namespace ukm
+
+#endif  // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_UKM_TEST_UTIL_H_
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb
index a882c0b7..859e67fb 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb
@@ -201,6 +201,7 @@
 <translation id="6196640612572343990">Блокиране на „бисквитките“ на трети страни</translation>
 <translation id="6206551242102657620">Връзката е защитена. Информация за сайта</translation>
 <translation id="6216432067784365534">Опции за <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6231752747840485235">Да се деинсталира ли <ph name="APP_NAME" />?</translation>
 <translation id="6260852843601447737">Затваряне и подаване на сигнал за злоупотреба</translation>
 <translation id="6262279340360821358"><ph name="PERMISSION_1" /> и <ph name="PERMISSION_2" /> са блокирани</translation>
 <translation id="6270391203985052864">Сайтовете могат да извеждат подкани за изпращане на известия</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
index 34483f20..3ac78f6 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
@@ -201,6 +201,7 @@
 <translation id="6196640612572343990">រារាំង​ខូគី​ភាគី​ទីបី</translation>
 <translation id="6206551242102657620">ការតភ្ជាប់​មាន​សុវត្ថិភាព។ ព័ត៌មាន​អំពីគេហទំព័រ</translation>
 <translation id="6216432067784365534">ជម្រើស <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6231752747840485235">លុប '<ph name="APP_NAME" />' ឬ?</translation>
 <translation id="6260852843601447737">បិទ ហើយ​រាយការណ៍​អំពីការបំពាន</translation>
 <translation id="6262279340360821358">បានទប់ស្កាត់ <ph name="PERMISSION_1" /> និង <ph name="PERMISSION_2" /></translation>
 <translation id="6270391203985052864">គេហទំព័រ​អាច​ស្នើសុំ​ការអនុញ្ញាត​ដើម្បី​ផ្ញើ​ការជូន​ដំណឹង</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb
index 645f423a..e2ce7c5 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb
@@ -201,6 +201,7 @@
 <translation id="6196640612572343990">Гуравдагч талын күүкиг блоклох</translation>
 <translation id="6206551242102657620">Холболт аюулгүй байна. Сайтын мэдээлэл</translation>
 <translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Сонголт</translation>
+<translation id="6231752747840485235"><ph name="APP_NAME" />-г устгах уу?</translation>
 <translation id="6260852843601447737">Хаагаад, зохисгүй үйлдлийг мэдээлэх</translation>
 <translation id="6262279340360821358"><ph name="PERMISSION_1" /> болон <ph name="PERMISSION_2" />-г блоклосон</translation>
 <translation id="6270391203985052864">Сайтууд нь танд мэдэгдэл илгээх зөвшөөрөл асуух боломжтой</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb
index b809fd2..c17c129 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb
@@ -201,6 +201,7 @@
 <translation id="6196640612572343990">ပြင်ပကုမ္ပဏီကွတ်ကီးများကို ပိတ်ဆို့မည်</translation>
 <translation id="6206551242102657620">ချိတ်ဆက်မှုသည် လုံခြုံပါသည်။ ဝဘ်ဆိုက် အချက်အလက်</translation>
 <translation id="6216432067784365534">ရွေးစရာ <ph name="NAME_OF_LIST_ITEM" /> ခု</translation>
+<translation id="6231752747840485235">‘<ph name="APP_NAME" />’ ဖယ်ရှားမလား။</translation>
 <translation id="6260852843601447737">ပိတ်ပြီး အလွဲသုံးစားပြုခြင်းကို တိုင်ကြားရန်</translation>
 <translation id="6262279340360821358"><ph name="PERMISSION_1" /> နှင့် <ph name="PERMISSION_2" /> ပိတ်ထားသည်</translation>
 <translation id="6270391203985052864">ဝဘ်ဆိုက်များက အကြောင်းကြားချက်များပို့ရန် တောင်းဆိုနိုင်သည်</translation>
diff --git a/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb b/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
index 0d50e6e..b9ed1ae3 100644
--- a/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
+++ b/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
@@ -201,6 +201,7 @@
 <translation id="6196640612572343990">Tashqi cookie-fayllarni bloklash.</translation>
 <translation id="6206551242102657620">Aloqa himoyalangan. Sayt axboroti</translation>
 <translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> parametrlar</translation>
+<translation id="6231752747840485235"><ph name="APP_NAME" /> oʻchirib tashlansinmi?</translation>
 <translation id="6260852843601447737">Yopish va shikoyat yuborish</translation>
 <translation id="6262279340360821358">Bloklandi: <ph name="PERMISSION_1" /> va <ph name="PERMISSION_2" /></translation>
 <translation id="6270391203985052864">Saytlar bildirishnoma chiqarishga ruxsat soʻray oladi</translation>
diff --git a/components/full_restore/full_restore_read_and_save_unittest.cc b/components/full_restore/full_restore_read_and_save_unittest.cc
index 9eab7de1..97eaa83 100644
--- a/components/full_restore/full_restore_read_and_save_unittest.cc
+++ b/components/full_restore/full_restore_read_and_save_unittest.cc
@@ -33,6 +33,7 @@
 
 constexpr int32_t kId1 = 100;
 constexpr int32_t kId2 = 200;
+constexpr int32_t kId3 = 300;
 
 constexpr int32_t kActivationIndex1 = 100;
 constexpr int32_t kActivationIndex2 = 101;
@@ -281,6 +282,13 @@
   timer->FireNow();
   task_environment().RunUntilIdle();
 
+  // Modify the window id from `kId2` to `kId3` for `kAppId`.
+  FullRestoreSaveHandler::GetInstance()->ModifyWindowId(GetPath(), kAppId, kId2,
+                                                        kId3);
+  EXPECT_TRUE(timer->IsRunning());
+  timer->FireNow();
+  task_environment().RunUntilIdle();
+
   ReadFromFile(GetPath());
 
   // Verify the restore data can be read correctly.
@@ -303,13 +311,16 @@
   EXPECT_TRUE(data1->activation_index.has_value());
   EXPECT_EQ(kActivationIndex1, data1->activation_index.value());
 
-  // Verify for |kId2|.
-  const auto app_restore_data_it2 = launch_list_it->second.find(kId2);
-  EXPECT_TRUE(app_restore_data_it2 != launch_list_it->second.end());
+  // Verify the restore data for |kId2| doesn't exist.
+  EXPECT_TRUE(!base::Contains(launch_list_it->second, kId2));
 
-  const auto& data2 = app_restore_data_it2->second;
-  EXPECT_TRUE(data2->activation_index.has_value());
-  EXPECT_EQ(kActivationIndex2, data2->activation_index.value());
+  // Verify the restore data for |kId2| is moved to |kId3|.
+  const auto app_restore_data_it3 = launch_list_it->second.find(kId3);
+  ASSERT_NE(app_restore_data_it3, launch_list_it->second.end());
+
+  const auto& data3 = app_restore_data_it3->second;
+  EXPECT_TRUE(data3->activation_index.has_value());
+  EXPECT_EQ(kActivationIndex2, data3->activation_index.value());
 }
 
 TEST_F(FullRestoreReadAndSaveTest, MultipleFilePaths) {
diff --git a/components/full_restore/full_restore_save_handler.cc b/components/full_restore/full_restore_save_handler.cc
index 149704ce..7de405d 100644
--- a/components/full_restore/full_restore_save_handler.cc
+++ b/components/full_restore/full_restore_save_handler.cc
@@ -255,6 +255,22 @@
   MaybeStartSaveTimer();
 }
 
+void FullRestoreSaveHandler::ModifyWindowId(const base::FilePath& profile_path,
+                                            const std::string& app_id,
+                                            int32_t old_window_id,
+                                            int32_t new_window_id) {
+  auto it = profile_path_to_restore_data_.find(profile_path);
+  if (it == profile_path_to_restore_data_.end())
+    return;
+
+  profile_path_to_restore_data_[profile_path].ModifyWindowId(
+      app_id, old_window_id, new_window_id);
+
+  pending_save_profile_paths_.insert(profile_path);
+
+  MaybeStartSaveTimer();
+}
+
 void FullRestoreSaveHandler::ModifyWindowInfo(
     const base::FilePath& profile_path,
     const std::string& app_id,
diff --git a/components/full_restore/full_restore_save_handler.h b/components/full_restore/full_restore_save_handler.h
index d94bd86..8fd7781 100644
--- a/components/full_restore/full_restore_save_handler.h
+++ b/components/full_restore/full_restore_save_handler.h
@@ -94,6 +94,12 @@
   void AddAppLaunchInfo(const base::FilePath& profile_path,
                         AppLaunchInfoPtr app_launch_info);
 
+  // Modify the window id for `app_id` from `old_window_id` to `new_window_id`.
+  void ModifyWindowId(const base::FilePath& profile_path,
+                      const std::string& app_id,
+                      int32_t old_window_id,
+                      int32_t new_window_id);
+
   // Saves |window_info| to |profile_path| for |app_id| and |window_id|.
   void ModifyWindowInfo(const base::FilePath& profile_path,
                         const std::string& app_id,
diff --git a/components/full_restore/restore_data.cc b/components/full_restore/restore_data.cc
index e134b4b..5675ab5 100644
--- a/components/full_restore/restore_data.cc
+++ b/components/full_restore/restore_data.cc
@@ -98,6 +98,21 @@
       std::make_unique<AppRestoreData>(std::move(app_launch_info));
 }
 
+void RestoreData::ModifyWindowId(const std::string& app_id,
+                                 int32_t old_window_id,
+                                 int32_t new_window_id) {
+  auto it = app_id_to_launch_list_.find(app_id);
+  if (it == app_id_to_launch_list_.end())
+    return;
+
+  auto data_it = it->second.find(old_window_id);
+  if (data_it == it->second.end())
+    return;
+
+  it->second[new_window_id] = std::move(data_it->second);
+  it->second.erase(data_it);
+}
+
 void RestoreData::ModifyWindowInfo(const std::string& app_id,
                                    int32_t window_id,
                                    const WindowInfo& window_info) {
diff --git a/components/full_restore/restore_data.h b/components/full_restore/restore_data.h
index 184c2cec..a179eba2 100644
--- a/components/full_restore/restore_data.h
+++ b/components/full_restore/restore_data.h
@@ -86,6 +86,13 @@
   // Adds |app_launch_info| to |app_id_to_launch_list_|.
   void AddAppLaunchInfo(std::unique_ptr<AppLaunchInfo> app_launch_info);
 
+  // Modify the window id for |app_id| from |old_window_id| to |new_window_id|.
+  // This function is used for ARC ghost window only, to switch the window id
+  // from the session id to the task id.
+  void ModifyWindowId(const std::string& app_id,
+                      int32_t old_window_id,
+                      int32_t new_window_id);
+
   // Modifies the window's information based on |window_info| for the window
   // with |window_id| of the app with |app_id|.
   void ModifyWindowInfo(const std::string& app_id,
diff --git a/components/full_restore/restore_data_unittest.cc b/components/full_restore/restore_data_unittest.cc
index f551b7c7..e5b2278 100644
--- a/components/full_restore/restore_data_unittest.cc
+++ b/components/full_restore/restore_data_unittest.cc
@@ -28,6 +28,7 @@
 constexpr int32_t kWindowId1 = 100;
 constexpr int32_t kWindowId2 = 200;
 constexpr int32_t kWindowId3 = 300;
+constexpr int32_t kWindowId4 = 400;
 
 constexpr int64_t kDisplayId1 = 22000000;
 constexpr int64_t kDisplayId2 = 11000000;
@@ -342,6 +343,48 @@
   VerifyRestoreData(restore_data());
 }
 
+// Modify the window id from `kWindowId2` to `kWindowId4` for `kAppId1`. Verify
+// the restore data is correctly updated.
+TEST_F(RestoreDataTest, ModifyWindowId) {
+  AddAppLaunchInfos();
+  ModifyWindowInfos();
+  ModifyThemeColors();
+  VerifyRestoreData(restore_data());
+
+  restore_data().ModifyWindowId(kAppId1, kWindowId2, kWindowId4);
+
+  // Verify for |kAppId1|.
+  const auto launch_list_it1 =
+      app_id_to_launch_list(restore_data()).find(kAppId1);
+  EXPECT_TRUE(launch_list_it1 != app_id_to_launch_list(restore_data()).end());
+  EXPECT_EQ(2u, launch_list_it1->second.size());
+
+  // Verify the restore data for |kAppId1| and |kWindowId1| still exists.
+  EXPECT_TRUE(base::Contains(launch_list_it1->second, kWindowId1));
+
+  // Verify the restore data for |kAppId1| and |kWindowId2| doesn't exist.
+  EXPECT_TRUE(!base::Contains(launch_list_it1->second, kWindowId2));
+
+  // Verify the restore data for |kWindowId2| is migrated to |kWindowId4|.
+  const auto app_restore_data_it4 = launch_list_it1->second.find(kWindowId4);
+  EXPECT_TRUE(app_restore_data_it4 != launch_list_it1->second.end());
+  VerifyAppRestoreData(app_restore_data_it4->second,
+                       apps::mojom::LaunchContainer::kLaunchContainerTab,
+                       WindowOpenDisposition::NEW_FOREGROUND_TAB, kDisplayId1,
+                       std::vector<base::FilePath>{base::FilePath(kFilePath2)},
+                       CreateIntent(kIntentActionView, kMimeType, kShareText2),
+                       kActivationIndex2, kDeskId2, kVisibleOnAllWorkspaces2,
+                       kRestoreBounds2, kCurrentBounds2, kWindowStateType2,
+                       absl::nullopt, kMinSize2, kPrimaryColor2,
+                       kStatusBarColor2);
+
+  // Verify the restore data for |kAppId2| still exists.
+  const auto launch_list_it2 =
+      app_id_to_launch_list(restore_data()).find(kAppId2);
+  EXPECT_TRUE(launch_list_it2 != app_id_to_launch_list(restore_data()).end());
+  EXPECT_EQ(1u, launch_list_it2->second.size());
+}
+
 TEST_F(RestoreDataTest, RemoveAppRestoreData) {
   AddAppLaunchInfos();
   ModifyWindowInfos();
diff --git a/components/pdf/browser/BUILD.gn b/components/pdf/browser/BUILD.gn
index acdda20..78b3f30 100644
--- a/components/pdf/browser/BUILD.gn
+++ b/components/pdf/browser/BUILD.gn
@@ -6,6 +6,10 @@
 
 static_library("browser") {
   sources = [
+    "pdf_navigation_throttle.cc",
+    "pdf_navigation_throttle.h",
+    "pdf_url_loader_request_interceptor.cc",
+    "pdf_url_loader_request_interceptor.h",
     "pdf_web_contents_helper.cc",
     "pdf_web_contents_helper.h",
     "pdf_web_contents_helper_client.h",
diff --git a/components/pdf/browser/DEPS b/components/pdf/browser/DEPS
index ab9e1f9..7589f41 100644
--- a/components/pdf/browser/DEPS
+++ b/components/pdf/browser/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+content/public/browser",
   "+mojo/public/cpp/bindings",
+  "+services/network/public/cpp",
   "+ui/base",
   "+ui/touch_selection",
 ]
diff --git a/components/pdf/browser/pdf_navigation_throttle.cc b/components/pdf/browser/pdf_navigation_throttle.cc
new file mode 100644
index 0000000..12de4823
--- /dev/null
+++ b/components/pdf/browser/pdf_navigation_throttle.cc
@@ -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.
+
+#include "components/pdf/browser/pdf_navigation_throttle.h"
+
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/navigation_throttle.h"
+
+namespace pdf {
+
+PdfNavigationThrottle::PdfNavigationThrottle(
+    content::NavigationHandle* navigation_handle)
+    : content::NavigationThrottle(navigation_handle) {}
+
+PdfNavigationThrottle::~PdfNavigationThrottle() = default;
+
+const char* PdfNavigationThrottle::GetNameForLogging() {
+  return "PdfNavigationThrottle";
+}
+
+}  // namespace pdf
diff --git a/components/pdf/browser/pdf_navigation_throttle.h b/components/pdf/browser/pdf_navigation_throttle.h
new file mode 100644
index 0000000..6163437
--- /dev/null
+++ b/components/pdf/browser/pdf_navigation_throttle.h
@@ -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.
+
+#ifndef COMPONENTS_PDF_BROWSER_PDF_NAVIGATION_THROTTLE_H_
+#define COMPONENTS_PDF_BROWSER_PDF_NAVIGATION_THROTTLE_H_
+
+#include "content/public/browser/navigation_throttle.h"
+
+namespace content {
+class NavigationHandle;
+}  // namespace content
+
+namespace pdf {
+
+class PdfNavigationThrottle final : public content::NavigationThrottle {
+ public:
+  explicit PdfNavigationThrottle(content::NavigationHandle* navigation_handle);
+  PdfNavigationThrottle(const PdfNavigationThrottle&) = delete;
+  PdfNavigationThrottle& operator=(const PdfNavigationThrottle&) = delete;
+  ~PdfNavigationThrottle() override;
+
+  // `content::NavigationThrottle`:
+  const char* GetNameForLogging() override;
+};
+
+}  // namespace pdf
+
+#endif  // COMPONENTS_PDF_BROWSER_PDF_NAVIGATION_THROTTLE_H_
diff --git a/components/pdf/browser/pdf_url_loader_request_interceptor.cc b/components/pdf/browser/pdf_url_loader_request_interceptor.cc
new file mode 100644
index 0000000..f33fcad
--- /dev/null
+++ b/components/pdf/browser/pdf_url_loader_request_interceptor.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 "components/pdf/browser/pdf_url_loader_request_interceptor.h"
+
+#include <utility>
+
+#include "base/callback.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/url_loader_request_interceptor.h"
+#include "services/network/public/cpp/resource_request.h"
+
+namespace pdf {
+
+PdfURLLoaderRequestInterceptor::PdfURLLoaderRequestInterceptor() = default;
+PdfURLLoaderRequestInterceptor::~PdfURLLoaderRequestInterceptor() = default;
+
+void PdfURLLoaderRequestInterceptor::MaybeCreateLoader(
+    const network::ResourceRequest& tentative_resource_request,
+    content::BrowserContext* browser_context,
+    content::URLLoaderRequestInterceptor::LoaderCallback callback) {
+  std::move(callback).Run({});
+}
+
+}  // namespace pdf
diff --git a/components/pdf/browser/pdf_url_loader_request_interceptor.h b/components/pdf/browser/pdf_url_loader_request_interceptor.h
new file mode 100644
index 0000000..b0e7b0a
--- /dev/null
+++ b/components/pdf/browser/pdf_url_loader_request_interceptor.h
@@ -0,0 +1,30 @@
+// 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_PDF_BROWSER_PDF_URL_LOADER_REQUEST_INTERCEPTOR_H_
+#define COMPONENTS_PDF_BROWSER_PDF_URL_LOADER_REQUEST_INTERCEPTOR_H_
+
+#include "content/public/browser/url_loader_request_interceptor.h"
+
+namespace pdf {
+
+class PdfURLLoaderRequestInterceptor final
+    : public content::URLLoaderRequestInterceptor {
+ public:
+  PdfURLLoaderRequestInterceptor();
+  PdfURLLoaderRequestInterceptor(const PdfURLLoaderRequestInterceptor&) =
+      delete;
+  PdfURLLoaderRequestInterceptor& operator=(
+      const PdfURLLoaderRequestInterceptor&) = delete;
+  ~PdfURLLoaderRequestInterceptor() override;
+
+  void MaybeCreateLoader(
+      const network::ResourceRequest& tentative_resource_request,
+      content::BrowserContext* browser_context,
+      content::URLLoaderRequestInterceptor::LoaderCallback callback) override;
+};
+
+}  // namespace pdf
+
+#endif  // COMPONENTS_PDF_BROWSER_PDF_URL_LOADER_REQUEST_INTERCEPTOR_H_
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 48281ad..aec855ef 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -1778,6 +1778,15 @@
   optional bool allowed = 1;
 }
 
+// Settings that control when a device will reboot. The reboots are
+// recurring. In order to disable scheduled reboots the policy must be
+// removed.
+message DeviceScheduledRebootProto {
+  // This is a JSON string, for details see "DeviceScheduledReboot" in
+  // policy_templates.json.
+  optional string device_scheduled_reboot_settings = 1;
+}
+
 message ChromeDeviceSettingsProto {
   reserved 61, 90;
   optional DevicePolicyRefreshRateProto device_policy_refresh_rate = 1;
@@ -1935,4 +1944,5 @@
       device_allowed_bluetooth_services = 120;
   optional DeviceDebugPacketCaptureAllowedProto
       device_debug_packet_capture_allowed = 121;
+  optional DeviceScheduledRebootProto device_scheduled_reboot = 122;
 }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 4a8b08a..40e27fb0 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -21839,6 +21839,51 @@
       'desc': '''Allows setting a custom schedule to check for updates. This applies to all users, and to all interfaces on the device. Once set, the device will check for updates according to the schedule. The policy must be removed to cancel any more scheduled update checks.'''
     },
     {
+      'name': 'DeviceScheduledReboot',
+      'owners': ['sanjaperisic@chromium.org'],
+      'device_only': True,
+      'type': 'dict',
+      'schema': {
+        'type': 'object',
+        'properties': {
+          'reboot_time': {
+            'description': '''Time when the reboot should happen, interpreted in the device's local time zone.''',
+            '$ref': 'Time'
+          },
+          'frequency': {
+            'description': 'Frequency at which the reboot should recur.',
+            'type': 'string',
+            'enum': [
+              'DAILY',
+              'WEEKLY',
+              'MONTHLY'
+            ]
+          },
+          'day_of_week': {
+            'description': '''Day of week when the reboot should happen, interpreted in the device's local time zone. Only used when 'frequency' is 'WEEKLY'.''',
+            '$ref': 'WeekDay'
+          },
+          'day_of_month': {
+            'description': '''Day of month [1-31] when the reboot should happen, interpreted in the device's local time zone. Only used when 'frequency' is 'MONTHLY'. If this is more than the maximum number of days in a given month then the last day of the month will be chosen.''',
+            'type': 'integer',
+            'minimum': 1,
+            'maximum': 31
+          }
+        },
+        'required': ['reboot_time', 'frequency']
+      },
+      'future_on': ['chrome_os'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': False,
+      },
+      'example_value': {'reboot_time' : {'hour': 22, 'minute': 30}, 'frequency': 'WEEKLY', 'day_of_week': 'TUESDAY', 'day_of_month': 11},
+      'tags': [],
+      'id': 862,
+      'caption': '''Set custom schedule to reboot kiosk devices''',
+      'desc': '''Allows setting a custom schedule to reboot devices. The policy currently applies only to devices which have enabled auto-launch app in the Kiosk session. Once set to True, the device will reboot to the schedule. The policy must be removed to cancel any more scheduled reboots.'''
+    },
+    {
       'name': 'KerberosEnabled',
       'owners': ['fsandrade@chromium.org', 'file://chrome/browser/ash/kerberos/OWNERS'],
       'type': 'main',
@@ -26468,6 +26513,7 @@
     'DeviceBorealisAllowed': 'device_borealis_allowed.allowed',
     'DeviceAllowedBluetoothServices': 'device_allowed_bluetooth_services.allowlist',
     'DeviceDebugPacketCaptureAllowed': 'device_debug_packet_capture_allowed.allowed',
+    'DeviceScheduledReboot': 'device_scheduled_reboot.device_scheduled_reboot_settings',
   },
   'policy_atomic_group_definitions': [
     {
@@ -26956,6 +27002,6 @@
   'placeholders': [],
   'deleted_policy_ids': [114, 115, 204, 205, 206, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669],
   'deleted_atomic_policy_group_ids': [19],
-  'highest_id_currently_used': 861,
+  'highest_id_currently_used': 862,
   'highest_atomic_group_id_currently_used': 40
 }
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index ef2abc09..bd38dbcb 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -652,22 +652,15 @@
     if (signin_error_controller->HasError()) {
       const CoreAccountId error_account_id =
           signin_error_controller->error_account_id();
-      const absl::optional<AccountInfo> error_account_info =
-          identity_manager
-              ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-                  error_account_id);
+      const AccountInfo error_account_info =
+          identity_manager->FindExtendedAccountInfoByAccountId(
+              error_account_id);
       AddSectionEntry(basic_info, "Auth Error",
           signin_error_controller->auth_error().ToString());
       AddSectionEntry(basic_info, "Auth Error Account Id",
                       error_account_id.ToString());
-
-      // The error_account_info optional should never be unset when we reach
-      // this line (as we should have a refresh token, even if in an error
-      // state). However, since this is a debug page, make the code resilient
-      // to avoid rendering the page unavailable to debug if a regression is
-      // introduced (and thus making debugging the regression harder).
       AddSectionEntry(basic_info, "Auth Error Username",
-                      error_account_info ? error_account_info->email : "");
+                      error_account_info.email);
     } else {
       AddSectionEntry(basic_info, "Auth Error", "None");
     }
diff --git a/components/signin/core/browser/account_investigator.cc b/components/signin/core/browser/account_investigator.cc
index 870e302..5aa0ba6 100644
--- a/components/signin/core/browser/account_investigator.cc
+++ b/components/signin/core/browser/account_investigator.cc
@@ -37,15 +37,12 @@
 
 // Returns the extended info for the primary account (no consent required) if
 // available.
-absl::optional<AccountInfo> GetExtendedAccountInfo(
-    signin::IdentityManager* identity_manager) {
+AccountInfo GetExtendedAccountInfo(signin::IdentityManager* identity_manager) {
   CoreAccountId account_id =
       identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSignin);
   if (account_id.empty())
-    return absl::nullopt;
-  return identity_manager
-      ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-          account_id);
+    return AccountInfo();
+  return identity_manager->FindExtendedAccountInfoByAccountId(account_id);
 }
 
 // Returns true if there is primary account (no consent required) but no
@@ -53,7 +50,7 @@
 bool WaitingForExtendedInfo(signin::IdentityManager* identity_manager) {
   if (!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin))
     return false;
-  return !GetExtendedAccountInfo(identity_manager).has_value();
+  return GetExtendedAccountInfo(identity_manager).IsEmpty();
 }
 
 }  // namespace
@@ -244,10 +241,9 @@
   if (identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
     const bool is_syncing =
         identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync);
-    absl::optional<AccountInfo> info =
-        GetExtendedAccountInfo(identity_manager_);
+    AccountInfo info = GetExtendedAccountInfo(identity_manager_);
     signin_metrics::LogSignedInCookiesCountsPerPrimaryAccountType(
-        signed_in_accounts.size(), is_syncing, info->IsManaged());
+        signed_in_accounts.size(), is_syncing, info.IsManaged());
   }
 
   periodic_pending_ = false;
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 594c2f71..0cbe1fd9 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -102,17 +102,17 @@
 
   net::HttpRequestHeaders CreateRequest(
       const GURL& url,
-      const std::string& account_id,
+      const std::string& gaia_id,
       const absl::optional<bool>& is_child_account) {
     net::HttpRequestHeaders original_headers;
     RequestAdapterWrapper request_adapter(url, original_headers);
     AppendOrRemoveMirrorRequestHeader(
-        request_adapter.adapter(), GURL(), account_id, is_child_account,
+        request_adapter.adapter(), GURL(), gaia_id, is_child_account,
         account_consistency_, cookie_settings_.get(), PROFILE_MODE_DEFAULT,
         kTestSource, force_account_consistency_);
-    AppendOrRemoveDiceRequestHeader(
-        request_adapter.adapter(), GURL(), account_id, sync_enabled_,
-        account_consistency_, cookie_settings_.get(), device_id_);
+    AppendOrRemoveDiceRequestHeader(request_adapter.adapter(), GURL(), gaia_id,
+                                    sync_enabled_, account_consistency_,
+                                    cookie_settings_.get(), device_id_);
     return request_adapter.GetFinalHeaders();
   }
 
@@ -130,23 +130,23 @@
   }
 
   void CheckMirrorHeaderRequest(const GURL& url,
-                                const std::string& account_id,
+                                const std::string& gaia_id,
                                 const absl::optional<bool>& is_child_account,
                                 const std::string& expected_request) {
     net::HttpRequestHeaders headers =
-        CreateRequest(url, account_id, is_child_account);
+        CreateRequest(url, gaia_id, is_child_account);
     CheckAccountConsistencyHeaderRequest(headers, kChromeConnectedHeader,
                                          expected_request);
   }
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   void CheckDiceHeaderRequest(const GURL& url,
-                              const std::string& account_id,
+                              const std::string& gaia_id,
                               const absl::optional<bool>& is_child_account,
                               const std::string& expected_mirror_request,
                               const std::string& expected_dice_request) {
     net::HttpRequestHeaders headers =
-        CreateRequest(url, account_id, is_child_account);
+        CreateRequest(url, gaia_id, is_child_account);
     CheckAccountConsistencyHeaderRequest(headers, kChromeConnectedHeader,
                                          expected_mirror_request);
     CheckAccountConsistencyHeaderRequest(headers, kDiceRequestHeader,
@@ -657,11 +657,11 @@
   account_consistency_ = AccountConsistencyMethod::kMirror;
   const GURL url("https://docs.google.com/document");
   const GURL redirect_url("https://www.google.com");
-  const std::string account_id = "0123456789";
+  const std::string gaia_id = "0123456789";
   net::HttpRequestHeaders original_headers;
   RequestAdapterWrapper request_adapter(url, original_headers);
   AppendOrRemoveMirrorRequestHeader(
-      request_adapter.adapter(), redirect_url, account_id,
+      request_adapter.adapter(), redirect_url, gaia_id,
       /*is_child_account=*/absl::nullopt, account_consistency_,
       cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
       false /* force_account_consistency */);
@@ -675,12 +675,12 @@
   account_consistency_ = AccountConsistencyMethod::kMirror;
   const GURL url("https://docs.google.com/document");
   const GURL redirect_url("http://www.foo.com");
-  const std::string account_id = "0123456789";
+  const std::string gaia_id = "0123456789";
   net::HttpRequestHeaders original_headers;
   original_headers.SetHeader(kChromeConnectedHeader, "foo,bar");
   RequestAdapterWrapper request_adapter(url, original_headers);
   AppendOrRemoveMirrorRequestHeader(
-      request_adapter.adapter(), redirect_url, account_id,
+      request_adapter.adapter(), redirect_url, gaia_id,
       /*is_child_account=*/absl::nullopt, account_consistency_,
       cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
       false /* force_account_consistency */);
@@ -694,13 +694,13 @@
   account_consistency_ = AccountConsistencyMethod::kMirror;
   const GURL url("https://www.bar.com");
   const GURL redirect_url("http://www.foo.com");
-  const std::string account_id = "0123456789";
+  const std::string gaia_id = "0123456789";
   const std::string fake_header = "foo,bar";
   net::HttpRequestHeaders original_headers;
   original_headers.SetHeader(kChromeConnectedHeader, fake_header);
   RequestAdapterWrapper request_adapter(url, original_headers);
   AppendOrRemoveMirrorRequestHeader(
-      request_adapter.adapter(), redirect_url, account_id,
+      request_adapter.adapter(), redirect_url, gaia_id,
       /*is_child_account=*/absl::nullopt, account_consistency_,
       cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
       false /* force_account_consistency */);
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java
index e5615ae..6f8027d 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java
@@ -84,9 +84,7 @@
         final Promise<AccountInfo> accountInfoPromise = new Promise<>();
         mAccountTrackerService.seedAccountsIfNeeded(() -> {
             accountInfoPromise.fulfill(
-                    mIdentityManager
-                            .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                                    email));
+                    mIdentityManager.findExtendedAccountInfoByEmailAddress(email));
         });
         return accountInfoPromise;
     }
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java
index 8614def..7ed5ba7d 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java
@@ -159,11 +159,9 @@
      * Looks up and returns information for account with given |email|. If the account
      * cannot be found, return a null value.
      */
-    public @Nullable AccountInfo findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-            String email) {
-        return IdentityManagerJni.get()
-                .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                        mNativeIdentityManager, email);
+    public @Nullable AccountInfo findExtendedAccountInfoByEmailAddress(String email) {
+        return IdentityManagerJni.get().findExtendedAccountInfoByEmailAddress(
+                mNativeIdentityManager, email);
     }
 
     /**
@@ -208,8 +206,7 @@
         @Nullable
         CoreAccountInfo getPrimaryAccountInfo(long nativeIdentityManager, int consentLevel);
         @Nullable
-        AccountInfo findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-                long nativeIdentityManager, String email);
+        AccountInfo findExtendedAccountInfoByEmailAddress(long nativeIdentityManager, String email);
         CoreAccountInfo[] getAccountsWithRefreshTokens(long nativeIdentityManager);
         void forceRefreshOfExtendedAccountInfo(
                 long nativeIdentityManager, CoreAccountId coreAccountId);
diff --git a/components/signin/public/identity_manager/accounts_mutator_unittest.cc b/components/signin/public/identity_manager/accounts_mutator_unittest.cc
index 0daef5a..dc405e83 100644
--- a/components/signin/public/identity_manager/accounts_mutator_unittest.cc
+++ b/components/signin/public/identity_manager/accounts_mutator_unittest.cc
@@ -145,10 +145,7 @@
   EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
 
   AccountInfo original_account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
   EXPECT_EQ(original_account_info.account_id, account_id);
   EXPECT_EQ(original_account_info.email, kTestEmail);
   EXPECT_FALSE(original_account_info.is_child_account);
@@ -159,10 +156,7 @@
       /*is_child_account=*/true,
       /*is_under_advanced_protection=*/absl::nullopt);
   AccountInfo updated_account_info_1 =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
 
   // Only |is_child_account| changed so far, everything else remains the same.
   EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
@@ -178,10 +172,7 @@
                                         /*is_child_account=*/absl::nullopt,
                                         /*is_under_advanced_protection=*/true);
   AccountInfo updated_account_info_2 =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
 
   // |is_under_advanced_protection| has changed now, but |is_child_account|
   // remains the same since we previously set it to |true| in the previous step.
@@ -199,10 +190,7 @@
                                         /*is_child_account=*/false,
                                         /*is_under_advanced_protection=*/false);
   AccountInfo reset_account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
 
   // Everything is back to its original state now.
   EXPECT_EQ(reset_account_info.is_child_account,
@@ -238,10 +226,7 @@
           account_id));
 
   AccountInfo account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
   EXPECT_EQ(account_info.account_id, account_id);
   EXPECT_EQ(account_info.email, kTestEmail);
   EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
@@ -271,10 +256,7 @@
       identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState(
           account_id));
   AccountInfo account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
   EXPECT_EQ(account_info.account_id, account_id);
   EXPECT_EQ(account_info.email, kTestEmail);
   EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
@@ -311,10 +293,7 @@
   // No new accounts should be created, just the information should be updated.
   EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
   AccountInfo updated_account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
   EXPECT_EQ(account_info.account_id, updated_account_info.account_id);
   EXPECT_EQ(account_info.gaia, updated_account_info.gaia);
   EXPECT_EQ(updated_account_info.email, maybe_updated_email);
@@ -387,10 +366,7 @@
   run_loop.Run();
 
   AccountInfo secondary_account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
   EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2U);
 
   // Now try invalidating the primary account, and check that it gets updated.
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc
index be965f0..42410f77 100644
--- a/components/signin/public/identity_manager/identity_manager.cc
+++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -522,16 +522,15 @@
   return ConvertToJavaCoreAccountInfo(env, account_info);
 }
 
-base::android::ScopedJavaLocalRef<jobject> IdentityManager::
-    FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-        JNIEnv* env,
-        const base::android::JavaParamRef<jstring>& j_email) const {
-  auto account_info =
-      FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-          base::android::ConvertJavaStringToUTF8(env, j_email));
-  if (!account_info.has_value())
+base::android::ScopedJavaLocalRef<jobject>
+IdentityManager::FindExtendedAccountInfoByEmailAddress(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jstring>& j_email) const {
+  AccountInfo account_info = FindExtendedAccountInfoByEmailAddress(
+      base::android::ConvertJavaStringToUTF8(env, j_email));
+  if (account_info.IsEmpty())
     return nullptr;
-  return ConvertToJavaAccountInfo(env, account_info.value());
+  return ConvertToJavaAccountInfo(env, account_info);
 }
 
 base::android::ScopedJavaLocalRef<jobjectArray>
diff --git a/components/signin/public/identity_manager/identity_manager.h b/components/signin/public/identity_manager/identity_manager.h
index 8e3a14a3..4be6706e 100644
--- a/components/signin/public/identity_manager/identity_manager.h
+++ b/components/signin/public/identity_manager/identity_manager.h
@@ -493,7 +493,7 @@
       JNIEnv* env) const;
 
   base::android::ScopedJavaLocalRef<jobject>
-  FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
+  FindExtendedAccountInfoByEmailAddress(
       JNIEnv* env,
       const base::android::JavaParamRef<jstring>& j_email) const;
 
diff --git a/components/signin/public/identity_manager/identity_test_utils.cc b/components/signin/public/identity_manager/identity_test_utils.cc
index 81c68a3..ae7a7ac 100644
--- a/components/signin/public/identity_manager/identity_test_utils.cc
+++ b/components/signin/public/identity_manager/identity_test_utils.cc
@@ -188,14 +188,13 @@
   CoreAccountInfo account_info =
       SetPrimaryAccount(identity_manager, email, consent_level);
   SetRefreshTokenForPrimaryAccount(identity_manager);
-  absl::optional<AccountInfo> primary_account_info =
-      identity_manager
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_info.account_id);
+  AccountInfo primary_account_info =
+      identity_manager->FindExtendedAccountInfoByAccountId(
+          account_info.account_id);
   // Ensure that extended information for the account is available after setting
   // the refresh token.
-  DCHECK(primary_account_info.has_value());
-  return primary_account_info.value();
+  DCHECK(!primary_account_info.IsEmpty());
+  return primary_account_info;
 }
 
 void RevokeSyncConsent(IdentityManager* identity_manager) {
diff --git a/components/strings/components_strings_am.xtb b/components/strings/components_strings_am.xtb
index 7610104..90e7e4b 100644
--- a/components/strings/components_strings_am.xtb
+++ b/components/strings/components_strings_am.xtb
@@ -1536,7 +1536,7 @@
 <translation id="6648524591329069940">ባለጭረት ቅርጸ-ቁምፊ</translation>
 <translation id="6651270836885078973">በሚከተለው የሚተዳደር ነው፦</translation>
 <translation id="6652101503459149953">Windows Helloን ይጠቀሙ</translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="666259744093848177">(x86_64 የተተረጎመ)</translation>
 <translation id="6665553082534466207">ሦስቴ ብስ ቀኝ</translation>
 <translation id="6671697161687535275">የአስተያየት ጥቆማ ከChromium ይወገድ?</translation>
diff --git a/components/strings/components_strings_bg.xtb b/components/strings/components_strings_bg.xtb
index 7f4e550..f98314d3 100644
--- a/components/strings/components_strings_bg.xtb
+++ b/components/strings/components_strings_bg.xtb
@@ -1025,6 +1025,7 @@
 <translation id="4731967714531604179">Prc2 (плик)</translation>
 <translation id="4733082559415072992"><ph name="URL" /> иска да използва местоположението на устройството ви</translation>
 <translation id="4736825316280949806">Рестартирайте Chromium.</translation>
+<translation id="4736934858538408121">Виртуална карта</translation>
 <translation id="473775607612524610">Актуализиране</translation>
 <translation id="4738601419177586157">Предложение за търсене на „<ph name="TEXT" />“</translation>
 <translation id="4742407542027196863">Управление на паролите…</translation>
diff --git a/components/strings/components_strings_bn.xtb b/components/strings/components_strings_bn.xtb
index 7c9dfec..4b9864bc 100644
--- a/components/strings/components_strings_bn.xtb
+++ b/components/strings/components_strings_bn.xtb
@@ -984,7 +984,7 @@
 <translation id="4515275063822566619">কার্ড ও ঠিকানাগুলি Chrome এবং আপনার Google অ্যাকাউন্ট (<ph name="ACCOUNT_EMAIL" />) থেকে এসেছে। আপনি <ph name="BEGIN_LINK" />সেটিংস<ph name="END_LINK" />এ গিয়ে সেগুলি পরিচালনা করতে পারবেন।</translation>
 <translation id="4517607026994743406">Comm-10 (Envelope)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> মিলিমিটার (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4522570452068850558">বিবরণগুলি</translation>
 <translation id="4524138615196389145">এখন থেকে WebAuthn ব্যবহার করে আপনার কার্ড আরও দ্রুত কনফার্ম করুন</translation>
 <translation id="4524805452350978254">কার্ড ম্যানেজ করুন</translation>
 <translation id="4542971377163063093">ট্রে ৬</translation>
diff --git a/components/strings/components_strings_el.xtb b/components/strings/components_strings_el.xtb
index b0c84e5..27a83cfb 100644
--- a/components/strings/components_strings_el.xtb
+++ b/components/strings/components_strings_el.xtb
@@ -1550,7 +1550,7 @@
 <translation id="6648524591329069940">Γραμματοσειρά Serif</translation>
 <translation id="6651270836885078973">Η διαχείριση γίνεται από:</translation>
 <translation id="6652101503459149953">Χρήση Windows Hello</translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="666259744093848177">(x86_64 μεταφρασμένο)</translation>
 <translation id="6665553082534466207">Τριπλό τρύπημα στα δεξιά</translation>
 <translation id="6671697161687535275">Να καταργηθεί η πρόταση φόρμας από το Chromium;</translation>
diff --git a/components/strings/components_strings_hr.xtb b/components/strings/components_strings_hr.xtb
index 3b7fb913..4547803 100644
--- a/components/strings/components_strings_hr.xtb
+++ b/components/strings/components_strings_hr.xtb
@@ -983,7 +983,7 @@
 <translation id="4515275063822566619">Kartice i adrese dolaze iz Cromea i vašeg Google računa (<ph name="ACCOUNT_EMAIL" />). Njima možete upravljati u <ph name="BEGIN_LINK" />Postavkama<ph name="END_LINK" />.</translation>
 <translation id="4517607026994743406">Comm-10 (omotnica)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Detalji</translation>
+<translation id="4522570452068850558">Pojedinosti</translation>
 <translation id="4524138615196389145">Odsad brže potvrdite kartice upotrebom značajke WebAuthn</translation>
 <translation id="4524805452350978254">Upravljanje karticama</translation>
 <translation id="4542971377163063093">Ladica 6</translation>
diff --git a/components/strings/components_strings_km.xtb b/components/strings/components_strings_km.xtb
index 6ecc1c4..b8ff55b49 100644
--- a/components/strings/components_strings_km.xtb
+++ b/components/strings/components_strings_km.xtb
@@ -1033,6 +1033,7 @@
 <translation id="4731967714531604179">Prc2 (ស្រោម​សំបុត្រ)</translation>
 <translation id="4733082559415072992"><ph name="URL" /> ចង់ប្រើ​ទីតាំង​ឧបករណ៍​របស់អ្នក</translation>
 <translation id="4736825316280949806">ចាប់ផ្តើម Chromium ឡើងវិញ</translation>
+<translation id="4736934858538408121">កាតនិម្មិត</translation>
 <translation id="473775607612524610">ធ្វើបច្ចុប្បន្នភាព</translation>
 <translation id="4738601419177586157">ការណែនាំ​ការស្វែងរក <ph name="TEXT" /></translation>
 <translation id="4742407542027196863">គ្រប់គ្រង​ពាក្យ​សម្ងាត់…</translation>
diff --git a/components/strings/components_strings_lv.xtb b/components/strings/components_strings_lv.xtb
index 834c2951..34bdb9c 100644
--- a/components/strings/components_strings_lv.xtb
+++ b/components/strings/components_strings_lv.xtb
@@ -980,7 +980,7 @@
 <translation id="4515275063822566619">Kartes un adreses tiek iegūtas no Chrome un jūsu Google konta (<ph name="ACCOUNT_EMAIL" />). Varat tās pārvaldīt <ph name="BEGIN_LINK" />iestatījumos<ph name="END_LINK" />.</translation>
 <translation id="4517607026994743406">Comm-10 (aploksne)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Informācija</translation>
+<translation id="4522570452068850558">Dati</translation>
 <translation id="4524138615196389145">Turpmāk, izmantojot WebAuthn, apstipriniet kartes ātrāk</translation>
 <translation id="4524805452350978254">Pārvaldīt kartītes</translation>
 <translation id="4542971377163063093">6. paplāte</translation>
diff --git a/components/strings/components_strings_mn.xtb b/components/strings/components_strings_mn.xtb
index f3b49b0..d3f3492 100644
--- a/components/strings/components_strings_mn.xtb
+++ b/components/strings/components_strings_mn.xtb
@@ -1030,6 +1030,7 @@
 <translation id="4731967714531604179">Prc2 (Дугтуй)</translation>
 <translation id="4733082559415072992"><ph name="URL" /> таны төхөөрөмжийн байршлыг ашиглах хүсэлтэй байна</translation>
 <translation id="4736825316280949806">Chromium-г дахин эхлүүлэх</translation>
+<translation id="4736934858538408121">Виртуал карт</translation>
 <translation id="473775607612524610">Шинэчлэх</translation>
 <translation id="4738601419177586157"><ph name="TEXT" />-н хайлтын зөвлөмж</translation>
 <translation id="4742407542027196863">Нууц үгийг удирдах...</translation>
diff --git a/components/strings/components_strings_my.xtb b/components/strings/components_strings_my.xtb
index 6f9037ee..714b7dd2 100644
--- a/components/strings/components_strings_my.xtb
+++ b/components/strings/components_strings_my.xtb
@@ -1029,6 +1029,7 @@
 <translation id="4731967714531604179">Prc2 (စာအိတ်)</translation>
 <translation id="4733082559415072992"><ph name="URL" /> သည် သင့်စက်၏ တည်နေရာကို အသုံးပြုလိုသည်</translation>
 <translation id="4736825316280949806">Chromium ကို ပိတ်ပြီးပြန်ဖွင့်ပါ</translation>
+<translation id="4736934858538408121">ပကတိအသွင်ကတ်</translation>
 <translation id="473775607612524610">အပ်ဒိတ်လုပ်ရန်</translation>
 <translation id="4738601419177586157"><ph name="TEXT" /> ရှာဖွေမှု အကြံပြုချက်</translation>
 <translation id="4742407542027196863">စကားဝှက်များ စီမံရန်…</translation>
diff --git a/components/strings/components_strings_ro.xtb b/components/strings/components_strings_ro.xtb
index f5cf8f08..7ab5177 100644
--- a/components/strings/components_strings_ro.xtb
+++ b/components/strings/components_strings_ro.xtb
@@ -2033,7 +2033,7 @@
 <translation id="8490137692873530638">Receptorul de hârtie 10</translation>
 <translation id="8498891568109133222"><ph name="HOST_NAME" /> a răspuns prea târziu.</translation>
 <translation id="8503559462189395349">Parole Chrome</translation>
-<translation id="8503813439785031346">Nume utilizator</translation>
+<translation id="8503813439785031346">Nume de utilizator</translation>
 <translation id="8507227106804027148">Linie de comandă</translation>
 <translation id="8508648098325802031">Pictograma Căutare</translation>
 <translation id="8511402995811232419">Gestionează cookie-urile</translation>
diff --git a/components/strings/components_strings_ru.xtb b/components/strings/components_strings_ru.xtb
index e178ad5..96eeac79 100644
--- a/components/strings/components_strings_ru.xtb
+++ b/components/strings/components_strings_ru.xtb
@@ -971,7 +971,7 @@
 <translation id="4515275063822566619">Это карты и адреса, указанные в Chrome и вашем аккаунте Google (<ph name="ACCOUNT_EMAIL" />). Вы можете изменить их на странице <ph name="BEGIN_LINK" />Настройки<ph name="END_LINK" />.</translation>
 <translation id="4517607026994743406">Comm-10 (конверт)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> мм (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4522570452068850558">Детали</translation>
 <translation id="4524138615196389145">Подтверждайте карты быстрее с помощью WebAuthn</translation>
 <translation id="4524805452350978254">Изменить</translation>
 <translation id="4542971377163063093">Лоток 6</translation>
diff --git a/components/strings/components_strings_sv.xtb b/components/strings/components_strings_sv.xtb
index 7a247a4..07072d9b 100644
--- a/components/strings/components_strings_sv.xtb
+++ b/components/strings/components_strings_sv.xtb
@@ -983,7 +983,7 @@
 <translation id="4515275063822566619">Kort och adresser har hämtats från Chrome och ditt Google-konto (<ph name="ACCOUNT_EMAIL" />). Du hanterar dessa under <ph name="BEGIN_LINK" />Inställningar<ph name="END_LINK" />.</translation>
 <translation id="4517607026994743406">Comm-10 (kuvert)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Info</translation>
+<translation id="4522570452068850558">Detaljer</translation>
 <translation id="4524138615196389145">Verifiera kreditkort snabbare genom att använda WebAuthn från och med nu</translation>
 <translation id="4524805452350978254">Hantera kort</translation>
 <translation id="4542971377163063093">Fack 6</translation>
diff --git a/components/strings/components_strings_th.xtb b/components/strings/components_strings_th.xtb
index e2d0ecf0..f01513a6 100644
--- a/components/strings/components_strings_th.xtb
+++ b/components/strings/components_strings_th.xtb
@@ -1183,7 +1183,7 @@
 <translation id="5299298092464848405">ข้อผิดพลาดในการแยกวิเคราะห์นโยบาย</translation>
 <translation id="5300589172476337783">แสดง</translation>
 <translation id="5306593769196050043">ทั้ง 2 แผ่นงาน</translation>
-<translation id="5307166000025436103">ตกลง</translation>
+<translation id="5307166000025436103">ปกติ</translation>
 <translation id="5308380583665731573">เชื่อมต่อ</translation>
 <translation id="5308689395849655368">การรายงานข้อขัดข้องถูกปิดใช้งาน</translation>
 <translation id="5314967030527622926">เครื่องทำจุลสาร</translation>
diff --git a/components/strings/components_strings_uz.xtb b/components/strings/components_strings_uz.xtb
index 74f8697b..7e590cc1 100644
--- a/components/strings/components_strings_uz.xtb
+++ b/components/strings/components_strings_uz.xtb
@@ -1024,6 +1024,7 @@
 <translation id="4731967714531604179">Prc2 (Envelope)</translation>
 <translation id="4733082559415072992"><ph name="URL" /> sayti qurilmangiz joylashuvidan foydalanmoqchi</translation>
 <translation id="4736825316280949806">Chromium’ni qayta ishga tushiring</translation>
+<translation id="4736934858538408121">Virtual karta</translation>
 <translation id="473775607612524610">Yangilash</translation>
 <translation id="4738601419177586157"><ph name="TEXT" /> qidiruv taklifi</translation>
 <translation id="4742407542027196863">Parollarni boshqarish…</translation>
diff --git a/components/strings/components_strings_zh-CN.xtb b/components/strings/components_strings_zh-CN.xtb
index 6f94fb2..355ac4c8 100644
--- a/components/strings/components_strings_zh-CN.xtb
+++ b/components/strings/components_strings_zh-CN.xtb
@@ -968,7 +968,7 @@
 <translation id="4515275063822566619">信用卡选项和地址选项均来自 Chrome 和您的 Google 帐号 (<ph name="ACCOUNT_EMAIL" />)。您可在<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />中管理这些选项。</translation>
 <translation id="4517607026994743406">Comm-10 (Envelope)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> 毫米(<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">详细信息</translation>
+<translation id="4522570452068850558">详情</translation>
 <translation id="4524138615196389145">从现在开始,您只需使用 WebAuthn 便能更快速地确认银行卡</translation>
 <translation id="4524805452350978254">管理卡片</translation>
 <translation id="4542971377163063093">纸匣 6</translation>
diff --git a/components/strings/components_strings_zh-HK.xtb b/components/strings/components_strings_zh-HK.xtb
index b3ae8aa4..38c0757 100644
--- a/components/strings/components_strings_zh-HK.xtb
+++ b/components/strings/components_strings_zh-HK.xtb
@@ -2023,7 +2023,7 @@
 <translation id="8490137692873530638">堆疊器 10</translation>
 <translation id="8498891568109133222"><ph name="HOST_NAME" /> 的回應時間過長。</translation>
 <translation id="8503559462189395349">Chrome 密碼</translation>
-<translation id="8503813439785031346">使用者名稱</translation>
+<translation id="8503813439785031346">用戶名稱</translation>
 <translation id="8507227106804027148">指令列</translation>
 <translation id="8508648098325802031">搜尋圖示</translation>
 <translation id="8511402995811232419">管理 Cookie</translation>
diff --git a/components/strings/components_strings_zh-TW.xtb b/components/strings/components_strings_zh-TW.xtb
index 70b747a..1e494ab 100644
--- a/components/strings/components_strings_zh-TW.xtb
+++ b/components/strings/components_strings_zh-TW.xtb
@@ -972,7 +972,7 @@
 <translation id="4515275063822566619">信用卡和地址資訊皆來自 Chrome 和你的 Google 帳戶 (<ph name="ACCOUNT_EMAIL" />)。你可以在<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />頁面管理這些資訊。</translation>
 <translation id="4517607026994743406">Comm-10 (信封)</translation>
 <translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> 公釐 (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4522570452068850558">詳細資料</translation>
 <translation id="4524138615196389145">現在就開始使用 WebAuthn,加快卡片驗證速度</translation>
 <translation id="4524805452350978254">管理卡片</translation>
 <translation id="4542971377163063093">紙匣 6</translation>
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc
index 783d96a..8a8f7419 100644
--- a/components/user_manager/known_user.cc
+++ b/components/user_manager/known_user.cc
@@ -743,11 +743,12 @@
     return;
 
   ListPrefUpdate update(local_state_, kKnownUsers);
-  for (size_t i = 0; i < update->GetSize(); ++i) {
+  base::Value::ListView update_view = update->GetList();
+  for (auto it = update_view.begin(); it != update_view.end(); ++it) {
     base::DictionaryValue* element = nullptr;
-    if (update->GetDictionary(i, &element)) {
+    if (it->GetAsDictionary(&element)) {
       if (UserMatches(account_id, *element)) {
-        update->Remove(i, nullptr);
+        update->EraseListIter(it);
         break;
       }
     }
diff --git a/components/viz/service/display_embedder/software_output_device_ozone.cc b/components/viz/service/display_embedder/software_output_device_ozone.cc
index 140dd76..c411f517 100644
--- a/components/viz/service/display_embedder/software_output_device_ozone.cc
+++ b/components/viz/service/display_embedder/software_output_device_ozone.cc
@@ -30,7 +30,7 @@
 
   viewport_pixel_size_ = viewport_pixel_size;
 
-  surface_ozone_->ResizeCanvas(viewport_pixel_size_);
+  surface_ozone_->ResizeCanvas(viewport_pixel_size_, scale_factor);
 }
 
 SkCanvas* SoftwareOutputDeviceOzone::BeginPaint(const gfx::Rect& damage_rect) {
diff --git a/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc b/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
index f5c8d98..d8ddd83 100644
--- a/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
+++ b/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
@@ -36,7 +36,7 @@
 
   // ui::SurfaceOzoneCanvas override:
   SkCanvas* GetCanvas() override { return surface_->getCanvas(); }
-  void ResizeCanvas(const gfx::Size& viewport_size) override {
+  void ResizeCanvas(const gfx::Size& viewport_size, float scale) override {
     surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
         viewport_size.width(), viewport_size.height()));
   }
diff --git a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
index a5bb4093..85909322 100644
--- a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
+++ b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
@@ -431,6 +431,7 @@
 
  protected:
   void SetUp() override {
+    DirectSocketsServiceImpl::SetConnectionDialogBypassForTesting(true);
     DirectSocketsServiceImpl::SetEnterpriseManagedForTesting(false);
 
     embedded_test_server()->AddDefaultHandlers(GetTestDataFilePath());
@@ -507,6 +508,42 @@
       DirectSocketsServiceImpl::FailureType::kCORS, 1);
 }
 
+// Permission Denied failures(user dialog) should be triggered if connection
+// dialog is not accepted.
+IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest,
+                       OpenTcp_ConnectionDialogNotAccepted) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+
+  base::HistogramTester histogram_tester;
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      DirectSocketsServiceImpl::FailureType::kUserDialog, 0);
+
+  DirectSocketsServiceImpl::SetConnectionDialogBypassForTesting(false);
+
+  const std::string script =
+      "openTcp({remoteAddress: '127.0.0.1', remotePort: 993})";
+
+  EXPECT_EQ("openTcp failed: NotAllowedError: Permission denied",
+            EvalJs(shell(), script));
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      DirectSocketsServiceImpl::FailureType::kUserDialog, 1);
+}
+
+// Remote address should be provided or TEST will fail with NotAllowedError. In
+// actual use scenario, it can be obtained from the user's input in connection
+// dialog.
+IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest,
+                       OpenTcp_RemoteAddressCurrentlyRequired) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+
+  const std::string script = "openTcp({remotePort: 993})";
+
+  EXPECT_EQ("openTcp failed: NotAllowedError: Permission denied",
+            EvalJs(shell(), script));
+}
+
 IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest,
                        OpenTcp_RestrictedByEnterprisePolicies) {
   EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
@@ -688,6 +725,42 @@
       DirectSocketsServiceImpl::FailureType::kCORS, 1);
 }
 
+// Permission Denied failures(user dialog) should be triggered if connection
+// dialog is not accepted.
+IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest,
+                       OpenUdp_ConnectionDialogNotAccepted) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+
+  base::HistogramTester histogram_tester;
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      DirectSocketsServiceImpl::FailureType::kUserDialog, 0);
+
+  DirectSocketsServiceImpl::SetConnectionDialogBypassForTesting(false);
+
+  const std::string script =
+      "openUdp({remoteAddress: '127.0.0.1', remotePort: 993})";
+
+  EXPECT_EQ("openUdp failed: NotAllowedError: Permission denied",
+            EvalJs(shell(), script));
+  histogram_tester.ExpectBucketCount(
+      kPermissionDeniedHistogramName,
+      DirectSocketsServiceImpl::FailureType::kUserDialog, 1);
+}
+
+// Remote address should be provided or TEST will fail with NotAllowedError. In
+// actual use scenario, it can be obtained from the user's input in connection
+// dialog.
+IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest,
+                       OpenUdp_RemoteAddressCurrentlyRequired) {
+  EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
+
+  const std::string script = "openUdp({remotePort: 993})";
+
+  EXPECT_EQ("openUdp failed: NotAllowedError: Permission denied",
+            EvalJs(shell(), script));
+}
+
 IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest,
                        OpenUdp_RestrictedByEnterprisePolicies) {
   EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL()));
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc
index fd979f22..ae346d8 100644
--- a/content/browser/direct_sockets/direct_sockets_service_impl.cc
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -16,6 +16,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "mojo/public/cpp/system/data_pipe.h"
@@ -52,6 +53,8 @@
         }
       )");
 
+bool g_connection_dialog_bypass_for_testing = false;
+
 absl::optional<bool> g_is_enterprise_managed_for_testing;
 
 constexpr int32_t kMaxBufferSize = 32 * 1024 * 1024;
@@ -86,6 +89,33 @@
   return local_addr;
 }
 
+net::Error ValidateAddressAndPort(blink::mojom::DirectSocketOptions& options,
+                                  const std::string& address,
+                                  const std::string& port) {
+  // This check only ensures that the user has indeed input something. The
+  // verification of the address is done through class ResolveHostAndOpenSocket.
+  if (!address.empty())
+    options.remote_hostname = address;
+
+  if (!options.remote_hostname)
+    return net::ERR_NAME_NOT_RESOLVED;
+
+  uint32_t remote_port;
+  if (!port.empty() && base::StringToUint(port, &remote_port) &&
+      base::IsValueInRangeForNumericType<uint16_t>(remote_port)) {
+    options.remote_port = static_cast<uint16_t>(remote_port);
+  }
+
+  if (options.remote_port == 443) {
+    base::UmaHistogramEnumeration(kPermissionDeniedHistogramName,
+                                  DirectSocketsServiceImpl::FailureType::kCORS);
+    // TODO(crbug.com/1119601): Issue a CORS preflight request.
+    return net::ERR_UNSAFE_PORT;
+  }
+
+  return net::OK;
+}
+
 #if BUILDFLAG(ENABLE_MDNS)
 bool ResemblesMulticastDNSName(const std::string& hostname) {
   return base::EndsWith(hostname, ".local") ||
@@ -349,16 +379,9 @@
     mojo::ReportBadMessage("Insufficient isolation to open socket.");
     return;
   }
-  network::mojom::NetworkContext* const network_context = GetNetworkContext();
-  if (!options || !network_context) {
-    mojo::ReportBadMessage("Invalid request to open socket");
-    return;
-  }
 
   const net::Error result = ValidateOptions(*options);
 
-  // TODO(crbug.com/1119681): Collect metrics for usage and permission checks
-
   if (result != net::OK) {
     std::move(callback).Run(result, absl::nullopt, absl::nullopt,
                             mojo::ScopedDataPipeConsumerHandle(),
@@ -366,10 +389,16 @@
     return;
   }
 
-  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenSocket(
-      weak_ptr_factory_.GetWeakPtr(), std::move(options), std::move(receiver),
-      std::move(observer), std::move(callback));
-  resolver->Start(network_context);
+  std::string remote_hostname;
+  if (options->remote_hostname)
+    remote_hostname = *options->remote_hostname;
+
+  GetContentClient()->browser()->ShowDirectSocketsConnectionDialog(
+      frame_host_, remote_hostname,
+      base::BindOnce(&DirectSocketsServiceImpl::OnDialogProceedTcp,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(options),
+                     std::move(receiver), std::move(observer),
+                     std::move(callback)));
 }
 
 void DirectSocketsServiceImpl::OpenUdpSocket(
@@ -383,11 +412,6 @@
     mojo::ReportBadMessage("Insufficient isolation to open socket.");
     return;
   }
-  network::mojom::NetworkContext* const network_context = GetNetworkContext();
-  if (!options || !network_context) {
-    mojo::ReportBadMessage("Invalid request to open socket");
-    return;
-  }
 
   const net::Error result = ValidateOptions(*options);
 
@@ -396,12 +420,16 @@
     return;
   }
 
-  // TODO(crbug.com/1119681): Collect metrics for usage and permission checks
+  std::string remote_hostname;
+  if (options->remote_hostname)
+    remote_hostname = *options->remote_hostname;
 
-  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenSocket(
-      weak_ptr_factory_.GetWeakPtr(), std::move(options), std::move(receiver),
-      std::move(listener), std::move(callback));
-  resolver->Start(network_context);
+  GetContentClient()->browser()->ShowDirectSocketsConnectionDialog(
+      frame_host_, remote_hostname,
+      base::BindOnce(&DirectSocketsServiceImpl::OnDialogProceedUdp,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(options),
+                     std::move(receiver), std::move(listener),
+                     std::move(callback)));
 }
 
 // static
@@ -412,6 +440,12 @@
 }
 
 // static
+void DirectSocketsServiceImpl::SetConnectionDialogBypassForTesting(
+    bool bypass) {
+  g_connection_dialog_bypass_for_testing = bypass;
+}
+
+// static
 void DirectSocketsServiceImpl::SetEnterpriseManagedForTesting(
     bool enterprise_managed) {
   g_is_enterprise_managed_for_testing = enterprise_managed;
@@ -490,22 +524,78 @@
   }
 
   // TODO(crbug.com/1119659): Check permissions policy.
-  // TODO(crbug.com/1119600): Implement rate limiting.
-
-  if (options.remote_port == 443) {
-    base::UmaHistogramEnumeration(kPermissionDeniedHistogramName,
-                                  FailureType::kCORS);
-    // TODO(crbug.com/1119601): Issue a CORS preflight request.
-    return net::ERR_UNSAFE_PORT;
-  }
-
-  // ValidateOptions() will need to become asynchronous:
-  // TODO(crbug.com/1119597): Show connection dialog.
-  // TODO(crbug.com/1119597): Use the hostname provided by the user.
-  if (!options.remote_hostname)
-    return net::ERR_NAME_NOT_RESOLVED;
 
   return net::OK;
 }
 
+void DirectSocketsServiceImpl::OnDialogProceedTcp(
+    blink::mojom::DirectSocketOptionsPtr options,
+    mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
+    mojo::PendingRemote<network::mojom::SocketObserver> observer,
+    OpenTcpSocketCallback callback,
+    bool accepted,
+    const std::string& address,
+    const std::string& port) {
+  if (!accepted && !g_connection_dialog_bypass_for_testing) {
+    base::UmaHistogramEnumeration(kPermissionDeniedHistogramName,
+                                  FailureType::kUserDialog);
+    std::move(callback).Run(net::ERR_ABORTED, absl::nullopt, absl::nullopt,
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
+    return;
+  }
+
+  network::mojom::NetworkContext* const network_context = GetNetworkContext();
+  if (!network_context) {
+    mojo::ReportBadMessage("Invalid request to open socket");
+    return;
+  }
+
+  const net::Error result = ValidateAddressAndPort(*options, address, port);
+  if (result != net::OK) {
+    std::move(callback).Run(result, absl::nullopt, absl::nullopt,
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
+    return;
+  }
+
+  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenSocket(
+      weak_ptr_factory_.GetWeakPtr(), std::move(options), std::move(receiver),
+      std::move(observer), std::move(callback));
+  resolver->Start(network_context);
+}
+
+void DirectSocketsServiceImpl::OnDialogProceedUdp(
+    blink::mojom::DirectSocketOptionsPtr options,
+    mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver,
+    mojo::PendingRemote<network::mojom::UDPSocketListener> listener,
+    OpenUdpSocketCallback callback,
+    bool accepted,
+    const std::string& address,
+    const std::string& port) {
+  if (!accepted && !g_connection_dialog_bypass_for_testing) {
+    base::UmaHistogramEnumeration(kPermissionDeniedHistogramName,
+                                  FailureType::kUserDialog);
+    std::move(callback).Run(net::ERR_ABORTED, absl::nullopt, absl::nullopt);
+    return;
+  }
+
+  network::mojom::NetworkContext* const network_context = GetNetworkContext();
+  if (!network_context) {
+    mojo::ReportBadMessage("Invalid request to open socket");
+    return;
+  }
+
+  const net::Error result = ValidateAddressAndPort(*options, address, port);
+  if (result != net::OK) {
+    std::move(callback).Run(result, absl::nullopt, absl::nullopt);
+    return;
+  }
+
+  ResolveHostAndOpenSocket* resolver = new ResolveHostAndOpenSocket(
+      weak_ptr_factory_.GetWeakPtr(), std::move(options), std::move(receiver),
+      std::move(listener), std::move(callback));
+  resolver->Start(network_context);
+}
+
 }  // namespace content
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.h b/content/browser/direct_sockets/direct_sockets_service_impl.h
index cc9394d3..fa6c048 100644
--- a/content/browser/direct_sockets/direct_sockets_service_impl.h
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.h
@@ -84,6 +84,8 @@
 
   static net::MutableNetworkTrafficAnnotationTag TrafficAnnotation();
 
+  static void SetConnectionDialogBypassForTesting(bool bypass);
+
   static void SetEnterpriseManagedForTesting(bool enterprise_managed);
 
   static void SetPermissionCallbackForTesting(PermissionCallback callback);
@@ -101,6 +103,24 @@
   // Returns net::OK if the options are valid and the connection is permitted.
   net::Error ValidateOptions(const blink::mojom::DirectSocketOptions& options);
 
+  // DirectSocketsRequestDialogController:
+  void OnDialogProceedTcp(
+      blink::mojom::DirectSocketOptionsPtr options,
+      mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
+      mojo::PendingRemote<network::mojom::SocketObserver> observer,
+      OpenTcpSocketCallback callback,
+      bool accepted,
+      const std::string& address,
+      const std::string& port);
+  void OnDialogProceedUdp(
+      blink::mojom::DirectSocketOptionsPtr options,
+      mojo::PendingReceiver<blink::mojom::DirectUDPSocket> receiver,
+      mojo::PendingRemote<network::mojom::UDPSocketListener> listener,
+      OpenUdpSocketCallback callback,
+      bool accepted,
+      const std::string& address,
+      const std::string& port);
+
   RenderFrameHost* frame_host_;
   mojo::UniqueReceiverSet<blink::mojom::DirectUDPSocket>
       direct_udp_socket_receivers_;
diff --git a/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc b/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc
index 00ca6bd6..6fce8e4 100644
--- a/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc
+++ b/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc
@@ -272,6 +272,7 @@
 
  protected:
   void SetUp() override {
+    DirectSocketsServiceImpl::SetConnectionDialogBypassForTesting(true);
     DirectSocketsServiceImpl::SetEnterpriseManagedForTesting(false);
 
     embedded_test_server()->AddDefaultHandlers(GetTestDataFilePath());
diff --git a/content/browser/direct_sockets/direct_sockets_unittest.cc b/content/browser/direct_sockets/direct_sockets_unittest.cc
index dcdaa38..bc87637 100644
--- a/content/browser/direct_sockets/direct_sockets_unittest.cc
+++ b/content/browser/direct_sockets/direct_sockets_unittest.cc
@@ -15,10 +15,6 @@
 #include "net/base/net_errors.h"
 #include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"
 
-#if defined(OS_WIN)
-#include "base/win/win_util.h"
-#endif
-
 namespace content {
 
 class DirectSocketsUnitTest : public RenderViewHostTestHarness {
@@ -74,17 +70,6 @@
   EXPECT_EQ(ValidateOptions(options), net::ERR_CONTEXT_SHUT_DOWN);
 }
 
-// TODO(crbug.com/1119597): Allow the user to enter the address.
-TEST_F(DirectSocketsUnitTest, RemoteAddressCurrentlyRequired) {
-// Mark as not enterprise managed.
-#if defined(OS_WIN)
-  base::win::ScopedDomainStateForTesting scoped_domain(false);
-#endif
-
-  blink::mojom::DirectSocketOptions options;
-  EXPECT_EQ(ValidateOptions(options), net::ERR_NAME_NOT_RESOLVED);
-}
-
 TEST_F(DirectSocketsUnitTest, PopulateLocalAddr) {
   blink::mojom::DirectSocketOptions options;
 
diff --git a/content/browser/prerender/prerender_browsertest.cc b/content/browser/prerender/prerender_browsertest.cc
index 10b36f7..8cf6649e 100644
--- a/content/browser/prerender/prerender_browsertest.cc
+++ b/content/browser/prerender/prerender_browsertest.cc
@@ -479,15 +479,14 @@
   EXPECT_FALSE(HasHostForUrl(kPrerenderingUrl));
 }
 
-// TODO(https://crbug.com/1214964): Test this case with speculationrules.
 // Tests that prerendering triggered by prerendered pages is deferred until
 // activation.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderChain) {
   // kInitialUrl prerenders kPrerenderChain1, then kPrerenderChain1 prerenders
   // kPrerenderChain2.
-  const GURL kInitialUrl = GetUrl("/prerender/prerender_chain.html?1");
-  const GURL kPrerenderChain1 = GetUrl("/prerender/prerender_chain.html?2");
-  const GURL kPrerenderChain2 = GetUrl("/prerender/prerender_chain.html?3");
+  const GURL kInitialUrl = GetUrl("/empty.html");
+  const GURL kPrerenderChain1 = GetUrl("/prerender/prerender_chain.html?1");
+  const GURL kPrerenderChain2 = GetUrl("/prerender/prerender_chain.html?2");
 
   // Navigate to an initial page.
   ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
@@ -499,8 +498,16 @@
   EXPECT_TRUE(AddTestUtilJS(prerender_host));
 
   // Add a prerender trigger to the prerendering page.
-  ExecuteScriptAsync(prerender_host,
-                     JsReplace("add_prerender($1)", kPrerenderChain2));
+  EXPECT_TRUE(ExecJs(prerender_host,
+                     JsReplace("add_speculation_rules($1)", kPrerenderChain2)));
+
+  // Speculation rules is processed by the idle task runner in Blink. To ensure
+  // the speculation candidates has been sent by renderer processes, we should
+  // wait until this runner finishes all tasks.
+  EXPECT_TRUE(ExecJs(prerender_host, R"(
+    const idlePromise = new Promise(resolve => requestIdleCallback(resolve));
+    idlePromise;
+  )"));
 
   // Start a navigation request that should not be deferred, and wait it to
   // reach the server. If the prerender request for kPrerenderChain2 is not
@@ -508,7 +515,8 @@
   // earlier than the non-deferred one, so we can wait until the latest request
   // reaches the sever to prove that the prerender request for kPrerenderChain2
   // is deferred.
-  ExecuteScriptAsync(prerender_host, "add_iframe_async('/title1.html')");
+  EXPECT_TRUE(ExecJs(prerender_host, "add_iframe_async('/title1.html')",
+                     EvalJsOptions::EXECUTE_SCRIPT_NO_RESOLVE_PROMISES));
   WaitForRequest(GetUrl("/title1.html"), 1);
 
   // The prerender requests were deferred by Mojo capability control, so
@@ -548,81 +556,6 @@
   shell()->Close();
 }
 
-// TODO(https://crbug.com/1214964): Test this case in
-// SpeculationRuleSetTest.DropUnrecognizedRules since non-http(s) speculation
-// candidates are ignored in Blink.
-// Tests that non-http(s) schemes are disallowed for prerendering.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, HttpToBlobUrl) {
-  base::HistogramTester histogram_tester;
-
-  const GURL kInitialUrl = GetUrl("/empty.html");
-  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
-
-  // Generate a Blob page and obtain a URL for the Blob page.
-  const char kCreateBlobUrlScript[] =
-      "URL.createObjectURL("
-      "new Blob([\"<h1>hello blob</h1>\"], { type: 'text/html' }));";
-  const std::string blob_url =
-      EvalJs(web_contents(), kCreateBlobUrlScript).ExtractString();
-  const GURL blob_gurl(blob_url);
-
-  // Add <link rel=prerender> that will prerender the Blob page.
-  test::PrerenderHostRegistryObserver observer(*web_contents_impl());
-  AddLinkRelPrerenderAsync(blob_gurl);
-  observer.WaitForTrigger(blob_gurl);
-
-  // A prerender host for the URL should not be registered.
-  EXPECT_FALSE(HasHostForUrl(blob_gurl));
-  histogram_tester.ExpectUniqueSample(
-      "Prerender.Experimental.PrerenderHostFinalStatus",
-      PrerenderHost::FinalStatus::kInvalidSchemeNavigation, 1);
-}
-
-// TODO(https://crbug.com/1214964): Test this case in
-// SpeculationRuleSetTest.DropUnrecognizedRules since non-http(s) speculation
-// candidates are ignored in Blink.
-// Tests that non-http(s) schemes are disallowed for prerendering.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, BlobUrlToBlobUrl) {
-  base::HistogramTester histogram_tester;
-
-  // Navigate to an initial page.
-  // This test can not use `about:blank` as the initial url because created
-  // blobs inside the page are populated as opaque and blob to blob prerendering
-  // are alerted as cross-origin prerendering.
-  const GURL kInitialUrl = GetUrl("/empty.html");
-  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
-
-  // Navigate to a dynamically constructed Blob page.
-  const char kCreateBlobUrlScript[] =
-      "URL.createObjectURL(new Blob([\"<script>"
-      "function add_prerender(url) {"
-      "  const link = document.createElement('link');"
-      "  link.rel = 'prerender';"
-      "  link.href= url;"
-      "  document.head.appendChild(link);"
-      "}"
-      "</script>\"], { type: 'text/html' }));";
-  const std::string initial_blob_url =
-      EvalJs(web_contents(), kCreateBlobUrlScript).ExtractString();
-  ASSERT_TRUE(NavigateToURL(shell(), GURL(initial_blob_url)));
-
-  // Create another Blob URL inside the Blob page.
-  const std::string blob_url =
-      EvalJs(web_contents(), kCreateBlobUrlScript).ExtractString();
-  const GURL blob_gurl(blob_url);
-
-  // Add <link rel=prerender> that will prerender the Blob page.
-  test::PrerenderHostRegistryObserver observer(*web_contents_impl());
-  EXPECT_TRUE(ExecJs(web_contents(), JsReplace("add_prerender($1)", blob_url)));
-  observer.WaitForTrigger(blob_gurl);
-
-  // A prerender host for the URL should not be registered.
-  EXPECT_FALSE(HasHostForUrl(blob_gurl));
-  histogram_tester.ExpectUniqueSample(
-      "Prerender.Experimental.PrerenderHostFinalStatus",
-      PrerenderHost::FinalStatus::kInvalidSchemeNavigation, 1);
-}
-
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SameOriginRedirection) {
   // Navigate to an initial page.
   const GURL kInitialUrl = GetUrl("/empty.html");
@@ -751,12 +684,15 @@
   const char kCurrentDocumentPrerenderingScript[] = "document.prerendering";
   const char kOnprerenderingchangeObservedScript[] =
       "onprerenderingchange_observed";
+  const char kActivationStartScript[] =
+      "performance.getEntriesByType('navigation')[0].activationStart";
   EXPECT_EQ(true,
             EvalJs(prerender_frame_host, kInitialDocumentPrerenderingScript));
   EXPECT_EQ(false,
             EvalJs(prerender_frame_host, kCurrentDocumentPrerenderingScript));
   EXPECT_EQ(true,
             EvalJs(prerender_frame_host, kOnprerenderingchangeObservedScript));
+  EXPECT_NE(0, EvalJs(prerender_frame_host, kActivationStartScript));
 
   RenderFrameHost* same_origin_render_frame_host =
       FindRenderFrameHost(*prerender_frame_host, kSameOriginSubframeUrl);
@@ -767,6 +703,7 @@
                           kCurrentDocumentPrerenderingScript));
   EXPECT_EQ(true, EvalJs(same_origin_render_frame_host,
                          kOnprerenderingchangeObservedScript));
+  EXPECT_NE(0, EvalJs(same_origin_render_frame_host, kActivationStartScript));
 
   RenderFrameHost* cross_origin_render_frame_host =
       FindRenderFrameHost(*prerender_frame_host, kCrossOriginSubframeUrl);
@@ -777,6 +714,7 @@
                           kCurrentDocumentPrerenderingScript));
   EXPECT_EQ(false, EvalJs(cross_origin_render_frame_host,
                           kOnprerenderingchangeObservedScript));
+  EXPECT_EQ(0, EvalJs(cross_origin_render_frame_host, kActivationStartScript));
 }
 
 // Makes sure that subframe navigations are deferred if cross-origin redirects
@@ -2433,8 +2371,7 @@
   // Increment the keep alive ref count of the renderer process to keep it alive
   // so it is reused on the back navigation below. The test checks that the
   // session storage state changed in the activated page is correctly propagated
-  // after a back navigation that uses an existing renderer process. (Note: This
-  // is not working correctly now.)
+  // after a back navigation that uses an existing renderer process.
   initial_process_host->IncrementKeepAliveRefCount();
 
   AddPrerender(kPrerenderingUrl);
@@ -2453,13 +2390,8 @@
   observer.Wait();
   EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), kInitialUrl);
 
-  // There is a known issue that when the initial renderer process is reused
-  // after the back navigation, the session storage state changed in the
-  // activated is not correctly propagated to the initial renderer process.
-  // TODO(crbug.com/1197383): Fix this issue.
   EXPECT_EQ(
-      // This should be "activated, initial".
-      "initial",
+      "activated, initial",
       EvalJs(current_frame_host(), "getSessionStorageKeys()").ExtractString());
 }
 
@@ -2623,13 +2555,8 @@
   // the test is testing what is intended.
   ASSERT_EQ(shell()->web_contents()->GetMainFrame(), main_frame.get());
 
-  // There is a known issue that when the initial renderer process is reused
-  // after the back navigation, the session storage state changed in the
-  // activated is not correctly propagated to the initial renderer process.
-  // TODO(crbug.com/1197383): Fix this issue.
   EXPECT_EQ(
-      // This should be "activated, initial".
-      "initial",
+      "activated, initial",
       EvalJs(current_frame_host(), "getSessionStorageKeys()").ExtractString());
 }
 
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index b7fa89e0..9db9a13 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -11574,6 +11574,41 @@
   EXPECT_EQ("GET", contents()->GetMainFrame()->last_http_method());
 }
 
+// Tests that doing a form submission that opens a new about:blank tab won't
+// crash.
+IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
+                       FormSubmissionToNewTab) {
+  GURL url_start(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), url_start));
+
+  // Create and submit a form that will create a new about:blank tab.
+  WebContentsAddedObserver web_contents_added_observer;
+  TestNavigationObserver navigation_observer(nullptr, 1);
+  navigation_observer.StartWatchingNewWebContents();
+  ASSERT_TRUE(ExecuteScript(contents(),
+                            R"(let form = document.createElement('form');
+                                 form.method = 'POST';
+                                 form.target = '_blank';
+                                 form.action = 'about:blank';
+                                 document.body.appendChild(form);
+                                 form.submit();)"));
+  WebContentsImpl* popup_contents = static_cast<WebContentsImpl*>(
+      web_contents_added_observer.GetWebContents());
+  navigation_observer.WaitForNavigationFinished();
+  EXPECT_EQ(GURL(url::kAboutBlankURL), popup_contents->GetLastCommittedURL());
+
+  // Ensure that the new tab committed the form submission to about:blank
+  // correctly.
+  NavigationControllerImpl& controller =
+      static_cast<NavigationControllerImpl&>(popup_contents->GetController());
+  EXPECT_EQ(1, controller.GetEntryCount());
+  NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
+  EXPECT_EQ(GURL(url::kAboutBlankURL), entry->GetURL());
+  EXPECT_TRUE(entry->GetHasPostData());
+  EXPECT_NE(entry->GetPostID(), -1);
+  EXPECT_EQ("POST", popup_contents->GetMainFrame()->last_http_method());
+}
+
 IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
                        FormSubmitServerRedirect) {
   NavigationControllerImpl& controller =
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 9dc530e..ef41602 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -887,36 +887,35 @@
     }
   }
 
-  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
-      frame_tree_node, std::move(common_params), std::move(navigation_params),
-      std::move(commit_params), browser_initiated,
-      false /* from_begin_navigation */, false /* is_for_commit */, frame_entry,
-      entry, std::move(navigation_ui_data), mojo::NullAssociatedRemote(),
-      rfh_restored_from_back_forward_cache, initiator_process_id,
-      was_opener_suppressed));
-
+  scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
   if (frame_entry) {
-    navigation_request->blob_url_loader_factory_ =
-        frame_entry->blob_url_loader_factory();
+    blob_url_loader_factory = frame_entry->blob_url_loader_factory();
 
-    if (navigation_request->common_params().url.SchemeIsBlob() &&
-        !navigation_request->blob_url_loader_factory_) {
+    if (common_params->url.SchemeIsBlob() && !blob_url_loader_factory) {
       // If this navigation entry came from session history then the blob
       // factory would have been cleared in
       // NavigationEntryImpl::ResetForCommit(). This is avoid keeping large
       // blobs alive unnecessarily and the spec is unclear. So create a new blob
       // factory which will work if the blob happens to still be alive,
       // resolving the blob URL in the site instance it was loaded in.
-      navigation_request->blob_url_loader_factory_ =
+      blob_url_loader_factory =
           ChromeBlobStorageContext::URLLoaderFactoryForUrl(
               frame_tree_node->navigator()
                   .controller()
                   .GetBrowserContext()
                   ->GetStoragePartition(frame_entry->site_instance()),
-              navigation_request->common_params().url);
+              common_params->url);
     }
   }
 
+  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
+      frame_tree_node, std::move(common_params), std::move(navigation_params),
+      std::move(commit_params), browser_initiated,
+      false /* from_begin_navigation */, false /* is_for_commit */, frame_entry,
+      entry, std::move(navigation_ui_data), std::move(blob_url_loader_factory),
+      mojo::NullAssociatedRemote(), rfh_restored_from_back_forward_cache,
+      initiator_process_id, was_opener_suppressed));
+
   return navigation_request;
 }
 
@@ -1005,21 +1004,19 @@
 
   // `was_opener_suppressed` can be true for renderer initiated navigations, but
   // only in cases which get routed through `CreateBrowserInitiated()` instead.
-  std::unique_ptr<NavigationRequest> navigation_request(
-      new NavigationRequest(frame_tree_node, std::move(common_params),
-                            std::move(begin_params), std::move(commit_params),
-                            false,    // browser_initiated
-                            true,     // from_begin_navigation
-                            false,    // is_for_commit
-                            nullptr,  // frame_entry
-                            entry,
-                            nullptr,  // navigation_ui_data
-                            std::move(navigation_client),
-                            nullptr,  // rfh_restored_from_back_forward_cache
-                            initiator_process_id,
-                            /*was_opener_suppressed=*/false));
-  navigation_request->blob_url_loader_factory_ =
-      std::move(blob_url_loader_factory);
+  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
+      frame_tree_node, std::move(common_params), std::move(begin_params),
+      std::move(commit_params),
+      false,    // browser_initiated
+      true,     // from_begin_navigation
+      false,    // is_for_commit
+      nullptr,  // frame_entry
+      entry,
+      nullptr,  // navigation_ui_data
+      std::move(blob_url_loader_factory), std::move(navigation_client),
+      nullptr,  // rfh_restored_from_back_forward_cache
+      initiator_process_id,
+      /*was_opener_suppressed=*/false));
   navigation_request->prefetched_signed_exchange_cache_ =
       std::move(prefetched_signed_exchange_cache);
   navigation_request->web_bundle_handle_tracker_ =
@@ -1124,7 +1121,8 @@
       std::move(commit_params), false /* browser_initiated */,
       false /* from_begin_navigation */, true /* is_for_commit */,
       nullptr /* frame_navigation_entry */, nullptr /* navigation_entry */,
-      nullptr /* navigation_ui_data */, mojo::NullAssociatedRemote(),
+      nullptr /* navigation_ui_data */, nullptr /* blob_url_loader_factory */,
+      mojo::NullAssociatedRemote(),
       nullptr /* rfh_restored_from_back_forward_cache */,
       ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
       false /* was_opener_suppressed */));
@@ -1163,6 +1161,7 @@
     const FrameNavigationEntry* frame_entry,
     NavigationEntryImpl* entry,
     std::unique_ptr<NavigationUIData> navigation_ui_data,
+    scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
     mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
     RenderFrameHostImpl* rfh_restored_from_back_forward_cache,
     int initiator_process_id,
@@ -1174,6 +1173,7 @@
       commit_params_(std::move(commit_params)),
       browser_initiated_(browser_initiated),
       navigation_ui_data_(std::move(navigation_ui_data)),
+      blob_url_loader_factory_(std::move(blob_url_loader_factory)),
       restore_type_(entry ? entry->restore_type() : RestoreType::kNotRestored),
       // Some navigations, such as renderer-initiated subframe navigations,
       // won't have a NavigationEntryImpl. Set |reload_type_| if applicable
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index 582fdf3..d63388a 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -909,6 +909,7 @@
       const FrameNavigationEntry* frame_navigation_entry,
       NavigationEntryImpl* navitation_entry,
       std::unique_ptr<NavigationUIData> navigation_ui_data,
+      scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
       mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
       RenderFrameHostImpl* rfh_restored_from_back_forward_cache,
       int initiator_process_id,
@@ -1361,7 +1362,7 @@
   std::unique_ptr<NavigationUIData> navigation_ui_data_;
 
   // URLLoaderFactory to facilitate loading blob URLs.
-  scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_;
+  const scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_;
 
   NavigationState state_ = NOT_STARTED;
   bool is_navigation_started_ = false;
diff --git a/content/browser/renderer_host/private_network_access_browsertest.cc b/content/browser/renderer_host/private_network_access_browsertest.cc
index 4eacafd4..f59a6c3 100644
--- a/content/browser/renderer_host/private_network_access_browsertest.cc
+++ b/content/browser/renderer_host/private_network_access_browsertest.cc
@@ -21,6 +21,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/resource_load_observer.h"
 #include "content/test/test_content_browser_client.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -703,6 +704,64 @@
             security_state->ip_address_space);
 }
 
+IN_PROC_BROWSER_TEST_F(PrivateNetworkAccessBrowserTest,
+                       ClientSecurityStateForCachedSecureLocalDocument) {
+  // Navigate to the cacheable document in order to cache it, then navigate
+  // away.
+  const GURL url = SecureLocalURL("/cachetime");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+  EXPECT_TRUE(NavigateToURL(shell(), SecureLocalURL(kDefaultPath)));
+
+  // Navigate to the cached document.
+  //
+  // NOTE: We do not use `NavigateToURL()`, nor `window.location.reload()`, as
+  // both of those seem to bypass the cache.
+  ResourceLoadObserver observer(shell());
+  EXPECT_TRUE(ExecJs(shell(), JsReplace("window.location.href = $1;", url)));
+  observer.WaitForResourceCompletion(url);
+
+  blink::mojom::ResourceLoadInfoPtr* info = observer.FindResource(url);
+  ASSERT_TRUE(info);
+  ASSERT_TRUE(*info);
+  EXPECT_TRUE((*info)->was_cached);
+
+  const network::mojom::ClientSecurityStatePtr security_state =
+      root_frame_host()->BuildClientSecurityState();
+  ASSERT_FALSE(security_state.is_null());
+  EXPECT_TRUE(security_state->is_web_secure_context);
+  EXPECT_EQ(network::mojom::IPAddressSpace::kLocal,
+            security_state->ip_address_space);
+}
+
+IN_PROC_BROWSER_TEST_F(PrivateNetworkAccessBrowserTest,
+                       ClientSecurityStateForCachedInsecurePublicDocument) {
+  // Navigate to the cacheable document in order to cache it, then navigate
+  // away.
+  const GURL url = InsecurePublicURL("/cachetime");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+  EXPECT_TRUE(NavigateToURL(shell(), SecureLocalURL(kDefaultPath)));
+
+  // Navigate to the cached document.
+  //
+  // NOTE: We do not use `NavigateToURL()`, nor `window.location.reload()`, as
+  // both of those seem to bypass the cache.
+  ResourceLoadObserver observer(shell());
+  EXPECT_TRUE(ExecJs(shell(), JsReplace("window.location.href = $1;", url)));
+  observer.WaitForResourceCompletion(url);
+
+  blink::mojom::ResourceLoadInfoPtr* info = observer.FindResource(url);
+  ASSERT_TRUE(info);
+  ASSERT_TRUE(*info);
+  EXPECT_TRUE((*info)->was_cached);
+
+  const network::mojom::ClientSecurityStatePtr security_state =
+      root_frame_host()->BuildClientSecurityState();
+  ASSERT_FALSE(security_state.is_null());
+  EXPECT_FALSE(security_state->is_web_secure_context);
+  EXPECT_EQ(network::mojom::IPAddressSpace::kPublic,
+            security_state->ip_address_space);
+}
+
 // This test verifies that the chrome:// scheme is considered local for the
 // purpose of Private Network Access.
 IN_PROC_BROWSER_TEST_F(PrivateNetworkAccessBrowserTest,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index f90add2..601f43c 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8508,9 +8508,17 @@
   DCHECK(!is_notifying_activation_for_prerendering_);
   is_notifying_activation_for_prerendering_ = true;
 
+  // Currently cross origin iframes are deferred. So the origin must be same
+  // as the main frame's origin. But if we will decide not to defer the cross
+  // origin iframes, we need to remove the DCHECK_EQ and change the code not
+  // to send |activation_start_time_for_prerendering| to the renderer.
+  DCHECK_EQ(GetLastCommittedOrigin(), GetMainFrame()->GetLastCommittedOrigin());
+
   // Notify the renderer of activation to update the prerendering state and
   // dispatch the prerenderingchange event.
-  GetAssociatedLocalFrame()->ActivateForPrerendering();
+  GetAssociatedLocalFrame()->ActivateForPrerendering(
+      *GetMainFrame()
+           ->document_associated_data_->activation_start_time_for_prerendering);
 
   for (auto& child : children_)
     child->current_frame_host()->ActivateForPrerendering();
@@ -9609,6 +9617,25 @@
     DCHECK_EQ(navigation_request->is_overriding_user_agent() &&
                   frame_tree_node_->IsMainFrame(),
               params->is_overriding_user_agent);
+    if (navigation_request->IsPrerenderedPageActivation()) {
+      DCHECK(blink::features::IsPrerender2Enabled());
+      // Set the NavigationStart time for
+      // PerformanceNavigationTiming.activationStart.
+      // https://jeremyroman.github.io/alternate-loading-modes/#performance-navigation-timing-extension
+
+      // Currently, prerendering is only supported on same-origin pages. When
+      // supporting cross-origin prerendering (https://crbug.com/1176054), we
+      // need to change this CHECK to "if ()" not to send the activation start
+      // time to the prerendering page so that it is not used to send
+      // identifiers between origins.
+      CHECK_EQ(GetLastCommittedOrigin(),
+               navigation_request->GetOriginForURLLoaderFactory());
+      DCHECK(
+          !document_associated_data_->activation_start_time_for_prerendering);
+      document_associated_data_->activation_start_time_for_prerendering =
+          navigation_request->NavigationStart();
+    }
+
   } else {
     DCHECK_EQ(is_overriding_user_agent_, params->is_overriding_user_agent);
   }
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 59cd84d..2d5cc6e 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -3598,6 +3598,12 @@
     // The Page object associated with the main document. It is nullptr for
     // subframes.
     std::unique_ptr<PageImpl> owned_page;
+
+    // Prerender2:
+    // The activation start time for prerendering which is passed to the
+    // renderer process, and will be accessible in the prerendered page as
+    // PerformanceNavigationTiming.activationStart.
+    absl::optional<base::TimeTicks> activation_start_time_for_prerendering;
   };
 
   std::unique_ptr<DocumentAssociatedData> document_associated_data_;
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 4cb5e4c..cf913d6e 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -349,6 +349,14 @@
           coep_reporter_for_subresources.InitWithNewPipeAndPassReceiver());
     }
 
+    // Initialize the global scope now if the worker won't be paused. Otherwise,
+    // delay initialization until the main script is loaded.
+    if (!owner_version_->initialize_global_scope_after_main_script_loaded()) {
+      owner_version_->InitializeGlobalScope(
+          /*script_loader_factories=*/nullptr,
+          /*subresource_loader_factories=*/nullptr);
+    }
+
     // Register to DevTools and update params accordingly.
     const int routing_id = rph->GetNextRoutingID();
     ServiceWorkerDevToolsManager::GetInstance()->WorkerStarting(
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index ff652e8..0a4072a 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -159,7 +159,7 @@
     params->script_url = version->script_url();
     params->is_installed = false;
 
-    params->service_worker_receiver = CreateServiceWorker();
+    params->service_worker_receiver = CreateServiceWorker(version);
     params->controller_receiver = CreateController();
     params->installed_scripts_info = GetInstalledScriptsInfoPtr();
     params->provider_info = CreateProviderInfo(std::move(version));
@@ -176,9 +176,10 @@
     return provider_info;
   }
 
-  mojo::PendingReceiver<blink::mojom::ServiceWorker> CreateServiceWorker() {
-    service_workers_.emplace_back();
-    return service_workers_.back().BindNewPipeAndPassReceiver();
+  mojo::PendingReceiver<blink::mojom::ServiceWorker> CreateServiceWorker(
+      scoped_refptr<ServiceWorkerVersion> version) {
+    version->service_worker_remote_.reset();
+    return version->service_worker_remote_.BindNewPipeAndPassReceiver();
   }
 
   mojo::PendingReceiver<blink::mojom::ControllerServiceWorker>
@@ -206,7 +207,6 @@
   ServiceWorkerContextCore* context() { return helper_->context(); }
 
   // Mojo endpoints.
-  std::vector<mojo::Remote<blink::mojom::ServiceWorker>> service_workers_;
   std::vector<mojo::Remote<blink::mojom::ControllerServiceWorker>> controllers_;
   std::vector<mojo::Remote<blink::mojom::ServiceWorkerInstalledScriptsManager>>
       installed_scripts_managers_;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 47671fc..f75206fd 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -1023,7 +1023,9 @@
         script_loader_factories,
     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
         subresource_loader_factories) {
-  DCHECK(service_worker_host_);
+  receiver_.reset();
+  receiver_.Bind(service_worker_host_.InitWithNewEndpointAndPassReceiver());
+
   scoped_refptr<ServiceWorkerRegistration> registration =
       base::WrapRefCounted(context_->GetLiveRegistration(registration_id_));
   // The registration must exist since we keep a reference to it during
@@ -1894,15 +1896,6 @@
   CHECK(params->service_worker_receiver.is_valid());
   service_worker_remote_.set_disconnect_handler(
       base::BindOnce(&OnConnectionError, embedded_worker_->AsWeakPtr()));
-  receiver_.reset();
-  receiver_.Bind(service_worker_host_.InitWithNewEndpointAndPassReceiver());
-
-  // Initialize the global scope now if the worker won't be paused. Otherwise,
-  // delay initialization until the main script is loaded.
-  if (!initialize_global_scope_after_main_script_loaded_) {
-    InitializeGlobalScope(/*script_loader_factories=*/nullptr,
-                          /*subresource_loader_factories=*/nullptr);
-  }
 
   if (!controller_receiver_.is_valid()) {
     controller_receiver_ = remote_controller_.BindNewPipeAndPassReceiver();
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index a20ba228..58c5352 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -463,6 +463,10 @@
     force_bypass_cache_for_scripts_ = force_bypass_cache_for_scripts;
   }
 
+  bool initialize_global_scope_after_main_script_loaded() const {
+    return initialize_global_scope_after_main_script_loaded_;
+  }
+
   void set_initialize_global_scope_after_main_script_loaded() {
     DCHECK(!initialize_global_scope_after_main_script_loaded_);
     initialize_global_scope_after_main_script_loaded_ = true;
@@ -622,6 +626,15 @@
     reporting_observer_receiver_ = std::move(reporting_observer_receiver);
   }
 
+  // Initializes the global scope of the ServiceWorker on the renderer side.
+  // This is dependant on a number of internal members and should only be called
+  // at a few select points where those members are valid.
+  void InitializeGlobalScope(
+      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
+          script_loader_factories,
+      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
+          subresource_loader_factories);
+
  private:
   friend class base::RefCounted<ServiceWorkerVersion>;
   friend class EmbeddedWorkerInstanceTest;
@@ -891,12 +904,6 @@
                                  GetClientCallback callback,
                                  bool success);
 
-  void InitializeGlobalScope(
-      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
-          script_loader_factories,
-      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
-          subresource_loader_factories);
-
   // When ServiceWorkerTerminationOnNoControlle is enabled and there's no
   // controllee, update the idle delay if the worker is running and we don't
   // have to terminate the worker ASAP (e.g. for activation).
diff --git a/content/browser/speculation_rules/speculation_host_impl.cc b/content/browser/speculation_rules/speculation_host_impl.cc
index 5a531f5..bc94f32 100644
--- a/content/browser/speculation_rules/speculation_host_impl.cc
+++ b/content/browser/speculation_rules/speculation_host_impl.cc
@@ -8,11 +8,32 @@
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_client.h"
+#include "mojo/public/cpp/bindings/message.h"
 #include "third_party/blink/public/common/features.h"
 #include "url/origin.h"
 
 namespace content {
 
+namespace {
+
+// Returns true if all candidates pass the inspection.
+bool InspectCandidates(
+    std::vector<blink::mojom::SpeculationCandidatePtr>& candidates) {
+  for (auto& candidate : candidates) {
+    // These non-http candidates should be filtered out in Blink and
+    // SpeculationHostImpl should not see them. If SpeculationHostImpl receives
+    // non-http candidates, it may mean the renderer process has a bug
+    // or is compromised.
+    if (!candidate->url.SchemeIsHTTPOrHTTPS()) {
+      mojo::ReportBadMessage("SH_NON_HTTP");
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
 // static
 void SpeculationHostImpl::Bind(
     RenderFrameHost* frame_host,
@@ -47,6 +68,8 @@
 void SpeculationHostImpl::UpdateSpeculationCandidates(
     std::vector<blink::mojom::SpeculationCandidatePtr> candidates) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!InspectCandidates(candidates))
+    return;
 
   // Only handle messages from an active main frame.
   if (!render_frame_host()->IsActive())
diff --git a/content/browser/speculation_rules/speculation_host_impl_unittest.cc b/content/browser/speculation_rules/speculation_host_impl_unittest.cc
index 8d4fa924..359375ff 100644
--- a/content/browser/speculation_rules/speculation_host_impl_unittest.cc
+++ b/content/browser/speculation_rules/speculation_host_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/speculation_rules/speculation_host_impl.h"
 
+#include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/prerender/prerender_host_registry.h"
 #include "content/public/common/content_client.h"
@@ -12,6 +13,7 @@
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
+#include "mojo/public/cpp/system/functions.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom.h"
 
@@ -194,6 +196,34 @@
   EXPECT_TRUE(registry->FindHostByUrlForTesting(kFirstPrerenderingUrl));
 }
 
+// Tests that SpeculationHostImpl crash the renderer process if it receives
+// non-http prerender candidates.
+TEST_F(SpeculationHostImplTest, ReportNonHttpMessage) {
+  RenderFrameHostImpl* render_frame_host = GetRenderFrameHost();
+  PrerenderHostRegistry* registry = GetPrerenderHostRegistry();
+  mojo::Remote<blink::mojom::SpeculationHost> remote;
+  SpeculationHostImpl::Bind(render_frame_host,
+                            remote.BindNewPipeAndPassReceiver());
+
+  // Set up the error handler for bad mojo messages.
+  std::string bad_message_error;
+  mojo::SetDefaultProcessErrorHandler(
+      base::BindLambdaForTesting([&](const std::string& error) {
+        EXPECT_FALSE(error.empty());
+        EXPECT_TRUE(bad_message_error.empty());
+        bad_message_error = error;
+      }));
+
+  std::vector<blink::mojom::SpeculationCandidatePtr> candidates;
+  const GURL kPrerenderingUrl = GURL("blob:https://bar");
+  candidates.push_back(CreatePrerenderCandidate(kPrerenderingUrl));
+
+  remote->UpdateSpeculationCandidates(std::move(candidates));
+  remote.FlushForTesting();
+  EXPECT_EQ(bad_message_error, "SH_NON_HTTP");
+  EXPECT_FALSE(registry->FindHostByUrlForTesting(kPrerenderingUrl));
+}
+
 class TestSpeculationHostDelegate : public SpeculationHostDelegate {
  public:
   TestSpeculationHostDelegate() = default;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
index 84bfa4c..d3e7d40 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -18,6 +18,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.UrlUtils;
@@ -253,6 +254,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "https://crbug.com/1215897")
     public void test_ariaComboboxExpand() {
         performTest("aria-combo-box-expand.html", "aria-combo-box-expand-expected-android.txt");
     }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index dcc9c226..0959763 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -1241,4 +1241,12 @@
   return nullptr;
 }
 
+void ContentBrowserClient::ShowDirectSocketsConnectionDialog(
+    content::RenderFrameHost* owner,
+    const std::string& address,
+    base::OnceCallback<void(bool, const std::string&, const std::string&)>
+        callback) {
+  std::move(callback).Run(false, std::string(), std::string());
+}
+
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 09ce07d..7dd2b78 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -2071,6 +2071,17 @@
   // `render_frame_host`.
   virtual std::unique_ptr<SpeculationHostDelegate>
   CreateSpeculationHostDelegate(RenderFrameHost& render_frame_host);
+
+  // Allows the embedder to show a dialog that will be used to control whether a
+  // connection through the Direct Sockets API is permitted. If the connection
+  // is permitted, the remote address and port that the user input will be sent
+  // back to the caller through callback.
+  virtual void ShowDirectSocketsConnectionDialog(
+      RenderFrameHost* owner,
+      const std::string& address,
+      base::OnceCallback<void(bool accepted,
+                              const std::string& address,
+                              const std::string& port)> callback);
 };
 
 }  // namespace content
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc
index 7abe9743..ab9707b 100644
--- a/content/public/test/fake_local_frame.cc
+++ b/content/public/test/fake_local_frame.cc
@@ -158,7 +158,8 @@
     bool had_redirect,
     network::mojom::SourceLocationPtr source_location) {}
 
-void FakeLocalFrame::ActivateForPrerendering() {}
+void FakeLocalFrame::ActivateForPrerendering(base::TimeTicks activation_start) {
+}
 
 void FakeLocalFrame::BindDevToolsAgent(
     mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h
index 5b54027..701d32838 100644
--- a/content/public/test/fake_local_frame.h
+++ b/content/public/test/fake_local_frame.h
@@ -124,7 +124,7 @@
       const GURL& url_before_redirects,
       bool had_redirect,
       network::mojom::SourceLocationPtr source_location) override;
-  void ActivateForPrerendering() override;
+  void ActivateForPrerendering(base::TimeTicks activation_start) override;
   void BindDevToolsAgent(
       mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,
       mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver)
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 08d697c6..1b0dc099 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4901,7 +4901,7 @@
   CHECK(in_frame_tree_);
 
   // This might be the first navigation in this RenderFrame.
-  const bool first_navigation_in_frame = !had_started_any_navigation_;
+  const bool first_navigation_in_render_frame = !had_started_any_navigation_;
   had_started_any_navigation_ = true;
 
   // This method is only called for renderer initiated navigations, which
@@ -5059,14 +5059,46 @@
       mhtml_body_loader_client_.reset();
     }
 
-    // First navigation in a frame to an empty document must be handled
-    // synchronously.
-    bool is_first_real_empty_document_navigation =
+    // In certain cases, Blink re-navigates to about:blank when creating a new
+    // browsing context (when opening a new window or creating an iframe) and
+    // expects the navigation to complete synchronously.
+    // TODO(https://crbug.com/1215096): Remove the synchronous about:blank
+    // navigation.
+    bool should_do_synchronous_about_blank_navigation =
+        // Mainly a proxy for checking about:blank, even though it can match
+        // other things like about:srcdoc (or any empty document schemes that
+        // are registered).
+        // TODO(https://crbug.com/1215096): This should be changed to only check
+        // for about:blank because the navigation triggered by browsing context
+        // creation will always navigate to about:blank.
         WebDocumentLoader::WillLoadUrlAsEmpty(url) &&
-        !frame_->HasCommittedFirstRealLoad() && first_navigation_in_frame;
+        // The navigation method must be "GET". This is to avoid issues like
+        // https://crbug.com/1210653, where a form submits to about:blank
+        // targeting a new window using a POST. The browser never expects this
+        // to happen synchronously because it only expects the synchronous
+        // about:blank navigation to originate from browsing context creation,
+        // which will always be GET requests.
+        info->url_request.HttpMethod().Equals("GET") &&
+        // If the frame has committed or even started a navigation before, this
+        // navigation can't possibly be triggered by browsing context creation,
+        // which would have triggered the navigation synchronously as the first
+        // navigation in this frame. Note that we check both
+        // HasCommittedFirstRealLoad() and `first_navigation_in_render_frame`
+        // here because `first_navigation_in_render_frame` only tracks the state
+        // in this *RenderFrame*, so it will be true even if this navigation
+        // happens on a frame that has existed before in another process (e.g.
+        // an <iframe> pointing to a.com being navigated to a cross-origin
+        // about:blank document that happens in a new frame). Meanwhile,
+        // HasCommittedFirstRealLoad() tracks the state of the frame, so it will
+        // be true in the aforementioned case and we would not do a synchronous
+        // commit here.
+        !frame_->HasCommittedFirstRealLoad() &&
+        first_navigation_in_render_frame &&
+        // If this is a subframe history navigation that should be sent to the
+        // browser, don't commit it synchronously.
+        !is_history_navigation_in_new_child_frame;
 
-    if (is_first_real_empty_document_navigation &&
-        !is_history_navigation_in_new_child_frame) {
+    if (should_do_synchronous_about_blank_navigation) {
       for (auto& observer : observers_)
         observer.DidStartNavigation(url, info->navigation_type);
       SynchronouslyCommitAboutBlankForBug778318(std::move(info));
diff --git a/content/test/data/prerender/prerender_chain.html b/content/test/data/prerender/prerender_chain.html
index 962e1719..adc3c61 100644
--- a/content/test/data/prerender/prerender_chain.html
+++ b/content/test/data/prerender/prerender_chain.html
@@ -2,10 +2,12 @@
 <html>
 <head>
 <title>Prerender Chain Test</title>
-<link rel="prerender">
 <script>
-function add_prerender(url) {
-  document.getElementsByTagName('link')[0].href = url;
+function add_speculation_rules(url) {
+  const script = document.createElement('script');
+  script.type = 'speculationrules';
+  script.text = `{"prerender": [{"source": "list", "urls": ["${url}"] }] }`;
+  document.head.appendChild(script);
 }
 </script>
 </head>
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index 36b23e4a..2866204 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -424,3 +424,7 @@
 crbug.com/852089 [ win7 ] Pixel_WebGPUImportWebGLCanvas [ Skip ]
 crbug.com/852089 [ win7 ] Pixel_WebGPUImport2DCanvas [ Skip ]
 crbug.com/852089 [ win7 ] Pixel_WebGPUImportUnaccelerated2DCanvas [ Skip ]
+
+# Flaky on Pixel 4
+crbug.com/1215747 [ android android-pixel-4 skia-renderer-gl ] Pixel_OffscreenCanvasWebGLDefault [ RetryOnFailure ]
+
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index c545f222..f76f573c 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -106,11 +106,6 @@
 # VP9 videos fail to trigger zero copy video presentation path.
 crbug.com/930343 [ win intel ] VideoPathTraceTest_DirectComposition_Video_VP9_Fullsize [ Failure ]
 
-# TODO(crbug.com/1079393): Compress down to just "intel" instead of specific
-# GPUs once UHD 630 failures are fixed.
-crbug.com/969117 [ win10 intel-0x5912 ] OverlayModeTraceTest_DirectComposition_Video_MP4_FourColors_Aspect_4x3 [ RetryOnFailure ]
-crbug.com/978181 [ win10 nvidia ] OverlayModeTraceTest_DirectComposition_Underlay [ RetryOnFailure ]
-
 # Incorrectly reporting SCALING instead of DIRECT on Windows 10 UHD 630 GPUs.
 crbug.com/1079393 [ win10 intel-0x3e92 ] OverlayModeTraceTest_DirectComposition_Underlay [ Failure ]
 crbug.com/1079393 [ win10 intel-0x3e92 ] OverlayModeTraceTest_DirectComposition_Underlay_DXVA [ Failure ]
@@ -139,11 +134,6 @@
 # showing up as SOFTWARE which causes zero copy to fail.
 crbug.com/1079393 [ win10 intel-0x5912 ] OverlayModeTraceTest_DirectComposition_Video_MP4_NV12 [ Failure ]
 crbug.com/1079393 [ win10 intel-0x5912 ] OverlayModeTraceTest_DirectComposition_Video_VP9_NV12 [ Failure ]
-crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Underlay_Fullsize [ Failure ]
-crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_Fullsize [ Failure ]
-
-# Fuchsia Flakes.
-crbug.com/1058255 [ fuchsia ] TraceTest_WebGLGreenTriangle_AA_Alpha [ Failure ]
 
 # Software compositing is not supported on Android/ChromeOS/Fuchsia: we skip the
 # tests that disable GPU compositing (--disable-gpu-compositing).
@@ -171,10 +161,6 @@
 crbug.com/1151767 [ win10 amd-0x7340 ] VideoPathTraceTest_DirectComposition_Video_MP4_YUY2 [ Failure ]
 crbug.com/1151767 [ win10 amd-0x7340 ] VideoPathTraceTest_DirectComposition_Video_VP9_YUY2 [ Failure ]
 
-# Flakes on Linux
-crbug.com/1209284 [ linux nvidia-0x1cb3 skia-renderer-gl ] TraceTest_WebGLPreservedAfterTabSwitch [ RetryOnFailure ]
-crbug.com/1209284 [ linux nvidia-0x1cb3 skia-renderer-gl ] TraceTest_WebGLReadPixelsTabSwitch [ RetryOnFailure ]
-
 # WebGPU pixel tests hang on mac bots which mostly run older versions of mac os.
 crbug.com/1213170 [ mac ] TraceTest_WebGPUImportWebGLCanvas [ Skip ]
 crbug.com/1213170 [ mac ] TraceTest_WebGPUImport2DCanvas [ Skip ]
diff --git a/ios/chrome/app/strings/resources/ios_strings_am.xtb b/ios/chrome/app/strings/resources/ios_strings_am.xtb
index 26279a1d..4741292 100644
--- a/ios/chrome/app/strings/resources/ios_strings_am.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_am.xtb
@@ -570,7 +570,7 @@
 <translation id="6643016212128521049">አጽዳ</translation>
 <translation id="6645899968535965230">የQR ኮድ፦ <ph name="PAGE_TITLE" /></translation>
 <translation id="6656103420185847513">አቃፊ ያርትዑ</translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6668619169535738264">እልባትን አርትዕ</translation>
 <translation id="6672241253012342409">ጣቢያዎች የአሰሳዎን ተሞክሮ ለማሻሻል፣ ለምሳሌ እርስዎ በመለያ እንደገቡ ለማቆየት ወይም በግዢ ጋሪዎ ውስጥ ንጥሎችን ለማስታወስ ኩኪዎችን መጠቀም ይችላሉ።
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_el.xtb b/ios/chrome/app/strings/resources/ios_strings_el.xtb
index 37c3ddc72..adaaf39 100644
--- a/ios/chrome/app/strings/resources/ios_strings_el.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_el.xtb
@@ -571,7 +571,7 @@
 <translation id="6643016212128521049">Διαγραφή</translation>
 <translation id="6645899968535965230">Κωδικός QR: <ph name="PAGE_TITLE" /></translation>
 <translation id="6656103420185847513">Επεξεργασία φακέλου</translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6668619169535738264">Επεξεργασία σελιδοδείκτη</translation>
 <translation id="6672241253012342409">Οι ιστότοποι μπορούν να χρησιμοποιούν cookie για να βελτιώσουν την εμπειρία περιήγησής σας, για παράδειγμα, για να παραμείνετε συνδεδεμένοι ή να διατηρηθούν τα προϊόντα στο καλάθι αγορών σας.
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_ro.xtb b/ios/chrome/app/strings/resources/ios_strings_ro.xtb
index a638dea1..8b5cc87 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ro.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ro.xtb
@@ -747,7 +747,7 @@
 <translation id="8487700953926739672">Disponibil offline</translation>
 <translation id="8490978609246021741">Salvează modificările</translation>
 <translation id="8495097701594799854">Dezactivată de organizație.</translation>
-<translation id="8503813439785031346">Nume utilizator</translation>
+<translation id="8503813439785031346">Nume de utilizator</translation>
 <translation id="850600235656508448">Deschide în modul incognito</translation>
 <translation id="8510057420705599706">Astfel, te vei deconecta și vei dezactiva sincronizarea, dar marcajele, istoricul, parolele și alte date Chrome vor rămâne pe acest dispozitiv.</translation>
 <translation id="8517375800490286174">Licențe open source</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb b/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
index e34d1afe..3832a33 100644
--- a/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_zh-HK.xtb
@@ -745,7 +745,7 @@
 <translation id="8487700953926739672">可離線使用</translation>
 <translation id="8490978609246021741">儲存變更</translation>
 <translation id="8495097701594799854">已由您的機構關閉。</translation>
-<translation id="8503813439785031346">使用者名稱</translation>
+<translation id="8503813439785031346">用戶名稱</translation>
 <translation id="850600235656508448">以無痕模式開啟</translation>
 <translation id="8510057420705599706">此操作會將您登出並關閉同步處理功能,但您的書籤、記錄、密碼和其他 Chrome 資料會繼續保留在此裝置上。</translation>
 <translation id="8517375800490286174">開放原始碼授權</translation>
diff --git a/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm b/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm
index 5590220..5d145af 100644
--- a/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm
+++ b/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm
@@ -371,10 +371,8 @@
       IdentityManagerFactory::GetForBrowserState(browser_state_);
   if (!identity_manager)
     return AccountInfo();
-  absl::optional<AccountInfo> primary_account_info =
-      identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
-          identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync));
-  return primary_account_info.value_or(AccountInfo());
+  return identity_manager->FindExtendedAccountInfo(
+      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync));
 }
 
 AccountInfo ChromePasswordProtectionService::GetSignedInNonSyncAccount(
@@ -396,9 +394,7 @@
   if (account_iterator == signed_in_accounts.end())
     return AccountInfo();
 
-  return identity_manager
-      ->FindExtendedAccountInfoForAccountWithRefreshToken(*account_iterator)
-      .value_or(AccountInfo());
+  return identity_manager->FindExtendedAccountInfo(*account_iterator);
 }
 
 LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
diff --git a/ios/chrome/browser/signin/authentication_service.mm b/ios/chrome/browser/signin/authentication_service.mm
index 91a5a321..03eaa86 100644
--- a/ios/chrome/browser/signin/authentication_service.mm
+++ b/ios/chrome/browser/signin/authentication_service.mm
@@ -58,12 +58,7 @@
     signin::IdentityManager* identity_manager,
     ChromeIdentity* identity) {
   std::string gaia_id = base::SysNSStringToUTF8([identity gaiaID]);
-  auto maybe_account =
-      identity_manager
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(gaia_id);
-  AccountInfo account_info =
-      maybe_account.has_value() ? maybe_account.value() : AccountInfo();
-  return account_info.account_id;
+  return identity_manager->FindExtendedAccountInfoByGaiaId(gaia_id).account_id;
 }
 
 }  // namespace
@@ -261,12 +256,10 @@
   // from the SSO library and that hosted_domain is set (should be the proper
   // hosted domain or kNoHostedDomainFound that are both non-empty strings).
   CHECK(identity_manager_->HasAccountWithRefreshToken(account_id));
-  const absl::optional<AccountInfo> account_info =
-      identity_manager_
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
-              account_id);
-  CHECK(account_info.has_value());
-  CHECK(!account_info->hosted_domain.empty());
+  const AccountInfo account_info =
+      identity_manager_->FindExtendedAccountInfoByAccountId(account_id);
+  CHECK(!account_info.IsEmpty());
+  CHECK(!account_info.hosted_domain.empty());
 
   // |PrimaryAccountManager::SetAuthenticatedAccountId| simply ignores the call
   // if there is already a signed in user. Check that there is no signed in
@@ -551,12 +544,8 @@
 }
 
 bool AuthenticationService::IsAuthenticatedIdentityManaged() const {
-  absl::optional<AccountInfo> primary_account_info =
-      identity_manager_->FindExtendedAccountInfoForAccountWithRefreshToken(
-          identity_manager_->GetPrimaryAccountInfo(
-              signin::ConsentLevel::kSignin));
-  if (!primary_account_info)
-    return false;
-
-  return primary_account_info->IsManaged();
+  return identity_manager_
+      ->FindExtendedAccountInfo(identity_manager_->GetPrimaryAccountInfo(
+          signin::ConsentLevel::kSignin))
+      .IsManaged();
 }
diff --git a/ios/chrome/browser/signin/authentication_service_unittest.mm b/ios/chrome/browser/signin/authentication_service_unittest.mm
index aa9cb2e..8aee847 100644
--- a/ios/chrome/browser/signin/authentication_service_unittest.mm
+++ b/ios/chrome/browser/signin/authentication_service_unittest.mm
@@ -179,10 +179,7 @@
 
   std::string user_email = base::SysNSStringToUTF8([identity(0) userEmail]);
   AccountInfo account_info =
-      identity_manager()
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-              user_email)
-          .value();
+      identity_manager()->FindExtendedAccountInfoByEmailAddress(user_email);
   EXPECT_EQ(user_email, account_info.email);
   EXPECT_EQ(base::SysNSStringToUTF8([identity(0) gaiaID]), account_info.gaia);
   EXPECT_TRUE(
diff --git a/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm b/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm
index 9403df3..b2b18f58 100644
--- a/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm
+++ b/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm
@@ -263,13 +263,13 @@
           ->IsAuthenticatedIdentityManaged()) {
     signin::IdentityManager* identity_manager =
         IdentityManagerFactory::GetForBrowserState(browserState);
-    absl::optional<AccountInfo> primary_account_info =
-        identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
+    AccountInfo primary_account_info =
+        identity_manager->FindExtendedAccountInfo(
             identity_manager->GetPrimaryAccountInfo(
                 signin::ConsentLevel::kSync));
-    DCHECK(primary_account_info);
+    DCHECK(!primary_account_info.IsEmpty());
     NSString* hostedDomain =
-        base::SysUTF8ToNSString(primary_account_info->hosted_domain);
+        base::SysUTF8ToNSString(primary_account_info.hosted_domain);
     [self promptSwitchFromManagedEmail:lastSignedInEmail
                       withHostedDomain:hostedDomain
                                toEmail:[identity userEmail]
diff --git a/ios/chrome/browser/ui/authentication/authentication_ui_util.mm b/ios/chrome/browser/ui/authentication/authentication_ui_util.mm
index 3a0d3b2..383bbf1 100644
--- a/ios/chrome/browser/ui/authentication/authentication_ui_util.mm
+++ b/ios/chrome/browser/ui/authentication/authentication_ui_util.mm
@@ -27,13 +27,11 @@
 std::u16string HostedDomainForPrimaryAccount(Browser* browser) {
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForBrowserState(browser->GetBrowserState());
-  absl::optional<AccountInfo> account_info =
-      identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
-          identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync));
-  std::string hosted_domain = account_info.has_value()
-                                  ? account_info.value().hosted_domain
-                                  : std::string();
-  return base::UTF8ToUTF16(hosted_domain);
+  return base::UTF8ToUTF16(
+      identity_manager
+          ->FindExtendedAccountInfo(identity_manager->GetPrimaryAccountInfo(
+              signin::ConsentLevel::kSync))
+          .hosted_domain);
 }
 
 AlertCoordinator* ErrorCoordinator(NSError* error,
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_utils.mm b/ios/chrome/browser/ui/authentication/signin/signin_utils.mm
index 4e49313a..a4ba192 100644
--- a/ios/chrome/browser/ui/authentication/signin/signin_utils.mm
+++ b/ios/chrome/browser/ui/authentication/signin/signin_utils.mm
@@ -116,12 +116,11 @@
   if (identities.count == 0)
     return false;
 
-  // Don't show the SSO promo if the default primary account is subject to
-  // minor mode restrictions.
-  absl::optional<bool> isSubjectToMinorModeRestrictions =
-      identity_service->IsSubjectToMinorModeRestrictions(identities[0]);
-  if (isSubjectToMinorModeRestrictions.has_value() &&
-      isSubjectToMinorModeRestrictions.value())
+  // Don't show the SSO promo if the default primary account is cannot display
+  // extended sync promos.
+  absl::optional<bool> canOfferExtendedSyncPromos =
+      identity_service->CanOfferExtendedSyncPromos(identities[0]);
+  if (!canOfferExtendedSyncPromos.value_or(true))
     return false;
 
   // The sign-in promo should be shown twice, even if no account has been added.
diff --git a/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.h b/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.h
index 2abb28d..ae5f51bb 100644
--- a/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.h
+++ b/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.h
@@ -25,8 +25,8 @@
   SyncedBookmarksObserverBridge(id<SyncObserverModelBridge> delegate,
                                 ChromeBrowserState* browserState);
   ~SyncedBookmarksObserverBridge() override;
-  // Returns true if user is signed in.
-  bool IsSignedIn();
+  // Returns true if the user has consented to sync.
+  bool HasSyncConsent();
   // Returns true if it is undergoing the first sync cycle.
   bool IsPerformingInitialSync();
 
diff --git a/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.mm b/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.mm
index 5798f836..bfd380b9 100644
--- a/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.mm
+++ b/ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.mm
@@ -33,12 +33,12 @@
 
 #pragma mark - Signin and syncing status
 
-bool SyncedBookmarksObserverBridge::IsSignedIn() {
+bool SyncedBookmarksObserverBridge::HasSyncConsent() {
   return identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync);
 }
 
 bool SyncedBookmarksObserverBridge::IsPerformingInitialSync() {
-  if (!IsSignedIn())
+  if (!HasSyncConsent())
     return false;
 
   SyncSetupService* sync_setup_service =
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
index 23cc009..abb31ecb 100644
--- a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
+++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
@@ -42,6 +42,9 @@
 
 - (void)viewDidLoad {
   self.bannerImage = [UIImage imageNamed:@"signin_screen_banner"];
+  self.isTallBanner = NO;
+  self.scrollToEndMandatory = YES;
+
   self.titleText = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_TITLE);
   self.subtitleText = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SUBTITLE);
   if (!self.primaryActionString) {
@@ -71,8 +74,6 @@
                                               .bottomAnchor],
   ]];
 
-  // TODO(crbug.com/1189836): Add the identity control to the wrapper view.
-
   // Call super after setting up the strings and others, as required per super
   // class.
   [super viewDidLoad];
@@ -110,11 +111,7 @@
 #pragma mark - SignInScreenConsumer
 
 - (void)setUserImage:(UIImage*)userImage {
-  if (userImage) {
-    [self.identityControl setIdentityAvatar:userImage];
-  } else {
-    // TODO(crbug.com/1189836): Update with default avatar.
-  }
+  [self.identityControl setIdentityAvatar:userImage];
 }
 
 - (void)setSelectedIdentityUserName:(NSString*)userName
diff --git a/ios/chrome/browser/ui/first_run/sync/BUILD.gn b/ios/chrome/browser/ui/first_run/sync/BUILD.gn
index 797d481..9882beb 100644
--- a/ios/chrome/browser/ui/first_run/sync/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/sync/BUILD.gn
@@ -43,3 +43,32 @@
   ]
   frameworks = [ "UIKit.framework" ]
 }
+
+source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "sync_screen_coordinator_unittest.mm",
+    "sync_screen_mediator_unittest.mm",
+  ]
+  deps = [
+    ":sync",
+    "//base/test:test_support",
+    "//components/consent_auditor:test_support",
+    "//components/sync/driver:test_support",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/main:test_support",
+    "//ios/chrome/browser/signin",
+    "//ios/chrome/browser/signin:test_support",
+    "//ios/chrome/browser/sync",
+    "//ios/chrome/browser/sync:test_support",
+    "//ios/chrome/browser/ui/first_run:screen_delegate",
+    "//ios/chrome/browser/unified_consent",
+    "//ios/public/provider/chrome/browser:test_support",
+    "//ios/public/provider/chrome/browser/signin:fake_chrome_identity",
+    "//ios/web/public/test",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/ocmock",
+  ]
+}
diff --git a/ios/chrome/browser/ui/first_run/sync/sync_screen_coordinator_unittest.mm b/ios/chrome/browser/ui/first_run/sync/sync_screen_coordinator_unittest.mm
new file mode 100644
index 0000000..d24e2fb4
--- /dev/null
+++ b/ios/chrome/browser/ui/first_run/sync/sync_screen_coordinator_unittest.mm
@@ -0,0 +1,62 @@
+// 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 "ios/chrome/browser/ui/first_run/sync/sync_screen_coordinator.h"
+
+#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/chrome/browser/main/test_browser.h"
+#import "ios/chrome/browser/signin/authentication_service_factory.h"
+#import "ios/chrome/browser/signin/authentication_service_fake.h"
+#import "ios/chrome/browser/ui/first_run/first_run_screen_delegate.h"
+#include "ios/public/provider/chrome/browser/test_chrome_browser_provider.h"
+#import "ios/web/public/test/web_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#include "third_party/ocmock/OCMock/OCMock.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// This class provides a hook for platform-specific operations across
+// SyncScreenCoordinator unit tests.
+class SyncScreenCoordinatorTest : public PlatformTest {
+ protected:
+  void SetUp() override {
+    PlatformTest::SetUp();
+
+    TestChromeBrowserState::Builder builder;
+    builder.AddTestingFactory(
+        AuthenticationServiceFactory::GetInstance(),
+        base::BindRepeating(
+            &AuthenticationServiceFake::CreateAuthenticationService));
+    browser_state_ = builder.Build();
+    WebStateList* web_state_list = nullptr;
+    browser_ =
+        std::make_unique<TestBrowser>(browser_state_.get(), web_state_list);
+
+    navigationController_ = [[UINavigationController alloc] init];
+    delegate_ = OCMProtocolMock(@protocol(FirstRunScreenDelegate));
+
+    coordinator_ = [[SyncScreenCoordinator alloc]
+        initWithBaseNavigationController:navigationController_
+                                 browser:browser_.get()
+                                delegate:delegate_];
+  }
+
+  web::WebTaskEnvironment task_environment_;
+  std::unique_ptr<Browser> browser_;
+  std::unique_ptr<TestChromeBrowserState> browser_state_;
+  SyncScreenCoordinator* coordinator_;
+  UINavigationController* navigationController_;
+  id delegate_;
+};
+
+// Tests that calling the delegate immidiately to stop the coordinator when
+// there's no user identity.
+TEST_F(SyncScreenCoordinatorTest, TestStartWithoutIdentity) {
+  OCMExpect([delegate_ willFinishPresenting]);
+  [coordinator_ start];
+}
diff --git a/ios/chrome/browser/ui/first_run/sync/sync_screen_mediator_unittest.mm b/ios/chrome/browser/ui/first_run/sync/sync_screen_mediator_unittest.mm
new file mode 100644
index 0000000..6833a26e
--- /dev/null
+++ b/ios/chrome/browser/ui/first_run/sync/sync_screen_mediator_unittest.mm
@@ -0,0 +1,107 @@
+// 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 "ios/chrome/browser/ui/first_run/sync/sync_screen_mediator.h"
+
+#import "components/consent_auditor/fake_consent_auditor.h"
+#import "components/sync/driver/mock_sync_service.h"
+#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/chrome/browser/main/test_browser.h"
+#import "ios/chrome/browser/signin/authentication_service_factory.h"
+#import "ios/chrome/browser/signin/authentication_service_fake.h"
+#import "ios/chrome/browser/signin/identity_manager_factory.h"
+#import "ios/chrome/browser/sync/consent_auditor_factory.h"
+#import "ios/chrome/browser/sync/sync_service_factory.h"
+#import "ios/chrome/browser/sync/sync_setup_service_factory.h"
+#import "ios/chrome/browser/sync/sync_setup_service_mock.h"
+#import "ios/chrome/browser/unified_consent/unified_consent_service_factory.h"
+#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
+#import "ios/web/public/test/web_task_environment.h"
+#import "testing/gmock/include/gmock/gmock.h"
+#import "testing/platform_test.h"
+#import "third_party/ocmock/gtest_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+std::unique_ptr<KeyedService> CreateMockSyncService(
+    web::BrowserState* context) {
+  return std::make_unique<syncer::MockSyncService>();
+}
+
+std::unique_ptr<KeyedService> CreateFakeConsentAuditor(
+    web::BrowserState* context) {
+  return std::make_unique<consent_auditor::FakeConsentAuditor>();
+}
+}  // namespace
+
+// This class provides a hook for platform-specific operations across
+// SyncScreenMediator unit tests.
+class SyncScreenMediatorTest : public PlatformTest {
+ protected:
+  void SetUp() override {
+    PlatformTest::SetUp();
+
+    TestChromeBrowserState::Builder builder;
+    builder.AddTestingFactory(
+        AuthenticationServiceFactory::GetInstance(),
+        base::BindRepeating(
+            &AuthenticationServiceFake::CreateAuthenticationService));
+    builder.AddTestingFactory(ConsentAuditorFactory::GetInstance(),
+                              base::BindRepeating(&CreateFakeConsentAuditor));
+    builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
+                              base::BindRepeating(&CreateMockSyncService));
+    builder.AddTestingFactory(
+        SyncSetupServiceFactory::GetInstance(),
+        base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService));
+    browser_state_ = builder.Build();
+
+    identity_ = [FakeChromeIdentity identityWithEmail:@"test@email.com"
+                                               gaiaID:@"gaiaID"
+                                                 name:@"Test Name"];
+
+    // Identity services.
+    AuthenticationService* authentication_service =
+        AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
+    authentication_service->SignIn(identity_);
+    signin::IdentityManager* identity_manager =
+        IdentityManagerFactory::GetForBrowserState(browser_state_.get());
+    consent_auditor::ConsentAuditor* consent_auditor =
+        ConsentAuditorFactory::GetForBrowserState(browser_state_.get());
+    unified_consent::UnifiedConsentService* unified_consent_service =
+        UnifiedConsentServiceFactory::GetForBrowserState(browser_state_.get());
+    SyncSetupService* sync_setup_service =
+        SyncSetupServiceFactory::GetForBrowserState(browser_state_.get());
+
+    mediator_ = [[SyncScreenMediator alloc]
+        initWithAuthenticationService:authentication_service
+                      identityManager:identity_manager
+                       consentAuditor:consent_auditor
+                unifiedConsentService:unified_consent_service
+                     syncSetupService:sync_setup_service];
+
+    sync_setup_service_mock_ =
+        static_cast<SyncSetupServiceMock*>(sync_setup_service);
+  }
+
+  void TearDown() override { PlatformTest::TearDown(); }
+
+  web::WebTaskEnvironment task_environment_;
+  SyncScreenMediator* mediator_;
+  FakeChromeIdentity* identity_;
+  std::unique_ptr<Browser> browser_;
+  std::unique_ptr<TestChromeBrowserState> browser_state_;
+  SyncSetupServiceMock* sync_setup_service_mock_;
+};
+
+// Tests that the FirstSetupComplete flag is turned on after the mediator has
+// started Sync.
+TEST_F(SyncScreenMediatorTest, TestStartSyncService) {
+  EXPECT_CALL(
+      *sync_setup_service_mock_,
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW));
+  [mediator_ startSync];
+}
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm
index fa00bbac..7c0f1909 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm
@@ -44,7 +44,7 @@
 - (SessionsSyncUserState)userSignedInState;
 // Utility functions for -userSignedInState so these can be mocked out
 // easily for unit tests.
-- (BOOL)isSignedIn;
+- (BOOL)hasSyncConsent;
 - (BOOL)isSyncTabsEnabled;
 - (BOOL)hasForeignSessions;
 - (BOOL)isSyncCompleted;
@@ -187,12 +187,12 @@
 
 #pragma mark - Private
 
-- (BOOL)isSignedIn {
-  return _syncedSessionsObserver->IsSignedIn();
+- (BOOL)hasSyncConsent {
+  return _syncedSessionsObserver->HasSyncConsent();
 }
 
 - (BOOL)isSyncTabsEnabled {
-  DCHECK([self isSignedIn]);
+  DCHECK([self hasSyncConsent]);
   SyncSetupService* service =
       SyncSetupServiceFactory::GetForBrowserState(_browserState);
   return !service->UserActionIsRequiredToHaveTabSyncWork();
@@ -200,7 +200,7 @@
 
 // Returns whether this profile has any foreign sessions to sync.
 - (SessionsSyncUserState)userSignedInState {
-  if (![self isSignedIn])
+  if (![self hasSyncConsent])
     return SessionsSyncUserState::USER_SIGNED_OUT;
   if (![self isSyncTabsEnabled])
     return SessionsSyncUserState::USER_SIGNED_IN_SYNC_OFF;
diff --git a/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.h b/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.h
index 6d1b587..5e132c0e 100644
--- a/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.h
+++ b/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.h
@@ -37,8 +37,8 @@
   void OnPrimaryAccountChanged(
       const signin::PrimaryAccountChangeEvent& event) override;
 
-  // Returns true if user is signed in.
-  bool IsSignedIn();
+  // Returns true if user has granted sync consent.
+  bool HasSyncConsent();
 
  private:
   void OnForeignSessionChanged();
diff --git a/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.mm b/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.mm
index 8fe73cf..5539fbc 100644
--- a/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.mm
+++ b/ios/chrome/browser/ui/recent_tabs/synced_sessions_bridge.mm
@@ -55,7 +55,7 @@
 
 #pragma mark - Signin and syncing status
 
-bool SyncedSessionsObserverBridge::IsSignedIn() {
+bool SyncedSessionsObserverBridge::HasSyncConsent() {
   return identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync);
 }
 
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 0384d7f..87aef74 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -262,6 +262,7 @@
     "//ios/chrome/browser/ui/fancy_ui:unit_tests",
     "//ios/chrome/browser/ui/first_run:unit_tests",
     "//ios/chrome/browser/ui/first_run/signin:unit_tests",
+    "//ios/chrome/browser/ui/first_run/sync:unit_tests",
     "//ios/chrome/browser/ui/fullscreen:unit_tests",
     "//ios/chrome/browser/ui/gestures:unit_tests",
     "//ios/chrome/browser/ui/history:unit_tests",
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
index 4079f613..e3f410d 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-308c1222a5841a6b1e740ef138661c2e78e55411
\ No newline at end of file
+74f26b6069b4e8166fab915ffcaf9df3ca65f2bc
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
index bed34cc..8dc1409 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-7dbc8546d35ea30b9e0b8016acefeb4504509d22
\ No newline at end of file
+9afa9743ed0d528ee1d07e03f556734fd81b87c5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
index 66b91055..4550cbe4 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-51358964a351d7d338d15e4277dfaa1ab5290cdd
\ No newline at end of file
+63ef4ffa6d0c6bd613de7f1011696a61ac3cc539
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
index 3aea314..de93bcf3 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-ddf75a6b7ffba63ce53a8643086e7c56fc2499ad
\ No newline at end of file
+c3e99ca14823c5ec0fb32cbddff8653ece7e1b75
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
index bf8486d..535a4e8 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-c28da05dccabaac292bcafa5b653baffa1504ad2
\ No newline at end of file
+66b6e4106a979ba78d7e6d2c5f03399b9e4a3e6f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
index c1f63ff..d34ab3e1 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-270788532b4f6185c4332417f518cae3116ac993
\ No newline at end of file
+720152502285633607d3229421db879f14a2a0be
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
index d1e77fb..c3dd7e7 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-7192703c3c70bb419336cdfd5047a2feb9c0f65b
\ No newline at end of file
+a50b8d176d51c429635dfb2d99729d3049585ff6
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
index 551239d0..1d69676 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-ac8ac98fc8e8b057d5d0bda88c25b65683512a73
\ No newline at end of file
+b6aaeb512599cc9b412e9629bad47da704aebd81
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
index 4c51a808..485a7675 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-5171111d6a38197c6171b66be8a4acfa023b53e0
\ No newline at end of file
+2630343a8c71f8b5b614eda3b9ab4c9d79eebddd
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
index b70aae47c0..c9c8f74 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-26e34d9e665a81a943895204ba1a3ae992623707
\ No newline at end of file
+e3b951ad1079099f2d8a6d73dec57e98b401202b
\ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
index e2cf88b6..f75b02cb 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -220,10 +220,10 @@
   virtual NSString* GetCachedHostedDomainForIdentity(ChromeIdentity* identity);
 
   // Returns the cached value of the account capability that determines whether
-  // Chrome should apply minor mode restrictions to |identity|.
+  // Chrome should offer extended sync promos to |identity|.
   // This value will have a refresh period of 24 hours, meaning that at
   // retrieval it may be stale or unpopulated, in the case of a fresh install.
-  virtual absl::optional<bool> IsSubjectToMinorModeRestrictions(
+  virtual absl::optional<bool> CanOfferExtendedSyncPromos(
       ChromeIdentity* identity);
 
   // Returns the MDM device status associated with |user_info|.
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
index 193ea26..657e145 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
@@ -120,7 +120,7 @@
   return nil;
 }
 
-absl::optional<bool> ChromeIdentityService::IsSubjectToMinorModeRestrictions(
+absl::optional<bool> ChromeIdentityService::CanOfferExtendedSyncPromos(
     ChromeIdentity* identity) {
   return absl::nullopt;
 }
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h
index 7b186a61..a93a6b7 100644
--- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h
+++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h
@@ -55,7 +55,7 @@
   virtual UIImage* GetCachedAvatarForIdentity(
       ChromeIdentity* identity) override;
 
-  virtual absl::optional<bool> IsSubjectToMinorModeRestrictions(
+  virtual absl::optional<bool> CanOfferExtendedSyncPromos(
       ChromeIdentity* identity) override;
 
   virtual void GetHostedDomainForIdentity(
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm
index 96548a7..9134b12f 100644
--- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm
+++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm
@@ -299,14 +299,13 @@
   return FakeGetHostedDomainForIdentity(identity);
 }
 
-absl::optional<bool>
-FakeChromeIdentityService::IsSubjectToMinorModeRestrictions(
+absl::optional<bool> FakeChromeIdentityService::CanOfferExtendedSyncPromos(
     ChromeIdentity* identity) {
   if (![identities_ containsObject:identity]) {
     return absl::nullopt;
   }
   return absl::make_optional(
-      [identity.userEmail hasSuffix:kMinorModeIdentityEmailSuffix]);
+      ![identity.userEmail hasSuffix:kMinorModeIdentityEmailSuffix]);
 }
 
 void FakeChromeIdentityService::SimulateForgetIdentityFromOtherApp(
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index c33cfef..b863c718 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -162,8 +162,12 @@
     web::NavigationItem* item = [[CRWNavigationItemHolder
         holderForBackForwardListItem:webView.backForwardList.currentItem]
         navigationItem];
-    if (item)
+    if (item) {
       item->SetUserAgentType(userAgentType);
+      if (web::wk_navigation_util::IsRestoreSessionUrl(item->GetURL())) {
+        self.webStateImpl->SetUserAgent(userAgentType);
+      }
+    }
   }
 
   if (userAgentType != web::UserAgentType::NONE) {
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/navigation_manager_impl.mm
index dbbe519..dd5419f 100644
--- a/ios/web/navigation/navigation_manager_impl.mm
+++ b/ios/web/navigation/navigation_manager_impl.mm
@@ -268,10 +268,15 @@
     // since it will be a duplicate.
     NavigationItemImpl* current_item =
         GetNavigationItemFromWKItem(current_wk_item);
+    ui::PageTransition transition = pending_item_->GetTransitionType();
     if (!current_item) {
       current_item = pending_item_.get();
       SetNavigationItemInWKItem(current_wk_item, std::move(pending_item_));
     }
+    // Updating the transition type of the item is needed, for example when
+    // doing a FormSubmit with a GET method on the same URL. See
+    // crbug.com/1211879.
+    current_item->SetTransitionType(transition);
 
     pending_item_.reset();
   }
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm
index fab6033..12fdb97 100644
--- a/ios/web/navigation/navigation_manager_impl_unittest.mm
+++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -704,6 +704,8 @@
       web::NavigationInitiationType::BROWSER_INITIATED);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
+  OCMStub([mock_web_view_ URL])
+      .andReturn([NSURL URLWithString:@"http://www.existing.com"]);
   navigation_manager()->CommitPendingItem();
 
   ASSERT_TRUE(navigation_manager()->GetLastCommittedItem());
@@ -730,6 +732,8 @@
       web::NavigationInitiationType::BROWSER_INITIATED);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
+  OCMStub([mock_web_view_ URL])
+      .andReturn([NSURL URLWithString:@"http://www.existing.com"]);
   navigation_manager()->CommitPendingItem();
 
   ASSERT_TRUE(navigation_manager()->GetLastCommittedItem());
@@ -746,6 +750,8 @@
   // NavigationManagerImpl assumes that AddPendingItem() is only called for
   // new navigation, so it always creates a new pending item.
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
+  EXPECT_EQ(navigation_manager()->GetPendingItem(),
+            navigation_manager()->GetLastCommittedItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_LINK));
@@ -762,6 +768,8 @@
       web::NavigationInitiationType::BROWSER_INITIATED);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
+  OCMStub([mock_web_view_ URL])
+      .andReturn([NSURL URLWithString:@"http://www.existing.com"]);
   navigation_manager()->CommitPendingItem();
 
   ASSERT_TRUE(navigation_manager()->GetLastCommittedItem());
@@ -776,6 +784,8 @@
       existing_url, Referrer(), ui::PAGE_TRANSITION_FORM_SUBMIT,
       web::NavigationInitiationType::BROWSER_INITIATED);
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
+  EXPECT_EQ(navigation_manager()->GetPendingItem(),
+            navigation_manager()->GetLastCommittedItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_FORM_SUBMIT));
@@ -791,6 +801,8 @@
       web::NavigationInitiationType::BROWSER_INITIATED);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
+  OCMStub([mock_web_view_ URL])
+      .andReturn([NSURL URLWithString:@"http://www.existing.com"]);
   navigation_manager()->CommitPendingItem();
 
   ASSERT_TRUE(navigation_manager()->GetLastCommittedItem());
@@ -806,6 +818,8 @@
   // NavigationManagerImpl assumes that AddPendingItem() is only called for
   // new navigation, so it always creates a new pending item.
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
+  EXPECT_EQ(navigation_manager()->GetPendingItem(),
+            navigation_manager()->GetLastCommittedItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_LINK));
@@ -821,6 +835,8 @@
       web::NavigationInitiationType::BROWSER_INITIATED);
 
   [mock_wk_list_ setCurrentURL:@"http://www.existing.com"];
+  OCMStub([mock_web_view_ URL])
+      .andReturn([NSURL URLWithString:@"http://www.existing.com"]);
   navigation_manager()->CommitPendingItem();
 
   ASSERT_TRUE(navigation_manager()->GetLastCommittedItem());
@@ -834,6 +850,8 @@
       web::NavigationInitiationType::BROWSER_INITIATED);
 
   ASSERT_TRUE(navigation_manager()->GetPendingItem());
+  EXPECT_EQ(navigation_manager()->GetPendingItem(),
+            navigation_manager()->GetLastCommittedItem());
   EXPECT_TRUE(ui::PageTransitionCoreTypeIs(
       navigation_manager()->GetPendingItem()->GetTransitionType(),
       ui::PAGE_TRANSITION_RELOAD));
diff --git a/media/base/content_decryption_module.h b/media/base/content_decryption_module.h
index 45bd5d1e..31e1c85 100644
--- a/media/base/content_decryption_module.h
+++ b/media/base/content_decryption_module.h
@@ -68,7 +68,7 @@
   kHdcpVersion2_1,
   kHdcpVersion2_2,
   kHdcpVersion2_3,
-  kHdcpVersionMax = kHdcpVersion2_3
+  kMaxValue = kHdcpVersion2_3
 };
 
 // An interface that represents the Content Decryption Module (CDM) in the
diff --git a/media/base/ipc/media_param_traits_macros.h b/media/base/ipc/media_param_traits_macros.h
index 6bedf46d..d8d4d9b 100644
--- a/media/base/ipc/media_param_traits_macros.h
+++ b/media/base/ipc/media_param_traits_macros.h
@@ -99,7 +99,7 @@
                           media::EncryptionScheme::kMaxValue)
 
 IPC_ENUM_TRAITS_MAX_VALUE(media::HdcpVersion,
-                          media::HdcpVersion::kHdcpVersionMax)
+                          media::HdcpVersion::kMaxValue)
 
 IPC_ENUM_TRAITS_MAX_VALUE(media::MediaContentType, media::MediaContentType::Max)
 
diff --git a/media/gpu/test/video.cc b/media/gpu/test/video.cc
index 46e82ea..76063a4 100644
--- a/media/gpu/test/video.cc
+++ b/media/gpu/test/video.cc
@@ -63,7 +63,6 @@
       << "An odd origin point is not supported";
   auto new_video = std::make_unique<Video>(file_path_, metadata_file_path_);
   new_video->frame_checksums_ = frame_checksums_;
-  new_video->thumbnail_checksums_ = thumbnail_checksums_;
   new_video->profile_ = profile_;
   new_video->codec_ = codec_;
   new_video->frame_rate_ = frame_rate_;
@@ -128,7 +127,6 @@
       << "The pixel format of source video is not I420";
   auto new_video = std::make_unique<Video>(file_path_, metadata_file_path_);
   new_video->frame_checksums_ = frame_checksums_;
-  new_video->thumbnail_checksums_ = thumbnail_checksums_;
   new_video->profile_ = profile_;
   new_video->codec_ = codec_;
   new_video->bit_depth_ = bit_depth_;
@@ -336,10 +334,6 @@
   return frame_checksums_;
 }
 
-const std::vector<std::string>& Video::ThumbnailChecksums() const {
-  return thumbnail_checksums_;
-}
-
 // static
 void Video::SetTestDataPath(const base::FilePath& test_data_path) {
   test_data_path_ = test_data_path;
@@ -499,18 +493,6 @@
     }
   }
 
-  // Find optional thumbnail checksums. These are only required when using the
-  // thumbnail test on older platforms that don't support the frame validator.
-  const base::Value* thumbnail_checksums =
-      metadata->FindKeyOfType("thumbnail_checksums", base::Value::Type::LIST);
-  if (thumbnail_checksums) {
-    for (const base::Value& checksum : thumbnail_checksums->GetList()) {
-      const std::string& checksum_str = checksum.GetString();
-      if (checksum_str.size() > 0 && checksum_str[0] != '#')
-        thumbnail_checksums_.push_back(checksum_str);
-    }
-  }
-
   return true;
 }
 
diff --git a/media/gpu/test/video.h b/media/gpu/test/video.h
index 3687d526..a6c402b 100644
--- a/media/gpu/test/video.h
+++ b/media/gpu/test/video.h
@@ -83,10 +83,6 @@
 
   // Get the list of frame checksums.
   const std::vector<std::string>& FrameChecksums() const;
-  // Get the list of thumbnail checksums, used by the "RenderThumbnails" test.
-  // TODO(crbug.com/933632) Remove once the frame validator is supported on all
-  // active platforms.
-  const std::vector<std::string>& ThumbnailChecksums() const;
 
   // Set the default path to the test video data.
   static void SetTestDataPath(const base::FilePath& test_data_path);
@@ -142,8 +138,6 @@
 
   // Ordered list of video frame checksums.
   std::vector<std::string> frame_checksums_;
-  // List of thumbnail checksums.
-  std::vector<std::string> thumbnail_checksums_;
 
   // Video codec, profile and bit depth for encoded videos.
   VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.cc b/media/gpu/test/video_player/test_vda_video_decoder.cc
index 451121a..a3c3ab3 100644
--- a/media/gpu/test/video_player/test_vda_video_decoder.cc
+++ b/media/gpu/test/video_player/test_vda_video_decoder.cc
@@ -40,15 +40,11 @@
 }  // namespace
 
 TestVDAVideoDecoder::TestVDAVideoDecoder(
-    AllocationMode allocation_mode,
     bool use_vd_vda,
     const gfx::ColorSpace& target_color_space,
     FrameRenderer* const frame_renderer,
     gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory)
-    : output_mode_(allocation_mode == AllocationMode::kAllocate
-                       ? VideoDecodeAccelerator::Config::OutputMode::ALLOCATE
-                       : VideoDecodeAccelerator::Config::OutputMode::IMPORT),
-      use_vd_vda_(use_vd_vda),
+    : use_vd_vda_(use_vd_vda),
       target_color_space_(target_color_space),
       frame_renderer_(frame_renderer),
 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
@@ -57,10 +53,6 @@
       decode_start_timestamps_(kTimestampCacheSize) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(vda_wrapper_sequence_checker_);
 
-  // TODO(crbug.com/933632) Remove support for allocate mode, and always use
-  // import mode. Support for allocate mode is temporary maintained for older
-  // platforms that don't support import mode.
-
   vda_wrapper_task_runner_ = base::ThreadTaskRunnerHandle::Get();
 
   weak_this_ = weak_this_factory_.GetWeakPtr();
@@ -120,7 +112,7 @@
 
   // Create Decoder.
   VideoDecodeAccelerator::Config vda_config(config.profile());
-  vda_config.output_mode = output_mode_;
+  vda_config.output_mode = VideoDecodeAccelerator::Config::OutputMode::IMPORT;
   vda_config.encryption_scheme = config.encryption_scheme();
   vda_config.is_deferred_initialization_allowed = false;
   vda_config.initial_expected_coded_size = config.coded_size();
@@ -228,75 +220,40 @@
             << " picture buffers with size " << dimensions.width() << "x"
             << dimensions.height();
 
-  // If using allocate mode the format requested here might be
-  // PIXEL_FORMAT_UNKNOWN.
-  if (format == PIXEL_FORMAT_UNKNOWN)
-    format = PIXEL_FORMAT_ARGB;
-
+  // Create a set of DMABuf-backed video frames.
   std::vector<PictureBuffer> picture_buffers;
+  for (uint32_t i = 0; i < requested_num_of_buffers; ++i) {
+    picture_buffers.emplace_back(GetNextPictureBufferId(), dimensions);
+  }
 
-  switch (output_mode_) {
-    case VideoDecodeAccelerator::Config::OutputMode::IMPORT:
-      // If using import mode, create a set of DMABuf-backed video frames.
-      for (uint32_t i = 0; i < requested_num_of_buffers; ++i) {
-        picture_buffers.emplace_back(GetNextPictureBufferId(), dimensions);
-      }
-      decoder_->AssignPictureBuffers(picture_buffers);
+  decoder_->AssignPictureBuffers(picture_buffers);
 
-      // Create a video frame for each of the picture buffers and provide memory
-      // handles to the video frame's data to the decoder.
-      for (const PictureBuffer& picture_buffer : picture_buffers) {
-        scoped_refptr<VideoFrame> video_frame;
+  // Create a video frame for each of the picture buffers and provide memory
+  // handles to the video frame's data to the decoder.
+  for (const PictureBuffer& picture_buffer : picture_buffers) {
+    scoped_refptr<VideoFrame> video_frame;
 
 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
-        video_frame = CreatePlatformVideoFrame(
-            gpu_memory_buffer_factory_, format, dimensions, visible_rect,
-            visible_rect.size(), base::TimeDelta(),
-            gfx::BufferUsage::SCANOUT_VDA_WRITE);
+    video_frame = CreatePlatformVideoFrame(
+        gpu_memory_buffer_factory_, format, dimensions, visible_rect,
+        visible_rect.size(), base::TimeDelta(),
+        gfx::BufferUsage::SCANOUT_VDA_WRITE);
 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
 
-        ASSERT_TRUE(video_frame) << "Failed to create video frame";
-        video_frames_.emplace(picture_buffer.id(), video_frame);
-        gfx::GpuMemoryBufferHandle handle;
+    ASSERT_TRUE(video_frame) << "Failed to create video frame";
+    video_frames_.emplace(picture_buffer.id(), video_frame);
+    gfx::GpuMemoryBufferHandle handle;
 
 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
-        handle = CreateGpuMemoryBufferHandle(video_frame.get());
-        DCHECK(!handle.is_null());
+    handle = CreateGpuMemoryBufferHandle(video_frame.get());
+    DCHECK(!handle.is_null());
 #else
-        NOTREACHED();
+    NOTREACHED();
 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
 
-        ASSERT_TRUE(!handle.is_null()) << "Failed to create GPU memory handle";
-        decoder_->ImportBufferForPicture(picture_buffer.id(), format,
-                                         std::move(handle));
-      }
-      break;
-    case VideoDecodeAccelerator::Config::OutputMode::ALLOCATE: {
-      // If using allocate mode, request a set of texture-backed video frames
-      // from the renderer.
-      const gfx::Size texture_dimensions =
-          texture_target == GL_TEXTURE_EXTERNAL_OES
-              ? GetRectSizeFromOrigin(visible_rect)
-              : dimensions;
-      for (uint32_t i = 0; i < requested_num_of_buffers; ++i) {
-        uint32_t texture_id;
-        auto video_frame = frame_renderer_->CreateVideoFrame(
-            format, texture_dimensions, texture_target, &texture_id);
-        ASSERT_TRUE(video_frame) << "Failed to create video frame";
-        int32_t picture_buffer_id = GetNextPictureBufferId();
-        PictureBuffer::TextureIds texture_ids(1, texture_id);
-        picture_buffers.emplace_back(picture_buffer_id, texture_dimensions,
-                                     texture_ids, texture_ids, texture_target,
-                                     format);
-        video_frames_.emplace(picture_buffer_id, std::move(video_frame));
-      }
-      // The decoder requires an active GL context to allocate memory.
-      decoder_->AssignPictureBuffers(picture_buffers);
-      break;
-    }
-    default:
-      LOG(ERROR) << "Unsupported output mode "
-                 << static_cast<size_t>(output_mode_);
+    ASSERT_TRUE(!handle.is_null()) << "Failed to create GPU memory handle";
+    decoder_->ImportBufferForPicture(picture_buffer.id(), format,
+                                     std::move(handle));
   }
 }
 
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.h b/media/gpu/test/video_player/test_vda_video_decoder.h
index 2d0de12..0554704 100644
--- a/media/gpu/test/video_player/test_vda_video_decoder.h
+++ b/media/gpu/test/video_player/test_vda_video_decoder.h
@@ -32,11 +32,8 @@
 class TestVDAVideoDecoder : public media::VideoDecoder,
                             public VideoDecodeAccelerator::Client {
  public:
-  // Constructor for the TestVDAVideoDecoder. The |allocation_mode| specifies
-  // whether allocating video frames will be done by the TestVDAVideoDecoder, or
-  // delegated to the underlying VDA.
-  TestVDAVideoDecoder(AllocationMode allocation_mode,
-                      bool use_vd_vda,
+  // Constructor for the TestVDAVideoDecoder.
+  TestVDAVideoDecoder(bool use_vd_vda,
                       const gfx::ColorSpace& target_color_space,
                       FrameRenderer* const frame_renderer,
                       gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory);
@@ -101,9 +98,6 @@
   // Called when the decoder finished resetting.
   base::OnceClosure reset_cb_;
 
-  // Video decode accelerator output mode.
-  const VideoDecodeAccelerator::Config::OutputMode output_mode_;
-
   // Whether VdVideoDecodeAccelerator is used.
   bool use_vd_vda_;
 
diff --git a/media/gpu/test/video_player/video_decoder_client.cc b/media/gpu/test/video_player/video_decoder_client.cc
index 4f0051d..fdfb264 100644
--- a/media/gpu/test/video_player/video_decoder_client.cc
+++ b/media/gpu/test/video_player/video_decoder_client.cc
@@ -185,16 +185,11 @@
   switch (decoder_client_config_.implementation) {
     case DecoderImplementation::kVD:
 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
-      if (decoder_client_config_.allocation_mode == AllocationMode::kImport) {
-        decoder_ = ChromeosVideoDecoderFactory::Create(
-            base::ThreadTaskRunnerHandle::Get(),
-            std::make_unique<PlatformVideoFramePool>(
-                gpu_memory_buffer_factory_),
-            std::make_unique<VideoFrameConverter>(),
-            std::make_unique<NullMediaLog>());
-      } else {
-        LOG(ERROR) << "VD-based video decoders only support import mode";
-      }
+      decoder_ = ChromeosVideoDecoderFactory::Create(
+          base::ThreadTaskRunnerHandle::Get(),
+          std::make_unique<PlatformVideoFramePool>(gpu_memory_buffer_factory_),
+          std::make_unique<VideoFrameConverter>(),
+          std::make_unique<NullMediaLog>());
 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
       break;
     case DecoderImplementation::kVDA:
@@ -203,7 +198,6 @@
       // can use the TestVDAVideoDecoder wrapper here to test VDA-based video
       // decoders.
       decoder_ = std::make_unique<TestVDAVideoDecoder>(
-          decoder_client_config_.allocation_mode,
           decoder_client_config_.implementation ==
               DecoderImplementation::kVDVDA,
           gfx::ColorSpace(), frame_renderer_.get(), gpu_memory_buffer_factory_);
diff --git a/media/gpu/test/video_player/video_decoder_client.h b/media/gpu/test/video_player/video_decoder_client.h
index 87e81b43..7c6dde60 100644
--- a/media/gpu/test/video_player/video_decoder_client.h
+++ b/media/gpu/test/video_player/video_decoder_client.h
@@ -31,13 +31,6 @@
 class FrameRenderer;
 class VideoFrameProcessor;
 
-// TODO(dstaessens@) Remove allocation mode, temporary added here so we can
-// support the thumbnail test for older platforms that don't support import.
-enum class AllocationMode {
-  kImport,    // Client allocates video frame memory.
-  kAllocate,  // Video decoder allocates video frame memory.
-};
-
 // The supported video decoding implementation.
 enum class DecoderImplementation {
   kVDA,    // VDA-based video decoder.
@@ -50,8 +43,6 @@
   // The maximum number of bitstream buffer decodes that can be requested
   // without waiting for the result of the previous decode requests.
   size_t max_outstanding_decode_requests = 1;
-  // How the pictures buffers should be allocated.
-  AllocationMode allocation_mode = AllocationMode::kImport;
   DecoderImplementation implementation = DecoderImplementation::kVDA;
 };
 
diff --git a/media/gpu/test/video_player/video_player_test_environment.cc b/media/gpu/test/video_player/video_player_test_environment.cc
index 2b4112a..7348e48 100644
--- a/media/gpu/test/video_player/video_player_test_environment.cc
+++ b/media/gpu/test/video_player/video_player_test_environment.cc
@@ -76,29 +76,6 @@
 
 VideoPlayerTestEnvironment::~VideoPlayerTestEnvironment() = default;
 
-void VideoPlayerTestEnvironment::SetUp() {
-  VideoTestEnvironment::SetUp();
-
-  // TODO(dstaessens): Remove this check once all platforms support import mode.
-  // Some older platforms do not support importing buffers, but need to allocate
-  // buffers internally in the decoder.
-  // Note: buddy, guado and rikku support import mode for H.264 and VP9, but for
-  // VP8 they use a different video decoder (V4L2 instead of VAAPI) and don't
-  // support import mode.
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  constexpr const char* kImportModeBlocklist[] = {
-      "buddy",      "guado",      "guado-cfm", "guado-kernelnext", "nyan_big",
-      "nyan_blaze", "nyan_kitty", "rikku",     "rikku-cfm"};
-  const std::string board = base::SysInfo::GetLsbReleaseBoard();
-  import_supported_ = (std::find(std::begin(kImportModeBlocklist),
-                                 std::end(kImportModeBlocklist),
-                                 board) == std::end(kImportModeBlocklist));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-  // VideoDecoders always require import mode to be supported.
-  DCHECK(import_supported_ || implementation_ == DecoderImplementation::kVDA);
-}
-
 const media::test::Video* VideoPlayerTestEnvironment::Video() const {
   return video_.get();
 }
@@ -139,9 +116,5 @@
   return output_folder_;
 }
 
-bool VideoPlayerTestEnvironment::ImportSupported() const {
-  return import_supported_;
-}
-
 }  // namespace test
 }  // namespace media
diff --git a/media/gpu/test/video_player/video_player_test_environment.h b/media/gpu/test/video_player/video_player_test_environment.h
index a66f596..daeb2c5 100644
--- a/media/gpu/test/video_player/video_player_test_environment.h
+++ b/media/gpu/test/video_player/video_player_test_environment.h
@@ -38,9 +38,6 @@
       const FrameOutputConfig& frame_output_config = FrameOutputConfig());
   ~VideoPlayerTestEnvironment() override;
 
-  // Set up video test environment, called once for entire test run.
-  void SetUp() override;
-
   // Get the video the tests will be ran on.
   const media::test::Video* Video() const;
   // Check whether frame validation is enabled.
@@ -59,9 +56,6 @@
   // Get the output folder.
   const base::FilePath& OutputFolder() const;
 
-  // Whether import mode is supported, valid after SetUp() has been called.
-  bool ImportSupported() const;
-
   // Get the GpuMemoryBufferFactory for doing buffer allocations. This needs to
   // survive as long as the process is alive just like in production which is
   // why it's in here as there are threads that won't immediately die when an
@@ -82,9 +76,6 @@
   const FrameOutputConfig frame_output_config_;
   const base::FilePath output_folder_;
 
-  // TODO(dstaessens): Remove this once all allocate-only platforms reached EOL.
-  bool import_supported_ = false;
-
   std::unique_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory_;
 };
 }  // namespace test
diff --git a/media/gpu/video_decode_accelerator_perf_tests.cc b/media/gpu/video_decode_accelerator_perf_tests.cc
index d6fd4d309..fbd5558 100644
--- a/media/gpu/video_decode_accelerator_perf_tests.cc
+++ b/media/gpu/video_decode_accelerator_perf_tests.cc
@@ -321,10 +321,6 @@
     VideoDecoderClientConfig config;
     config.implementation = g_env->GetDecoderImplementation();
 
-    // Force allocate mode if import mode is not supported.
-    if (!g_env->ImportSupported())
-      config.allocation_mode = AllocationMode::kAllocate;
-
     auto video_player = VideoPlayer::Create(
         config, g_env->GetGpuMemoryBufferFactory(), std::move(frame_renderer),
         std::move(frame_processors));
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc
index 254b49b..29aa259a 100644
--- a/media/gpu/video_decode_accelerator_tests.cc
+++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -93,17 +93,12 @@
     LOG_ASSERT(video);
     std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors;
 
-    // Force allocate mode if import mode is not supported.
-    if (!g_env->ImportSupported())
-      config.allocation_mode = AllocationMode::kAllocate;
-
     base::FilePath output_folder = base::FilePath(g_env->OutputFolder())
                                        .Append(g_env->GetTestOutputFilePath());
 
     // Write all video frames to the '<testname>' folder if the frame output
-    // mode is 'all'. Only supported if import mode is supported and enabled.
-    if (g_env->GetFrameOutputMode() == FrameOutputMode::kAll &&
-        config.allocation_mode == AllocationMode::kImport) {
+    // mode is 'all'.
+    if (g_env->GetFrameOutputMode() == FrameOutputMode::kAll) {
       frame_processors.push_back(VideoFrameFileWriter::Create(
           output_folder, g_env->GetFrameOutputFormat(),
           g_env->GetFrameOutputLimit()));
@@ -112,10 +107,8 @@
 
     // Use the video frame validator to validate decoded video frames if
     // enabled. If the frame output mode is 'corrupt', a frame writer will be
-    // attached to forward corrupted frames to. Only supported if import mode
-    // is supported and enabled.
-    if (g_env->IsValidatorEnabled() &&
-        config.allocation_mode == AllocationMode::kImport) {
+    // attached to forward corrupted frames to.
+    if (g_env->IsValidatorEnabled()) {
       std::unique_ptr<VideoFrameFileWriter> frame_writer;
       if (g_env->GetFrameOutputMode() == FrameOutputMode::kCorrupt) {
         frame_writer = VideoFrameFileWriter::Create(
@@ -414,60 +407,6 @@
   }
 }
 
-// Play a video from start to finish. Thumbnails of the decoded frames will be
-// rendered into a image, whose checksum is compared to a golden value. This
-// test is only run on older platforms that don't support the video frame
-// validator, which requires import mode. If no thumbnail checksums are present
-// in the video metadata the test will be skipped. This test will be deprecated
-// once all devices support import mode.
-TEST_F(VideoDecoderTest, FlushAtEndOfStream_RenderThumbnails) {
-  if (!g_env->IsValidatorEnabled() || g_env->ImportSupported() ||
-      g_env->Video()->ThumbnailChecksums().empty()) {
-    GTEST_SKIP();
-  }
-
-  base::FilePath output_folder = base::FilePath(g_env->OutputFolder())
-                                     .Append(g_env->GetTestOutputFilePath());
-  VideoDecoderClientConfig config;
-  config.allocation_mode = AllocationMode::kAllocate;
-  auto tvp = CreateVideoPlayer(
-      g_env->Video(), config,
-      FrameRendererThumbnail::Create(g_env->Video()->ThumbnailChecksums(),
-                                     output_folder));
-
-  tvp->Play();
-  EXPECT_TRUE(tvp->WaitForFlushDone());
-
-  EXPECT_EQ(tvp->GetFlushDoneCount(), 1u);
-  EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->Video()->NumFrames());
-  EXPECT_TRUE(tvp->WaitForFrameProcessors());
-  EXPECT_TRUE(static_cast<FrameRendererThumbnail*>(tvp->GetFrameRenderer())
-                  ->ValidateThumbnail());
-}
-
-// Play a video from start to finish, using allocate mode. This test is only run
-// on platforms that support import mode, as on allocate-mode only platforms all
-// tests are run in allocate mode. The test will be skipped when --use_vd is
-// specified as the new video decoders only support import mode.
-// TODO(dstaessens): Deprecate after switching to new VD-based video decoders.
-TEST_F(VideoDecoderTest, FlushAtEndOfStream_Allocate) {
-  if (!g_env->ImportSupported() ||
-      g_env->GetDecoderImplementation() != DecoderImplementation::kVDA) {
-    GTEST_SKIP();
-  }
-
-  VideoDecoderClientConfig config;
-  config.allocation_mode = AllocationMode::kAllocate;
-  auto tvp = CreateVideoPlayer(g_env->Video(), config);
-
-  tvp->Play();
-  EXPECT_TRUE(tvp->WaitForFlushDone());
-
-  EXPECT_EQ(tvp->GetFlushDoneCount(), 1u);
-  EXPECT_EQ(tvp->GetFrameDecodedCount(), g_env->Video()->NumFrames());
-  EXPECT_TRUE(tvp->WaitForFrameProcessors());
-}
-
 // Test initializing the video decoder for the specified video. Initialization
 // will be successful if the video decoder is capable of decoding the test
 // video's configuration (e.g. codec and resolution). The test only verifies
diff --git a/media/test/data/resolution_change_500frames-vp9.ivf.json b/media/test/data/resolution_change_500frames-vp9.ivf.json
index 7a36212..749a33a 100644
--- a/media/test/data/resolution_change_500frames-vp9.ivf.json
+++ b/media/test/data/resolution_change_500frames-vp9.ivf.json
@@ -506,6 +506,5 @@
     "7eae660c7d1212d804afbb81ab833f28",
     "b46b47c290b7ac46bd346a94cce9854f",
     "8b8fda36c5fa3f1057fd1e180ef65902"
-  ],
-  "thumbnail_checksums": []
+  ]
 }
diff --git a/media/test/data/switch_1080p_720p_240frames.h264.json b/media/test/data/switch_1080p_720p_240frames.h264.json
index 88a66a6..6e14e2b 100644
--- a/media/test/data/switch_1080p_720p_240frames.h264.json
+++ b/media/test/data/switch_1080p_720p_240frames.h264.json
@@ -246,6 +246,5 @@
     "d116552b47a29718b70d03dfc417ad86",
     "c1236dc2a2a7da79ff7fc36c83770e33",
     "24f517003f38e5848cefe52042363403"
-  ],
-  "thumbnail_checksums": []
+  ]
 }
diff --git a/media/test/data/test-25fps.h264.json b/media/test/data/test-25fps.h264.json
index 3c1b38044..14e8ef2 100644
--- a/media/test/data/test-25fps.h264.json
+++ b/media/test/data/test-25fps.h264.json
@@ -256,30 +256,5 @@
     "160a29e8413328fde6623493a4da522f",
     "a2029dbf4304d50965dc2aad44b930c4",
     "1c082bc656c7752f21118f10b8677a6c"
-  ],
-  "thumbnail_checksums": [
-    "# Intel Sandy Brige - EGL",
-    "1a69a608521e3542f6fb060855f5ba14",
-    "# Intel - VA_FILTER_SCALING_DEFAULT",
-    "d924f9464d01847f3c3d2dee739603cc",
-    "# Intel - VA decode to NV12, EGLImage CSC",
-    "82a05426b6ef227e5147eb7b710423fb",
-    "d1ba5f08cdbcc39ee24d99acaf9477ea",
-    "# Intel - Broadwell - guado and rikku",
-    "e67adcfcb6985b47b0faf29168a56766",
-    "# TODO(hiroh): Update X11 value",
-    "# Intel - Haswell - X11",
-    "# Intel - Ivy Bridge - X11",
-    "# 5f697b015b7af0afa7ff202905f748fa",
-    "# Intel - Sandy Bridge - X11",
-    "# 07bac7ad907bcb75004324645637a06c",
-    "# ARM - Mali",
-    "82c979d493a00ee2188f7259230a8de9",
-    "# ARM - Tegra",
-    "b55cda7d10c37104d8c49d27c2699e40",
-    "# ARM - MediaTek",
-    "af21b8aa5ea63c4e88f0472ee948d01a",
-    "# AMD - Stoney Ridge",
-    "7ad287d048d6bdee63fbe37a3cd2c760"
   ]
 }
diff --git a/media/test/data/test-25fps.vp8.json b/media/test/data/test-25fps.vp8.json
index 2204d5f..521e12e 100644
--- a/media/test/data/test-25fps.vp8.json
+++ b/media/test/data/test-25fps.vp8.json
@@ -256,19 +256,5 @@
     "7c998a26a20aaa3e348f9f7c49407317",
     "3f8679de7b0d2d32ec3f5997090e86f5",
     "17e3fb19dd3b57130a73e40dca0b136a"
-  ],
-  "thumbnail_checksums": [
-    "# ARM - Mali",
-    "6012551634f90fb4bd59f871fff904f4",
-    "# ARM - Tegra",
-    "cd355b553ce7660283c52675232e9227",
-    "# ARM - MediaTek",
-    "5acb8209d79c02ed9bc12048e07908e4",
-    "# Intel - VA_FILTER_SCALING_DEFAULT",
-    "66f40a833b8b23dc52bbdfc0ef0e268f",
-    "# Intel - go2001",
-    "f9c98d3808b3ca06d3375d005ab31537",
-    "# Intel - VA decode to NV12, EGLImage CSC",
-    "4fc4e3c4b690c004072b968530058b67"
   ]
 }
diff --git a/media/test/data/test-25fps.vp9.json b/media/test/data/test-25fps.vp9.json
index 3483571..6a11099 100644
--- a/media/test/data/test-25fps.vp9.json
+++ b/media/test/data/test-25fps.vp9.json
@@ -256,17 +256,5 @@
     "5a63e607041536fa3f633c769f0a9e17",
     "3b33f8e78890e8a41d8cd93ebee7078e",
     "fbb59915d51c7f56386777e70ba2dddc"
-  ],
-  "thumbnail_checksums": [
-    "# ARM - GO2001",
-    "7daba42a115da37a463edc2fa6d2ab8e",
-    "# ARM - MediaTek",
-    "4db6e435d694180354a6d763afb27894",
-    "# ARM - RK3399",
-    "82647609e45a19f8e22fd1880a9edf3d",
-    "# Intel - VA_FILTER_SCALING_DEFAULT",
-    "3533e744155fa94830151df0c15b8459",
-    "# Intel - VA decode to NV12, EGLImage CSC",
-    "919bee0d8a8278eeebb2c198a6b51455"
   ]
 }
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index aa885ac..7a77dba 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -436,24 +436,10 @@
 
     case InitiatorLockCompatibility::kIncorrectLock:
       // Requests from the renderer need to always specify a correct initiator.
-      NOTREACHED() << "request_initiator_origin_lock_ = "
-                   << request_initiator_origin_lock_.value_or(
-                          url::Origin::Create(GURL("https://no-lock.com")))
-                   << "; request.request_initiator = "
-                   << request.request_initiator.value_or(url::Origin::Create(
-                          GURL("https://no-initiator.com")));
-      if (base::FeatureList::IsEnabled(
-              features::kRequestInitiatorSiteLockEnfocement)) {
-        url::debug::ScopedOriginCrashKey initiator_lock_crash_key(
-            debug::GetRequestInitiatorOriginLockCrashKey(),
-            base::OptionalOrNullptr(request_initiator_origin_lock_));
-        base::debug::ScopedCrashKeyString debug_tag_crash_key(
-            debug::GetFactoryDebugTagCrashKey(), debug_tag_);
-        mojo::ReportBadMessage(
-            "CorsURLLoaderFactory: lock VS initiator mismatch");
-        return false;
-      }
-      break;
+      NOTREACHED();
+      mojo::ReportBadMessage(
+          "CorsURLLoaderFactory: lock VS initiator mismatch");
+      return false;
   }
 
   if (context_ && !GetAllowAnyCorsExemptHeaderForBrowser() &&
diff --git a/services/network/crash_keys.cc b/services/network/crash_keys.cc
index 414f562..3b14982 100644
--- a/services/network/crash_keys.cc
+++ b/services/network/crash_keys.cc
@@ -40,12 +40,6 @@
   return crash_key;
 }
 
-base::debug::CrashKeyString* GetFactoryDebugTagCrashKey() {
-  static auto* crash_key = base::debug::AllocateCrashKeyString(
-      "url_loader_factory_debug_tag", base::debug::CrashKeySize::Size64);
-  return crash_key;
-}
-
 ScopedRequestCrashKeys::ScopedRequestCrashKeys(
     const network::ResourceRequest& request)
     : url_(GetRequestUrlCrashKey(), request.url.possibly_invalid_spec()),
diff --git a/services/network/crash_keys.h b/services/network/crash_keys.h
index eab0abe..8d3da77 100644
--- a/services/network/crash_keys.h
+++ b/services/network/crash_keys.h
@@ -14,8 +14,9 @@
 
 namespace debug {
 
+// TODO(lukasza): Move to //services/network/public/cpp to enable reuse outside
+// of //services/network (e.g. see https://crrev.com/c/2923326).
 base::debug::CrashKeyString* GetRequestInitiatorOriginLockCrashKey();
-base::debug::CrashKeyString* GetFactoryDebugTagCrashKey();
 
 class ScopedRequestCrashKeys {
  public:
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc
index 90589ccc..1da1606 100644
--- a/services/network/public/cpp/features.cc
+++ b/services/network/public/cpp/features.cc
@@ -147,17 +147,6 @@
 const base::Feature kDisableKeepaliveFetch{"DisableKeepaliveFetch",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls whether a |request_initiator| that mismatches
-// |request_initiator_origin_lock| leads to 1) failing the HTTP request and 2)
-// calling mojo::ReportBadMessage (on desktop platforms, where NetworkService
-// is hosted outside of the Browser process, this leads to DumpWithoutCrashing
-// and does *not* lead to a renderer kill).
-//
-// See also https://crbug.com/920634
-const base::Feature kRequestInitiatorSiteLockEnfocement = {
-    "RequestInitiatorSiteLockEnfocement",
-    base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enables preprocessing requests with the Trust Tokens API Fetch flags set,
 // and handling their responses, according to the protocol.
 // (See https://github.com/WICG/trust-token-api.)
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h
index 0be1267..7e1aafb 100644
--- a/services/network/public/cpp/features.h
+++ b/services/network/public/cpp/features.h
@@ -55,8 +55,6 @@
     kDnsOverHttpsUpgradeDisabledProvidersParam;
 COMPONENT_EXPORT(NETWORK_CPP)
 extern const base::Feature kDisableKeepaliveFetch;
-COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kRequestInitiatorSiteLockEnfocement;
 
 COMPONENT_EXPORT(NETWORK_CPP)
 extern const base::Feature kTrustTokens;
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index fc097b12..b7a52c8 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -4689,7 +4689,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4768,7 +4768,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -4926,7 +4926,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5005,7 +5005,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index cce63db7..617d594 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -53852,7 +53852,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -53932,7 +53932,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54092,7 +54092,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54172,7 +54172,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54397,7 +54397,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54476,7 +54476,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54634,7 +54634,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54713,7 +54713,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54938,7 +54938,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55017,7 +55017,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55175,7 +55175,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.88"
+              "revision": "version:91.0.4472.95"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55254,7 +55254,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.41"
+              "revision": "version:92.0.4515.42"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index c419183..15247e4 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -424,7 +424,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M92',
-          'revision': 'version:92.0.4515.41',
+          'revision': 'version:92.0.4515.42',
         }
       ],
     },
@@ -448,7 +448,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.88',
+          'revision': 'version:91.0.4472.95',
         }
       ],
     },
@@ -496,7 +496,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M92',
-          'revision': 'version:92.0.4515.41',
+          'revision': 'version:92.0.4515.42',
         }
       ],
     },
@@ -520,7 +520,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.88',
+          'revision': 'version:91.0.4472.95',
         }
       ],
     },
@@ -568,7 +568,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M92',
-          'revision': 'version:92.0.4515.41',
+          'revision': 'version:92.0.4515.42',
         }
       ],
     },
@@ -592,7 +592,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.88',
+          'revision': 'version:91.0.4472.95',
         }
       ],
     },
diff --git a/testing/merge_scripts/code_coverage/merge_js_lib.py b/testing/merge_scripts/code_coverage/merge_js_lib.py
index 92ab75f..75421e1 100644
--- a/testing/merge_scripts/code_coverage/merge_js_lib.py
+++ b/testing/merge_scripts/code_coverage/merge_js_lib.py
@@ -260,23 +260,31 @@
     return merged_coverage_file.write(json.dumps(coverage_by_path))
 
 
-def write_parsed_scripts(parsed_scripts_dir):
+def write_parsed_scripts(task_output_dir):
   """Extract parsed script contents and write back to original folder structure.
 
   Args:
-    parsed_scripts_dir (str): Directory that contains the raw JavaScript v8
-        coverage files that are identified by their ".js.json" suffix.
+    task_output_dir (str): The output directory for the sharded task. This will
+        contain the raw JavaScript v8 coverage files that are identified by
+        their ".js.json" suffix.
+
+  Returns:
+    The absolute file path to the raw parsed scripts.
   """
-  scripts = _get_paths_with_suffix(parsed_scripts_dir, '.js.json')
-  output_dir = os.path.join(parsed_scripts_dir, 'parsed')
+  scripts = _get_paths_with_suffix(task_output_dir, '.js.json')
+  output_dir = os.path.join(task_output_dir, 'parsed_scripts')
 
   if not scripts:
-    logging.info('No raw scripts found in %s', parsed_scripts_dir)
+    logging.info('No raw scripts found in %s', task_output_dir)
     return
 
   for file_path in scripts:
     script_data = _parse_json_file(file_path)
 
+    if any(key not in script_data for key in ('url', 'text')):
+      logging.info('File %s is missing key url or text', file_path)
+      continue
+
     if not script_data['url'].startswith('//'):
       continue
 
@@ -286,4 +294,7 @@
       os.makedirs(source_directory)
 
     with open(os.path.join(output_dir, source_path), 'w') as f:
-      f.write(script_data['text'])
+      f.write(script_data['text'].encode('utf8'))
+
+  logging.info('Raw parsed scripts written out to %s', output_dir)
+  return output_dir
diff --git a/testing/merge_scripts/code_coverage/merge_js_lib_test.py b/testing/merge_scripts/code_coverage/merge_js_lib_test.py
index f5d9892..6317e61 100755
--- a/testing/merge_scripts/code_coverage/merge_js_lib_test.py
+++ b/testing/merge_scripts/code_coverage/merge_js_lib_test.py
@@ -471,7 +471,7 @@
         expected_files.append(file_path)
         if test_script['exists']:
           expected_files.append(os.path.join(scripts_dir,
-              'parsed', *test_script['location']))
+              'parsed_scripts', *test_script['location']))
 
       merger.write_parsed_scripts(scripts_dir)
       actual_files = []
@@ -484,5 +484,39 @@
     finally:
       shutil.rmtree(scripts_dir)
 
+  def test_write_parsed_scripts_negative_cases(self):
+    test_files = [{
+      'url': '//a/b/c/1.js',
+      'contents': """{
+"url": "%s"
+}"""
+    }, {
+      'url': '//d/e/f/1.js',
+      'contents': """{
+"text": "test\\ncontents\\n%s"
+}"""
+    }]
+
+    scripts_dir = None
+    expected_files = []
+    try:
+      scripts_dir = tempfile.mkdtemp()
+      for i, test_script in enumerate(test_files):
+        file_path = os.path.join(scripts_dir, '%d.js.json' % i)
+        expected_files.append(file_path)
+        with open(file_path, 'w') as f:
+          f.write(test_script['contents'] % test_script['url'])
+
+      merger.write_parsed_scripts(scripts_dir)
+
+      actual_files = []
+      for root, _, files in os.walk(scripts_dir):
+        for file_name in files:
+          actual_files.append(os.path.join(root, file_name))
+
+      self.assertItemsEqual(expected_files, actual_files)
+    finally:
+      shutil.rmtree(scripts_dir)
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/testing/merge_scripts/code_coverage/merge_results.py b/testing/merge_scripts/code_coverage/merge_results.py
index 073207a0..be1cb21 100755
--- a/testing/merge_scripts/code_coverage/merge_results.py
+++ b/testing/merge_scripts/code_coverage/merge_results.py
@@ -101,6 +101,9 @@
       parser.error('--merged-js-cov-filename required when merging '
                    'JavaScript coverage')
 
+    javascript_merger.write_parsed_scripts(
+        os.path.join(params.task_output_dir))
+
     # Ensure JavaScript coverage dir exists.
     if not os.path.exists(params.javascript_coverage_dir):
       os.makedirs(params.javascript_coverage_dir)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 12f0e76..e5ade031 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3783,6 +3783,21 @@
             ]
         }
     ],
+    "HelpAppLauncherSearch": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "HelpAppLauncherSearch"
+                    ]
+                }
+            ]
+        }
+    ],
     "HelpAppLocalSearchServiceIntegration": [
         {
             "platforms": [
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index eb6dabb..6c1f5fc 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -804,7 +804,9 @@
   // Sent to a prerendered frame to inform it that it is being activated.
   // The document in the frame updates `document.prerendering` and dispatches
   // the prerenderingchange event.
-  ActivateForPrerendering();
+  // |activation_start| is the time that activation started for use in
+  // PerformanceNavigationTiming.
+  ActivateForPrerendering(mojo_base.mojom.TimeTicks activation_start);
 
   // Returns a DevToolsAgent interface for this frame, used for
   // remote debugging. See DevToolsAgent for details.
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 62c475d..ae2cb770 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3241,6 +3241,7 @@
   kFontFaceSizeAdjust = 3926,
   kHiddenBackfaceWith3D = 3927,
   kMainFrameNonSecurePrivateAddressSpace = 3928,
+  kCSSSelectorPseudoHas = 3929,
 
   // 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/strings/translations/blink_strings_bn.xtb b/third_party/blink/public/strings/translations/blink_strings_bn.xtb
index 0a61db9..3150a579 100644
--- a/third_party/blink/public/strings/translations/blink_strings_bn.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_bn.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">প্রশ্ন এবং উত্তর</translation>
 <translation id="4444765639179266822">মনে হচ্ছে বলতে চাইছে: <ph name="OCR_TEXT" /></translation>
 <translation id="4446524499724042288">শব্দকোষের রেফারেন্স</translation>
-<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4522570452068850558">বিবরণগুলি</translation>
 <translation id="4576178047100686001">এই ছবিটি লেবেল করা হয়নি। ছবির বিবরণ পেতে, স্ক্রিনের সবচেয়ে উপরে বাঁদিকে 'আরও বিকল্প' মেনু খুলুন।</translation>
 <translation id="4597532268155981612">ফর্ম</translation>
 <translation id="4661075872484491155">tree</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_hr.xtb b/third_party/blink/public/strings/translations/blink_strings_hr.xtb
index 02c449d..d5ac4f55 100644
--- a/third_party/blink/public/strings/translations/blink_strings_hr.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_hr.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">Pitanja i odgovori</translation>
 <translation id="4444765639179266822">Čini se da piše: <ph name="OCR_TEXT" /></translation>
 <translation id="4446524499724042288">referenca iz pojmovnika</translation>
-<translation id="4522570452068850558">Detalji</translation>
+<translation id="4522570452068850558">Pojedinosti</translation>
 <translation id="4576178047100686001">Slika nije označena. Da biste dobili opise slika, otvorite izbornik Više opcija u gornjem lijevom kutu.</translation>
 <translation id="4597532268155981612">obrazac</translation>
 <translation id="4661075872484491155">stablo</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_lv.xtb b/third_party/blink/public/strings/translations/blink_strings_lv.xtb
index a563dea..0ab5ca1 100644
--- a/third_party/blink/public/strings/translations/blink_strings_lv.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_lv.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">Jautājumi un atbildes</translation>
 <translation id="4444765639179266822">Izklausās: <ph name="OCR_TEXT" /></translation>
 <translation id="4446524499724042288">atsauce uz glosāriju</translation>
-<translation id="4522570452068850558">Informācija</translation>
+<translation id="4522570452068850558">Dati</translation>
 <translation id="4576178047100686001">Šim attēlam nav iezīmes. Lai iegūtu attēlu aprakstus, atveriet izvēlni Citas opcijas, kas atrodas kreisajā augšējā stūrī.</translation>
 <translation id="4597532268155981612">veidlapa</translation>
 <translation id="4661075872484491155">koks</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_ru.xtb b/third_party/blink/public/strings/translations/blink_strings_ru.xtb
index b412996..3e45624 100644
--- a/third_party/blink/public/strings/translations/blink_strings_ru.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_ru.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">Вопросы и ответы</translation>
 <translation id="4444765639179266822">Похоже, тут написано "<ph name="OCR_TEXT" />"</translation>
 <translation id="4446524499724042288">ссылка на словарную статью</translation>
-<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4522570452068850558">Детали</translation>
 <translation id="4576178047100686001">У этого изображения нет ярлыка. Чтобы получить описания изображений, откройте меню "Ещё" в левом верхнем углу экрана.</translation>
 <translation id="4597532268155981612">форма</translation>
 <translation id="4661075872484491155">tree</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_sv.xtb b/third_party/blink/public/strings/translations/blink_strings_sv.xtb
index 32342ec..0b38dc5 100644
--- a/third_party/blink/public/strings/translations/blink_strings_sv.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_sv.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">Frågor och svar</translation>
 <translation id="4444765639179266822">Säger troligen: <ph name="OCR_TEXT" /></translation>
 <translation id="4446524499724042288">hänvisning till ordlista</translation>
-<translation id="4522570452068850558">Info</translation>
+<translation id="4522570452068850558">Detaljer</translation>
 <translation id="4576178047100686001">Den här bilden har ingen etikett. Öppna menyn Fler inställningar uppe till vänster för att se bildbeskrivningar.</translation>
 <translation id="4597532268155981612">formulär</translation>
 <translation id="4661075872484491155">träd</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb b/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
index ed6676f4..f000ade0 100644
--- a/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">问答</translation>
 <translation id="4444765639179266822">似乎是说:<ph name="OCR_TEXT" /></translation>
 <translation id="4446524499724042288">词汇表参考资料</translation>
-<translation id="4522570452068850558">详细信息</translation>
+<translation id="4522570452068850558">详情</translation>
 <translation id="4576178047100686001">此图片未加标签。打开左上角的“更多选项”菜单即可获取图片说明。</translation>
 <translation id="4597532268155981612">表单</translation>
 <translation id="4661075872484491155">tree</translation>
diff --git a/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb b/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
index b7bc7f1..0d81040 100644
--- a/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
+++ b/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
@@ -118,7 +118,7 @@
 <translation id="4384583879834880242">問與答</translation>
 <translation id="4444765639179266822">圖片上的文字似乎是:<ph name="OCR_TEXT" /></translation>
 <translation id="4446524499724042288">詞彙解釋參考資料</translation>
-<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4522570452068850558">詳細資料</translation>
 <translation id="4576178047100686001">這個圖片尚未加上標籤。開啟左上角的「更多選項」選單以取得圖片說明。</translation>
 <translation id="4597532268155981612">表單</translation>
 <translation id="4661075872484491155">tree</translation>
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni
index bd98dc8f..389a2884 100644
--- a/third_party/blink/renderer/bindings/idl_in_core.gni
+++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -659,6 +659,7 @@
           "//third_party/blink/renderer/core/timing/performance_measure_options.idl",
           "//third_party/blink/renderer/core/timing/performance_navigation.idl",
           "//third_party/blink/renderer/core/timing/performance_navigation_timing.idl",
+          "//third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl",
           "//third_party/blink/renderer/core/timing/performance_observer.idl",
           "//third_party/blink/renderer/core/timing/performance_observer_entry_list.idl",
           "//third_party/blink/renderer/core/timing/performance_observer_init.idl",
diff --git a/third_party/blink/renderer/core/core_initializer.h b/third_party/blink/renderer/core/core_initializer.h
index 39ea294..8e3fcd0a 100644
--- a/third_party/blink/renderer/core/core_initializer.h
+++ b/third_party/blink/renderer/core/core_initializer.h
@@ -124,6 +124,13 @@
       Page* clone_from_page,
       const SessionStorageNamespaceId& clone_to_namespace) = 0;
 
+  // Evicts the cached data of Session Storage. Called after dispatching a
+  // document unload or freeze event to avoid reusing old data in the cache in
+  // case the same renderer process is reused after the session storage has been
+  // modified by another renderer process. (Eg: Back navigation from a
+  // prerendered page.)
+  virtual void EvictSessionStorageCachedData(Page*) = 0;
+
   virtual void DidChangeManifest(LocalFrame&) = 0;
   virtual void NotifyOrientationChanged(LocalFrame&) = 0;
   // Called with an updated set of ScreenInfos for a local root frame
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni
index eaab1e8..0a17b28f 100644
--- a/third_party/blink/renderer/core/css/build.gni
+++ b/third_party/blink/renderer/core/css/build.gni
@@ -364,6 +364,8 @@
   "font_size_functions.cc",
   "font_size_functions.h",
   "hash_tools.h",
+  "has_matched_cache_scope.cc",
+  "has_matched_cache_scope.h",
   "inline_css_style_declaration.cc",
   "inline_css_style_declaration.h",
   "invalidation/invalidation_flags.cc",
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc
index b49259d..2b999380 100644
--- a/third_party/blink/renderer/core/css/css_selector.cc
+++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -341,6 +341,7 @@
     case kPseudoVideoPersistentAncestor:
     case kPseudoXrOverlay:
     case kPseudoModal:
+    case kPseudoHas:
       return kPseudoIdNone;
   }
 
@@ -464,6 +465,7 @@
     {"-webkit-any", CSSSelector::kPseudoAny},
     {"cue", CSSSelector::kPseudoCue},
     {"dir", CSSSelector::kPseudoDir},
+    {"has", CSSSelector::kPseudoHas},
     {"highlight", CSSSelector::kPseudoHighlight},
     {"host", CSSSelector::kPseudoHost},
     {"host-context", CSSSelector::kPseudoHostContext},
@@ -545,6 +547,11 @@
     return CSSSelector::kPseudoUnknown;
   }
 
+  if (match->type == CSSSelector::kPseudoHas &&
+      !RuntimeEnabledFeatures::CSSPseudoHasEnabled()) {
+    return CSSSelector::kPseudoUnknown;
+  }
+
   return static_cast<CSSSelector::PseudoType>(match->type);
 }
 
@@ -688,6 +695,7 @@
     case kPseudoFullScreenAncestor:
     case kPseudoFullscreen:
     case kPseudoFutureCue:
+    case kPseudoHas:
     case kPseudoHorizontal:
     case kPseudoHost:
     case kPseudoHostContext:
@@ -848,6 +856,7 @@
           SerializeIdentifier(simple_selector->Argument(), builder);
           builder.Append(')');
           break;
+        case kPseudoHas:
         case kPseudoNot:
           DCHECK(simple_selector->SelectorList());
           break;
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h
index 540f8a6..9bb7bdd 100644
--- a/third_party/blink/renderer/core/css/css_selector.h
+++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -276,6 +276,7 @@
     kPseudoHighlight,
     kPseudoSpellingError,
     kPseudoGrammarError,
+    kPseudoHas,
   };
 
   enum class AttributeMatchType {
diff --git a/third_party/blink/renderer/core/css/has_matched_cache_scope.cc b/third_party/blink/renderer/core/css/has_matched_cache_scope.cc
new file mode 100644
index 0000000..c6b2709
--- /dev/null
+++ b/third_party/blink/renderer/core/css/has_matched_cache_scope.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/css/has_matched_cache_scope.h"
+
+#include "third_party/blink/renderer/core/css/css_selector.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+
+namespace blink {
+
+HasMatchedCacheScope::HasMatchedCacheScope(Document* document)
+    : document_(document) {
+  DCHECK(document_);
+
+  if (document_->GetHasMatchedCacheScope())
+    return;
+
+  document_->SetHasMatchedCacheScope(this);
+}
+
+HasMatchedCacheScope::~HasMatchedCacheScope() {
+  if (document_->GetHasMatchedCacheScope() != this)
+    return;
+
+  document_->SetHasMatchedCacheScope(nullptr);
+}
+
+// static
+ElementHasMatchedMap& HasMatchedCacheScope::GetCacheForSelector(
+    const Document* document,
+    const CSSSelector* selector) {
+  // To increase the cache hit ratio, we need to have a same cache key
+  // for multiple selector instances those are actually has a same selector.
+  // TODO(blee@igalia.com) Find a way to get hash key without serialization.
+  String selector_text = selector->SelectorText();
+
+  DCHECK(document);
+  DCHECK(document->GetHasMatchedCacheScope());
+
+  HasMatchedCache& cache =
+      document->GetHasMatchedCacheScope()->has_matched_cache_;
+
+  auto element_has_matched_map = cache.find(selector_text);
+
+  if (element_has_matched_map == cache.end()) {
+    return *cache
+                .Set(selector_text,
+                     MakeGarbageCollected<ElementHasMatchedMap>())
+                .stored_value->value;
+  }
+
+  return *element_has_matched_map->value;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/has_matched_cache_scope.h b/third_party/blink/renderer/core/css/has_matched_cache_scope.h
new file mode 100644
index 0000000..b5cbdef
--- /dev/null
+++ b/third_party/blink/renderer/core/css/has_matched_cache_scope.h
@@ -0,0 +1,119 @@
+// 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_CSS_HAS_MATCHED_CACHE_SCOPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_MATCHED_CACHE_SCOPE_H_
+
+#include "third_party/blink/renderer/core/dom/element.h"
+
+namespace blink {
+
+class Document;
+
+using ElementHasMatchedMap = HeapHashMap<Member<const Element>, bool>;
+using HasMatchedCache = HeapHashMap<String, Member<ElementHasMatchedMap>>;
+
+// HasMatchedCacheScope is the stack-allocated scoping class for :has
+// matching cache.
+//
+// This class has a hashmap to hold the matching status, so the cache
+// lifecycle follows the lifecycle of the HasMatchedCacheScope instance.
+// (The hashmap for caching will be created at the construction of a
+// HasMatchedCacheScope instance, and removed at the destruction of the
+// instance)
+//
+// void SomeFunction() {
+//   HasMatchedCacheScope cache_scope; // A cache will be created here.
+//   // Can use the created cache here.
+// } // The cache will be deleted here.
+//
+// The scope instance is allocated in the function-call stack, so the
+// allocation can be nested. In this case, nested cache scope should not
+// override the previous cache scope for a better cache hit ratio.
+//
+// void SomeFunction2() {
+//   HasMatchedCacheScope cache_scope2;
+//   // Use the cache in the cache_scope1.
+//   // The cache in the cache_scope2 will not be used.
+// }
+//
+// void SomeFunction1() {
+//   HasMatchedCacheScope cache_scope1;
+//   // Use the cache in the cache_scope1
+//   SomeFunction2();
+// }
+//
+// To make this simple, the first allocated instance on the call stack will
+// be held in the Document instance. (The instance registers itself in the
+// contructor and deregisters itself in the destructor) This is based on
+// the restriction : The HasMatchedCacheScope is allowed to use only in the
+// sequences on the blink main thread.
+//
+// The cache is valid until the DOM doesn't mutate, so any DOM mutations
+// inside the cache scope is not allowed because it will make incorrect
+// matching behavior.
+//
+// The cache keeps all the :has() matching status regardless of location.
+// (e.g. '.a:has(.b) .c', '.a .b:has(.c)', ':is(.a:has(.b) .c) .d', ...)
+//
+// It stores the matching status of a :has simple selector. For example,
+// when we have the selector '.a:has(.b) .c', during the selector matching
+// sequence, matching result for ':has(.b)' will be inserted into the cache.
+//
+// To differentiate multiple :has() simple selectors, the argument selector
+// text is selected as a cache key. For example, if we already have the result
+// of ':has(.a)' in the cache with cache key '.a', and we have the selectors
+// '.b:has(.a) .c' and '.b .c:has(a)' to be matched, then the matching
+// overhead of those 2 selectors will be similar with the overhead of '.a .c'
+// because we can get the result of ':has(.a)' from the cache with the cache
+// key '.a'.
+//
+// The cache uses 2 dimensional hash map to store the matching status.
+// - hashmap[<argument-selector>][<element>] = <boolean>
+//
+// A cache item has 3 status as below.
+// - Matched:
+//     - Checked :has(<argument-selector>) on <element> and matched
+//     - Cache item with 'true' value
+// - Checked:
+//     - Checked :has(<argument-selector>) on <element> but not matched
+//     - Cache item with 'false' value
+// - NotChecked:
+//     - Not checked :has(<argument-selector>) on <element> (default)
+//     - Cache item doesn't exist
+//
+// During the selector matching operation on an element, the cache items
+// will be inserted for every :has argument selector matching operations
+// on the subtree elements of the element.
+//
+// When we have a style rule 'div.b:has(.a1,.a2,.a3,...,.an) {...}', and
+// m number of elements in the descendant subtree of div.b elements, and
+// o number of ancestors of div.b elements, the maximum number of
+// inserted cache items will be n*(m+o)
+//
+// TODO(blee@igalia.com) Need to think about some restrictions that can
+// help to limit the cache size. For example, compounding with universal.
+// When the ':has' is compounded with universal selector(e.g. ':has(...)'
+// or '*:has(...)'), cache size can be large (m will be the number of
+// elements in the document, and o will be zero). Need to restrict the
+// case of compounding ':has' with universal selector?
+class HasMatchedCacheScope {
+  STACK_ALLOCATED();
+
+ public:
+  explicit HasMatchedCacheScope(Document*);
+  ~HasMatchedCacheScope();
+
+  static ElementHasMatchedMap& GetCacheForSelector(const Document*,
+                                                   const CSSSelector*);
+
+ private:
+  HasMatchedCache has_matched_cache_;
+
+  Document* document_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_HAS_MATCHED_CACHE_SCOPE_H_
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index 7520985..6c5aa21 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -455,6 +455,7 @@
     case CSSSelector::kPseudoIs:
     case CSSSelector::kPseudoWhere:
     case CSSSelector::kPseudoNot:
+    case CSSSelector::kPseudoHas:
       // These pseudo-classes are themselves always valid.
       // CSSSelectorParser::restricting_pseudo_element_ ensures that invalid
       // nested selectors will be dropped if they are invalid according to
@@ -796,6 +797,22 @@
       selector->SetSelectorList(std::move(selector_list));
       return selector;
     }
+    case CSSSelector::kPseudoHas: {
+      if (!RuntimeEnabledFeatures::CSSPseudoHasEnabled())
+        break;
+
+      DisallowPseudoElementsScope scope(this);
+      base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
+
+      std::unique_ptr<CSSSelectorList> selector_list =
+          std::make_unique<CSSSelectorList>();
+      *selector_list = ConsumeNestedSelectorList(block);
+      if (!selector_list->IsValid() || !block.AtEnd())
+        return nullptr;
+
+      selector->SetSelectorList(std::move(selector_list));
+      return selector;
+    }
     case CSSSelector::kPseudoNot: {
       DisallowPseudoElementsScope scope(this);
       base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
@@ -1356,6 +1373,10 @@
           DCHECK(RuntimeEnabledFeatures::CSSPseudoDirEnabled());
           feature = WebFeature::kCSSSelectorPseudoDir;
           break;
+        case CSSSelector::kPseudoHas:
+          DCHECK(RuntimeEnabledFeatures::CSSPseudoHasEnabled());
+          feature = WebFeature::kCSSSelectorPseudoHas;
+          break;
         default:
           break;
       }
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 3f3a4238..0f14a97 100644
--- a/third_party/blink/renderer/core/css/rule_feature_set.cc
+++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -185,6 +185,7 @@
     case CSSSelector::kPseudoHighlight:
     case CSSSelector::kPseudoSpellingError:
     case CSSSelector::kPseudoGrammarError:
+    case CSSSelector::kPseudoHas:
       return true;
     case CSSSelector::kPseudoUnknown:
     case CSSSelector::kPseudoLeftPage:
@@ -733,6 +734,13 @@
     return;
   CSSSelector::PseudoType pseudo_type = simple_selector.GetPseudoType();
 
+  // For the :has pseudo class, we should not extract invalidation set features
+  // here because the :has invalidation direction is different with others.
+  // (preceding-sibling/ancestors/preceding-sibling-of-ancestors)
+  // TODO(blee@igalia.com) Need to add :has invalidation
+  if (UNLIKELY(pseudo_type == CSSSelector::kPseudoHas))
+    return;
+
   DCHECK(SupportsInvalidationWithSelectorList(pseudo_type));
 
   const CSSSelector* sub_selector = selector_list->First();
@@ -950,7 +958,16 @@
     return;
   }
 
-  if (simple_selector.GetPseudoType() == CSSSelector::kPseudoPart)
+  CSSSelector::PseudoType pseudo_type = simple_selector.GetPseudoType();
+
+  // For the :has pseudo class, we should not extract invalidation set features
+  // here because the :has invalidation direction is different with others.
+  // (preceding-sibling/ancestors/preceding-sibling-of-ancestors)
+  // TODO(blee@igalia.com) Need to add :has invalidation
+  if (UNLIKELY(pseudo_type == CSSSelector::kPseudoHas))
+    return;
+
+  if (pseudo_type == CSSSelector::kPseudoPart)
     descendant_features.invalidation_flags.SetInvalidatesParts(true);
 
   AddFeaturesToInvalidationSetsForSelectorList(
@@ -1036,6 +1053,8 @@
   for (const CSSSelector* current = &selector; current;
        current = current->TagHistory()) {
     switch (current->GetPseudoType()) {
+      case CSSSelector::kPseudoHas:
+        break;
       case CSSSelector::kPseudoFirstLine:
         metadata.uses_first_line_rules = true;
         break;
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc
index ce49058a..3c75c935 100644
--- a/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -32,6 +32,7 @@
 #include "base/auto_reset.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
 #include "third_party/blink/renderer/core/css/css_selector_list.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
 #include "third_party/blink/renderer/core/css/part_names.h"
 #include "third_party/blink/renderer/core/css/style_engine.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -235,8 +236,10 @@
   if (sub_result.dynamic_pseudo != kPseudoIdNone)
     result.dynamic_pseudo = sub_result.dynamic_pseudo;
 
-  if (context.selector->IsLastInTagHistory())
+  if (context.selector->IsLastInTagHistory()) {
+    result.has_argument_leftmost_compound_match = context.element;
     return kSelectorMatches;
+  }
 
   MatchStatus match;
   if (context.selector->Relation() != CSSSelector::kSubSelector) {
@@ -314,8 +317,11 @@
     case CSSSelector::kDescendant:
       if (next_context.selector->GetPseudoType() == CSSSelector::kPseudoScope) {
         if (next_context.selector->IsLastInTagHistory()) {
-          if (context.scope->IsDocumentFragment())
+          if (context.scope->IsDocumentFragment() ||
+              UNLIKELY(context.in_has_argument_selector)) {
+            result.has_argument_leftmost_compound_match = context.element;
             return kSelectorMatches;
+          }
         }
       }
       for (next_context.element = ParentElement(next_context);
@@ -631,6 +637,102 @@
   return true;
 }
 
+bool SelectorChecker::CheckPseudoHas(const SelectorCheckingContext& context,
+                                     MatchResult& result) const {
+  Document& document = context.element->GetDocument();
+  DCHECK(document.GetHasMatchedCacheScope());
+  Element* element = context.element;
+  SelectorCheckingContext sub_context(element);
+  sub_context.scope = element;
+  sub_context.in_has_argument_selector = true;
+  // sub_context.is_inside_visited_link is false (by default) to disable
+  // :visited matching when it is in the :has argument
+
+  DCHECK(context.selector->SelectorList());
+  for (const CSSSelector* selector = context.selector->SelectorList()->First();
+       selector; selector = CSSSelectorList::Next(*selector)) {
+    ElementHasMatchedMap& map =
+        HasMatchedCacheScope::GetCacheForSelector(&document, selector);
+
+    // Get the cache item of matching ':has(<selector>)' on the element
+    // to skip argument matching on the subtree elements
+    //  - If the element was already marked as matched, return true.
+    //  - If the element was already checked but not matched,
+    //    move to the next argument selector.
+    //  - Otherwise, mark the element as checked but not matched.
+    {  // Limit the the AddResult scope to prevent SECURITY_DCHECK
+      auto cache_result = map.insert(element, false);  // Mark as checked
+      if (!cache_result.is_new_entry) {        // Was already marked as checked
+        if (cache_result.stored_value->value)  // Was already marked as matched
+          return true;
+        continue;
+      }
+    }
+
+    sub_context.selector = selector;
+
+    // TODO(blee@igalia.com)
+    // 1. Need to check how to handle the shadow tree cases
+    //    (e.g. ':has(::slotted(img))', ':has(component::part(my-part))')
+    // 2. Need to add logics for other combinators
+    //    (e.g. ':has(:scope > .a)', ':has(:scope ~ .a)', ':has(:scope + .a)'
+    for (Element& descendant : ElementTraversal::DescendantsOf(*element)) {
+      // Get the cache item of matching ':has(<selector>)' on the descendant.
+      // to skip argument selector matching on the descendant.
+      //  - If the descendant was already marked as matched,
+      //    mark the element as matched, and return true.
+      //  - If the descendant was already checked but not matched,
+      //    move to the next descendant.
+      //  - Otherwise, mark the descendant as checked but not matched.
+      {  // Limit the the AddResult scope to prevent SECURITY_DCHECK
+        auto cache_result = map.insert(&descendant, false);  // Mark as checked
+        if (!cache_result.is_new_entry) {  // Was already marked as checked
+          if (!cache_result.stored_value->value)  // Was not marked as matched
+            continue;
+          map.Set(element, true);  // Mark element as matched
+          return true;
+        }
+      }
+
+      // Match the argument selector <selector> on the descendant element,
+      // and move to the next descendant if not matched.
+      sub_context.element = &descendant;
+      MatchResult sub_result;
+      if (MatchSelector(sub_context, sub_result) != kSelectorMatches)
+        continue;
+
+      if (sub_result.has_argument_leftmost_compound_match) {
+        // Mark the ancestors of the element that matches leftmost compound
+        // of the argument selector <selector>. Make those elements as matched
+        // until it reaches the nullptr or the element(:has scope element).
+        // The reason of stopping at the :has scope element is to avoid
+        // duplicate parent tree traversal.
+        // For example, matching ':has(.a)' with nested .a elements will
+        // generate parent tree traversal for every .a elements when
+        // recalculating the entire document.
+        // With this restriction, we can prevent those redundants. It is
+        // OK not to mark every ancestors for every argument matching because
+        // it is enough to cache the matching status until meet the :has scope
+        // element. After those are cached, the cached status can be used as
+        // the status of :has scope element or descendant elements of the :has
+        // in another selector. (Please refer the above steps to get a cache
+        // item and return/continue early)
+        sub_context.element = sub_result.has_argument_leftmost_compound_match;
+        for (sub_context.element = ParentElement(sub_context);
+             sub_context.element && sub_context.element != element;
+             sub_context.element = ParentElement(sub_context)) {
+          map.Set(sub_context.element, true);  // Mark as matched
+        }
+      }
+
+      if (sub_context.element)
+        map.Set(element, true);  // Mark the element as matched
+      return true;
+    }
+  }
+  return false;
+}
+
 bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
                                        MatchResult& result) const {
   Element& element = *context.element;
@@ -647,6 +749,8 @@
   switch (selector.GetPseudoType()) {
     case CSSSelector::kPseudoNot:
       return CheckPseudoNot(context, result);
+    case CSSSelector::kPseudoHas:
+      return CheckPseudoHas(context, result);
     case CSSSelector::kPseudoEmpty: {
       bool is_empty = true;
       bool has_whitespace = false;
diff --git a/third_party/blink/renderer/core/css/selector_checker.h b/third_party/blink/renderer/core/css/selector_checker.h
index b040006..6dc502d 100644
--- a/third_party/blink/renderer/core/css/selector_checker.h
+++ b/third_party/blink/renderer/core/css/selector_checker.h
@@ -121,6 +121,7 @@
     Element* vtt_originating_element = nullptr;
     bool in_nested_complex_selector = false;
     bool is_inside_visited_link = false;
+    bool in_has_argument_selector = false;
   };
 
   struct MatchResult {
@@ -128,6 +129,39 @@
 
    public:
     PseudoId dynamic_pseudo{kPseudoIdNone};
+
+    // From the shortest argument selector match, we need to get the element
+    // that matches the leftmost compound selector to mark the correct scope
+    // elements of :has() pseudo class having the argument selectors starts
+    // with descendant combinator.
+    //
+    // <main id=main>
+    //   <div id=d1>
+    //     <div id=d2 class="a">
+    //       <div id=d3 class="a">
+    //         <div id=d4>
+    //           <div id=d5 class="b">
+    //           </div>
+    //         </div>
+    //       </div>
+    //     </div>
+    //   </div>
+    // </div>
+    // <script>
+    //  main.querySelectorAll('div:has(.a .b)'); // Should return #d1, #d2
+    // </script>
+    //
+    // In case of the above example, div#d5 element matches the argument
+    // selector '.a .b'. Among the ancestors of the div#d5, the div#d3 and
+    // div#d4 is not the correct candidate scope element of ':has(.a .b)'
+    // because those elements don't have .a element as it's descendant.
+    // So instead of marking ancestors of div#d5, we should mark ancestors
+    // of div#d3 to prevent incorrect marking.
+    // In case of the shortest match for the argument selector '.a .b' on
+    // div#d5 element, the div#d3 is the element that matches the leftmost
+    // compound selector '.a'. So the MatchResult will return the div#d3
+    // element for the matching operation.
+    Element* has_argument_leftmost_compound_match{nullptr};
   };
 
   bool Match(const SelectorCheckingContext& context, MatchResult& result) const;
@@ -188,6 +222,7 @@
                                  MatchResult&) const;
   bool CheckPseudoHost(const SelectorCheckingContext&, MatchResult&) const;
   bool CheckPseudoNot(const SelectorCheckingContext&, MatchResult&) const;
+  bool CheckPseudoHas(const SelectorCheckingContext&, MatchResult&) const;
 
   ComputedStyle* element_style_;
   CustomScrollbar* scrollbar_;
diff --git a/third_party/blink/renderer/core/css/selector_query.cc b/third_party/blink/renderer/core/css/selector_query.cc
index 52d3dd9..eb86a2be 100644
--- a/third_party/blink/renderer/core/css/selector_query.cc
+++ b/third_party/blink/renderer/core/css/selector_query.cc
@@ -30,6 +30,7 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
 #include "third_party/blink/renderer/core/css/parser/css_parser.h"
 #include "third_party/blink/renderer/core/css/selector_checker.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -106,11 +107,13 @@
 
 bool SelectorQuery::Matches(Element& target_element) const {
   QUERY_STATS_RESET();
+  HasMatchedCacheScope has_matched_cache_scope(&target_element.GetDocument());
   return SelectorListMatches(target_element, target_element);
 }
 
 Element* SelectorQuery::Closest(Element& target_element) const {
   QUERY_STATS_RESET();
+  HasMatchedCacheScope has_matched_cache_scope(&target_element.GetDocument());
   if (selectors_.IsEmpty())
     return nullptr;
 
@@ -124,6 +127,7 @@
 
 StaticElementList* SelectorQuery::QueryAll(ContainerNode& root_node) const {
   QUERY_STATS_RESET();
+  HasMatchedCacheScope has_matched_cache_scope(&root_node.GetDocument());
   NthIndexCache nth_index_cache(root_node.GetDocument());
   HeapVector<Member<Element>> result;
   Execute<AllElementsSelectorQueryTrait>(root_node, result);
@@ -132,6 +136,7 @@
 
 Element* SelectorQuery::QueryFirst(ContainerNode& root_node) const {
   QUERY_STATS_RESET();
+  HasMatchedCacheScope has_matched_cache_scope(&root_node.GetDocument());
   NthIndexCache nth_index_cache(root_node.GetDocument());
   Element* matched_element = nullptr;
   Execute<SingleElementSelectorQueryTrait>(root_node, matched_element);
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index 96d82f6a..26ee306 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
 #include "third_party/blink/renderer/core/css/document_style_sheet_collector.h"
 #include "third_party/blink/renderer/core/css/font_face_cache.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
 #include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h"
 #include "third_party/blink/renderer/core/css/media_feature_overrides.h"
 #include "third_party/blink/renderer/core/css/media_values.h"
@@ -2070,6 +2071,7 @@
 void StyleEngine::RecalcStyle(StyleRecalcChange change,
                               const StyleRecalcContext& style_recalc_context) {
   DCHECK(GetDocument().documentElement());
+  HasMatchedCacheScope has_matched_cache_scope(&GetDocument());
   Element& root_element = style_recalc_root_.RootElement();
   Element* parent = FlatTreeTraversal::ParentElement(root_element);
 
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index c37dd643..805fcd6 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8078,7 +8078,7 @@
   return find_in_page_active_match_node_;
 }
 
-void Document::ActivateForPrerendering() {
+void Document::ActivateForPrerendering(base::TimeTicks activation_start) {
   DCHECK(RuntimeEnabledFeatures::Prerender2Enabled());
 
   // For subframes, this can be called before the navigation commit, and this
@@ -8094,7 +8094,7 @@
   is_prerendering_ = false;
 
   if (DocumentLoader* loader = Loader())
-    loader->NotifyPrerenderingDocumentActivated();
+    loader->NotifyPrerenderingDocumentActivated(activation_start);
 
   Vector<base::OnceClosure> callbacks;
   callbacks.swap(will_dispatch_prerenderingchange_callbacks_);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index bf2b4b8..bd339bb 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -153,6 +153,7 @@
 class HTMLHeadElement;
 class HTMLLinkElement;
 class HTMLPopupElement;
+class HasMatchedCacheScope;
 class HitTestRequest;
 class HttpRefreshScheduler;
 class IdleRequestOptions;
@@ -1445,6 +1446,10 @@
 
   NthIndexCache* GetNthIndexCache() const { return nth_index_cache_; }
 
+  HasMatchedCacheScope* GetHasMatchedCacheScope() const {
+    return has_matched_cache_scope_;
+  }
+
   CanvasFontCache* GetCanvasFontCache();
 
   // Used by unit tests so that all parsing will be main thread for
@@ -1678,7 +1683,7 @@
   void SetFindInPageActiveMatchNode(Node*);
   const Node* GetFindInPageActiveMatchNode() const;
 
-  void ActivateForPrerendering();
+  void ActivateForPrerendering(base::TimeTicks activation_start);
 
   void AddWillDispatchPrerenderingchangeCallback(base::OnceClosure);
 
@@ -1717,6 +1722,7 @@
   friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
   friend class IgnoreOpensDuringUnloadCountIncrementer;
   friend class NthIndexCache;
+  friend class HasMatchedCacheScope;
   friend class CanvasRenderingAPIUkmMetricsTest;
   friend class OffscreenCanvasRenderingAPIUkmMetricsTest;
   FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest,
@@ -1820,6 +1826,11 @@
     nth_index_cache_ = nth_index_cache;
   }
 
+  void SetHasMatchedCacheScope(HasMatchedCacheScope* has_matched_cache_scope) {
+    DCHECK(!has_matched_cache_scope_ || !has_matched_cache_scope);
+    has_matched_cache_scope_ = has_matched_cache_scope;
+  }
+
   const OriginAccessEntry& AccessEntryFromURL();
 
   void UpdateActiveState(bool is_active, bool update_active_chain, Element*);
@@ -2058,6 +2069,13 @@
   GC_PLUGIN_IGNORE("461878")
   NthIndexCache* nth_index_cache_ = nullptr;
 
+  // This is an untraced pointer to the cache-scoped object that is first
+  // allocated on the stack. It is set upon the first object being allocated
+  // on the stack, and cleared upon leaving its allocated scope. The object's
+  // references will be traced by a stack walk.
+  GC_PLUGIN_IGNORE("669058")
+  HasMatchedCacheScope* has_matched_cache_scope_ = nullptr;
+
   DocumentClassFlags document_classes_;
 
   bool is_view_source_;
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index ad14a9c3..d7610b9 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -161,6 +161,7 @@
 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
 #include "third_party/blink/renderer/core/loader/idleness_detector.h"
 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
+#include "third_party/blink/renderer/core/loader/prerender_handle.h"
 #include "third_party/blink/renderer/core/messaging/message_port.h"
 #include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -763,6 +764,13 @@
       GetDocument());
 
   loader_.DispatchUnloadEvent(nullptr, nullptr);
+  if (evict_cached_session_storage_on_freeze_or_unload_) {
+    // Evicts the cached data of Session Storage to avoid reusing old data in
+    // the cache after the session storage has been modified by another renderer
+    // process.
+    CoreInitializer::GetInstance().EvictSessionStorageCachedData(
+        GetDocument()->GetPage());
+  }
   if (!Client())
     return false;
 
@@ -2708,6 +2716,11 @@
       &DOMWrapperWorld::MainWorld());
 }
 
+void LocalFrame::SetEvictCachedSessionStorageOnFreezeOrUnload() {
+  DCHECK(RuntimeEnabledFeatures::Prerender2Enabled());
+  evict_cached_session_storage_on_freeze_or_unload_ = true;
+}
+
 LoaderFreezeMode LocalFrame::GetLoaderFreezeMode() {
   if (GetPage()->GetPageScheduler()->IsInBackForwardCache() &&
       IsInflightNetworkRequestBackForwardCacheSupportEnabled()) {
@@ -2722,6 +2735,13 @@
   TRACE_EVENT0("blink", "LocalFrame::DidFreeze");
   DCHECK(IsAttached());
   GetDocument()->DispatchFreezeEvent();
+  if (evict_cached_session_storage_on_freeze_or_unload_) {
+    // Evicts the cached data of Session Storage to avoid reusing old data in
+    // the cache after the session storage has been modified by another renderer
+    // process.
+    CoreInitializer::GetInstance().EvictSessionStorageCachedData(
+        GetDocument()->GetPage());
+  }
   // DispatchFreezeEvent dispatches JS events, which may detach |this|.
   if (!IsAttached())
     return;
@@ -3873,7 +3893,7 @@
       url_before_redirects, had_redirect, std::move(source));
 }
 
-void LocalFrame::ActivateForPrerendering() {
+void LocalFrame::ActivateForPrerendering(base::TimeTicks activation_start) {
   DCHECK(features::IsPrerender2Enabled());
 
   // https://jeremyroman.github.io/alternate-loading-modes/#prerendering-browsing-context-activate
@@ -3883,8 +3903,9 @@
   // networking task source, given bc's active window, to perform the following
   // steps:"
   GetTaskRunner(TaskType::kNetworking)
-      ->PostTask(FROM_HERE, WTF::Bind(&Document::ActivateForPrerendering,
-                                      WrapPersistent(GetDocument())));
+      ->PostTask(FROM_HERE,
+                 WTF::Bind(&Document::ActivateForPrerendering,
+                           WrapPersistent(GetDocument()), activation_start));
 }
 
 void LocalFrame::BindDevToolsAgent(
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 31caa4651..87079c5b 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -713,7 +713,7 @@
       const KURL& url_before_redirects,
       bool had_redirect,
       network::mojom::blink::SourceLocationPtr source_location) final;
-  void ActivateForPrerendering() final;
+  void ActivateForPrerendering(base::TimeTicks activation_start) final;
   void BindDevToolsAgent(
       mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host,
       mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver)
@@ -825,6 +825,8 @@
 
   void LoadJavaScriptURL(const KURL& url);
 
+  void SetEvictCachedSessionStorageOnFreezeOrUnload();
+
  private:
   friend class FrameNavigationDisabler;
   FRIEND_TEST_ALL_PREFIXES(LocalFrameTest, CharacterIndexAtPointWithPinchZoom);
@@ -1111,6 +1113,8 @@
   // v8 stack at the time of creation. This is updated in `SetAdEvidence()`,
   // allowing the bit to be propagated when a frame navigates cross-origin.
   bool is_subframe_created_by_ad_script_ = false;
+
+  bool evict_cached_session_storage_on_freeze_or_unload_ = false;
 };
 
 inline FrameLoader& LocalFrame::Loader() const {
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
index 0e49290..2c5c435 100644
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -50,6 +50,7 @@
 #include "third_party/blink/renderer/core/css/css_variable_data.h"
 #include "third_party/blink/renderer/core/css/font_face.h"
 #include "third_party/blink/renderer/core/css/font_size_functions.h"
+#include "third_party/blink/renderer/core/css/has_matched_cache_scope.h"
 #include "third_party/blink/renderer/core/css/media_list.h"
 #include "third_party/blink/renderer/core/css/media_query.h"
 #include "third_party/blink/renderer/core/css/media_values.h"
@@ -875,6 +876,7 @@
     stylesheet->SyncTextIfNeeded();
   }
 
+  HasMatchedCacheScope has_matched_cache_scope(&document);
   InspectorStyleResolver resolver(element, element_pseudo_id);
 
   // Matched rules.
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
index 995ab53e9..b95e830f 100644
--- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -391,6 +391,7 @@
     DEFINE_STRING_MAPPING(PseudoHighlight)
     DEFINE_STRING_MAPPING(PseudoSpellingError)
     DEFINE_STRING_MAPPING(PseudoGrammarError)
+    DEFINE_STRING_MAPPING(PseudoHas)
 #undef DEFINE_STRING_MAPPING
   }
 
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index e6093e2..2fad389 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -497,6 +497,9 @@
       children->InsertChildNode(this, table, before_child);
     }
     table->AddChild(new_child);
+  } else if (LIKELY(new_child->IsHorizontalWritingMode()) ||
+             !new_child->IsText()) {
+    children->InsertChildNode(this, new_child, before_child);
   } else if (IsA<LayoutNGTextCombine>(*this)) {
     DCHECK(LayoutNGTextCombine::ShouldBeParentOf(*new_child)) << new_child;
     new_child->SetStyle(Style());
@@ -524,6 +527,8 @@
                                           To<LayoutText>(new_child)));
     }
   } else {
+    DCHECK(!new_child->IsHorizontalWritingMode()) << new_child;
+    DCHECK(new_child->IsText()) << new_child;
     children->InsertChildNode(this, new_child, before_child);
   }
 
@@ -2994,7 +2999,7 @@
         child_block_flow->IsAnonymousBlockContinuation())
       new_style->SetPosition(child->StyleRef().GetPosition());
 
-    if (IsA<LayoutNGTextCombine>(child)) {
+    if (UNLIKELY(IsA<LayoutNGTextCombine>(child))) {
       // "text-combine-width-after-style-change.html" reaches here.
       StyleAdjuster::AdjustStyleForTextCombine(*new_style);
     }
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 06379cd7..7af143b8 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
@@ -1259,18 +1259,22 @@
 
   // Auto-margins take precedence over any alignment properties.
   if (style.MayHaveMargin()) {
-    bool start_auto = is_inline_axis
-                          ? style.MarginStartUsing(container_style).IsAuto()
-                          : style.MarginBeforeUsing(container_style).IsAuto();
-    bool end_auto = is_inline_axis
-                        ? style.MarginEndUsing(container_style).IsAuto()
-                        : style.MarginAfterUsing(container_style).IsAuto();
+    bool is_start_auto =
+        is_inline_axis ? style.MarginStartUsing(container_style).IsAuto()
+                       : style.MarginBeforeUsing(container_style).IsAuto();
+    bool is_end_auto = is_inline_axis
+                           ? style.MarginEndUsing(container_style).IsAuto()
+                           : style.MarginAfterUsing(container_style).IsAuto();
 
-    if (start_auto && end_auto)
+    // 'auto' margin alignment is always "safe".
+    if (is_start_auto || is_end_auto)
+      *is_overflow_safe = true;
+
+    if (is_start_auto && is_end_auto)
       return AxisEdge::kCenter;
-    else if (start_auto)
+    else if (is_start_auto)
       return AxisEdge::kEnd;
-    else if (end_auto)
+    else if (is_end_auto)
       return AxisEdge::kStart;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h
index 0653d7d..c646db0 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h
@@ -37,9 +37,11 @@
 // static
 inline bool LayoutNGTextCombine::ShouldBeParentOf(
     const LayoutObject& layout_object) {
-  const auto& style = layout_object.StyleRef();
-  return !style.IsHorizontalWritingMode() && style.HasTextCombine() &&
-         layout_object.IsText() && layout_object.IsLayoutNGObject();
+  if (LIKELY(layout_object.IsHorizontalWritingMode()) ||
+      !layout_object.IsText())
+    return false;
+  return UNLIKELY(layout_object.StyleRef().HasTextCombine()) &&
+         layout_object.IsLayoutNGObject();
 }
 
 template <>
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
index 1c7764a6..3ae98cf 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -80,8 +80,8 @@
 }
 
 void NGInlineBoxState::ComputeTextMetrics(const ComputedStyle& styleref,
-                                          const Font& fontref,
-                                          FontBaseline baseline_type) {
+                                          const Font& fontref) {
+  const auto baseline_type = styleref.GetFontBaseline();
   if (const SimpleFontData* font_data = fontref.PrimaryFont()) {
     if (is_svg_text) {
       text_metrics =
@@ -119,14 +119,14 @@
 }
 
 void NGInlineBoxState::EnsureTextMetrics(const ComputedStyle& styleref,
-                                         const Font& fontref,
-                                         FontBaseline baseline_type) {
+                                         const Font& fontref) {
   if (text_metrics.IsEmpty())
-    ComputeTextMetrics(styleref, fontref, baseline_type);
+    ComputeTextMetrics(styleref, fontref);
 }
 
-void NGInlineBoxState::AccumulateUsedFonts(const ShapeResultView* shape_result,
-                                           FontBaseline baseline_type) {
+void NGInlineBoxState::AccumulateUsedFonts(
+    const ShapeResultView* shape_result) {
+  const auto baseline_type = style->GetFontBaseline();
   HashSet<const SimpleFontData*> fallback_fonts;
   shape_result->FallbackFonts(&fallback_fonts);
   for (const SimpleFontData* const fallback_font : fallback_fonts) {
@@ -205,8 +205,7 @@
     // line height properties) as the initial metrics for the line box.
     // https://drafts.csswg.org/css2/visudet.html#strut
     if (!line_height_quirk) {
-      line_box_state.ComputeTextMetrics(line_style, *line_box_state.font,
-                                        baseline_type);
+      line_box_state.ComputeTextMetrics(line_style, *line_box_state.font);
     }
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
index 109ead5..c7babe8c 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -105,15 +105,11 @@
   // Compute text metrics for a box. All text in a box share the same
   // metrics.
   // The computed metrics is included into the line height of the current box.
-  void ComputeTextMetrics(const ComputedStyle&,
-                          const Font& fontref,
-                          FontBaseline baseline_type);
-  void EnsureTextMetrics(const ComputedStyle&,
-                         const Font& fontref,
-                         FontBaseline);
+  void ComputeTextMetrics(const ComputedStyle&, const Font& fontref);
+  void EnsureTextMetrics(const ComputedStyle&, const Font& fontref);
   void ResetTextMetrics();
 
-  void AccumulateUsedFonts(const ShapeResultView*, FontBaseline);
+  void AccumulateUsedFonts(const ShapeResultView*);
 
   // 'text-top' offset for 'vertical-align'.
   LayoutUnit TextTop(FontBaseline baseline_type) const;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index d1328c8..8787ade 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -90,7 +90,7 @@
   // for the purpose of empty block calculation.
   // https://drafts.csswg.org/css2/visudet.html#line-height
   if (!quirks_mode_ || !item.IsEmptyItem())
-    box->ComputeTextMetrics(*item.Style(), *box->font, baseline_type_);
+    box->ComputeTextMetrics(*item.Style(), *box->font);
 
   if (item.Style()->HasMask()) {
     // Layout may change the bounding box, which affects MaskClip.
@@ -107,7 +107,7 @@
     NGLogicalLineItems* line_box,
     NGInlineBoxState* box) {
   if (UNLIKELY(quirks_mode_ && !item.IsEmptyItem()))
-    box->EnsureTextMetrics(*item.Style(), *box->font, baseline_type_);
+    box->EnsureTextMetrics(*item.Style(), *box->font);
   box = box_states_->OnCloseTag(ConstraintSpace(), line_box, box,
                                 baseline_type_, item.HasEndEdge());
   // Just clear |NeedsLayout| flags. Culled inline boxes do not need paint
@@ -218,7 +218,7 @@
   // have been to make sure that there's always room for the list item marker,
   // but that doesn't explain why it's done for every line...
   if (quirks_mode_ && line_style.Display() == EDisplay::kListItem)
-    box->ComputeTextMetrics(line_style, *box->font, baseline_type_);
+    box->ComputeTextMetrics(line_style, *box->font);
 
   bool has_logical_text_items = false;
   for (NGInlineItemResult& item_result : *line_items) {
@@ -231,13 +231,11 @@
       DCHECK(item_result.shape_result);
 
       if (UNLIKELY(quirks_mode_))
-        box->EnsureTextMetrics(*item.Style(), *box->font, baseline_type_);
+        box->EnsureTextMetrics(*item.Style(), *box->font);
 
       // Take all used fonts into account if 'line-height: normal'.
-      if (box->include_used_fonts) {
-        box->AccumulateUsedFonts(item_result.shape_result.get(),
-                                 baseline_type_);
-      }
+      if (box->include_used_fonts)
+        box->AccumulateUsedFonts(item_result.shape_result.get());
 
       DCHECK(item.TextType() == NGTextType::kNormal ||
              item.TextType() == NGTextType::kSymbolMarker);
@@ -517,7 +515,7 @@
   ClearNeedsLayoutIfNeeded(item.GetLayoutObject());
 
   if (UNLIKELY(quirks_mode_ && !box->HasMetrics()))
-    box->EnsureTextMetrics(*item.Style(), *box->font, baseline_type_);
+    box->EnsureTextMetrics(*item.Style(), *box->font);
 
   line_box->AddChild(item, std::move(item_result->shape_result),
                      item_result->TextOffset(), box->text_top,
@@ -779,8 +777,8 @@
                                               NGInlineItemResult* item_result,
                                               const NGLineInfo& line_info) {
   if (UNLIKELY(quirks_mode_)) {
-    box_states_->LineBoxState().EnsureTextMetrics(
-        *item.Style(), item.Style()->GetFont(), baseline_type_);
+    box_states_->LineBoxState().EnsureTextMetrics(*item.Style(),
+                                                  item.Style()->GetFont());
   }
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index 03a456a..c806413 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -796,5 +796,25 @@
       });
 }
 
+// crbug.com/1214232
+TEST_F(NGLineBreakerTest, GetOverhangCrash) {
+  NGInlineNode node = CreateInlineNode(
+      R"HTML(
+<!DOCTYPE html>
+<style>
+* { margin-inline-end: -7%; }
+rb { float: right; }
+rt { margin: 17179869191em; }
+</style>
+<div id="container">
+<ruby>
+<rb>
+C c
+<rt>
+)HTML");
+  // The test passes if we have no DCHECK failures in BreakLines().
+  BreakLines(node, LayoutUnit::Max());
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
index 41e0187..423af5c 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
@@ -104,9 +104,7 @@
     return overhang;
 
   const auto& run_fragment = item.layout_result->PhysicalFragment();
-  LayoutUnit start_overhang = LayoutUnit::Max();
-  LayoutUnit end_overhang = LayoutUnit::Max();
-  bool found_line = false;
+
   const ComputedStyle* ruby_text_style = nullptr;
   for (const auto& child_link : run_fragment.PostLayoutChildren()) {
     const NGPhysicalFragment& child_fragment = *child_link.get();
@@ -115,43 +113,50 @@
       continue;
     if (layout_object->IsRubyText()) {
       ruby_text_style = layout_object->Style();
-      continue;
-    }
-    if (layout_object->IsRubyBase()) {
-      const ComputedStyle& base_style = child_fragment.Style();
-      const auto writing_direction = base_style.GetWritingDirection();
-      const LayoutUnit base_inline_size =
-          NGFragment(writing_direction, child_fragment).InlineSize();
-      // RubyBase's inline_size is always same as RubyRun's inline_size.
-      // Overhang values are offsets from RubyBase's inline edges to
-      // the outmost text.
-      for (const auto& base_child_link : child_fragment.PostLayoutChildren()) {
-        const LayoutUnit line_inline_size =
-            NGFragment(writing_direction, *base_child_link).InlineSize();
-        if (line_inline_size == LayoutUnit())
-          continue;
-        found_line = true;
-        const LayoutUnit start =
-            base_child_link.offset
-                .ConvertToLogical(writing_direction, child_fragment.Size(),
-                                  base_child_link.get()->Size())
-                .inline_offset;
-        const LayoutUnit end = base_inline_size - start - line_inline_size;
-        start_overhang = std::min(start_overhang, start);
-        end_overhang = std::min(end_overhang, end);
-      }
+      break;
     }
   }
-
-  if (!found_line || !ruby_text_style)
+  if (!ruby_text_style)
     return overhang;
-  DCHECK_NE(start_overhang, LayoutUnit::Max());
-  DCHECK_NE(end_overhang, LayoutUnit::Max());
+
   // We allow overhang up to the half of ruby text font size.
   const LayoutUnit half_width_of_ruby_font =
       LayoutUnit(ruby_text_style->FontSize()) / 2;
-  overhang.start = std::min(start_overhang, half_width_of_ruby_font);
-  overhang.end = std::min(end_overhang, half_width_of_ruby_font);
+  LayoutUnit start_overhang = half_width_of_ruby_font;
+  LayoutUnit end_overhang = half_width_of_ruby_font;
+  bool found_line = false;
+  for (const auto& child_link : run_fragment.PostLayoutChildren()) {
+    const NGPhysicalFragment& child_fragment = *child_link.get();
+    const LayoutObject* layout_object = child_fragment.GetLayoutObject();
+    if (!layout_object->IsRubyBase())
+      continue;
+    const ComputedStyle& base_style = child_fragment.Style();
+    const auto writing_direction = base_style.GetWritingDirection();
+    const LayoutUnit base_inline_size =
+        NGFragment(writing_direction, child_fragment).InlineSize();
+    // RubyBase's inline_size is always same as RubyRun's inline_size.
+    // Overhang values are offsets from RubyBase's inline edges to
+    // the outmost text.
+    for (const auto& base_child_link : child_fragment.PostLayoutChildren()) {
+      const LayoutUnit line_inline_size =
+          NGFragment(writing_direction, *base_child_link).InlineSize();
+      if (line_inline_size == LayoutUnit())
+        continue;
+      found_line = true;
+      const LayoutUnit start =
+          base_child_link.offset
+              .ConvertToLogical(writing_direction, child_fragment.Size(),
+                                base_child_link.get()->Size())
+              .inline_offset;
+      const LayoutUnit end = base_inline_size - start - line_inline_size;
+      start_overhang = std::min(start_overhang, start);
+      end_overhang = std::min(end_overhang, end);
+    }
+  }
+  if (!found_line)
+    return overhang;
+  overhang.start = start_overhang;
+  overhang.end = end_overhang;
   return overhang;
 }
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
index 4e3d2e5..e5be30a 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -45,6 +45,17 @@
 
 namespace blink {
 
+namespace {
+
+void ClampBoundsToFinite(FloatRect& bounds) {
+  bounds.SetX(clampTo<float>(bounds.X()));
+  bounds.SetY(clampTo<float>(bounds.Y()));
+  bounds.SetWidth(clampTo<float>(bounds.Width()));
+  bounds.SetHeight(clampTo<float>(bounds.Height()));
+}
+
+}  // namespace
+
 LayoutSVGShape::LayoutSVGShape(SVGGeometryElement* node,
                                StrokeGeometryClass geometry_class)
     : LayoutSVGModelObject(node),
@@ -121,6 +132,7 @@
   NOT_DESTROYED();
   CreatePath();
   fill_bounding_box_ = GetPath().TightBoundingRect();
+  ClampBoundsToFinite(fill_bounding_box_);
 
   if (HasNonScalingStroke()) {
     // NonScalingStrokeTransform may depend on LocalTransform which in turn may
diff --git a/third_party/blink/renderer/core/loader/document_load_timing.cc b/third_party/blink/renderer/core/loader/document_load_timing.cc
index a43e765..95c4c3e0 100644
--- a/third_party/blink/renderer/core/loader/document_load_timing.cc
+++ b/third_party/blink/renderer/core/loader/document_load_timing.cc
@@ -281,4 +281,12 @@
   NotifyDocumentTimingChanged();
 }
 
+void DocumentLoadTiming::MarkActivationStart(base::TimeTicks activation_start) {
+  activation_start_ = activation_start;
+  TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "activationtart",
+                                   activation_start, "frame",
+                                   ToTraceValue(GetFrame()));
+  NotifyDocumentTimingChanged();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_load_timing.h b/third_party/blink/renderer/core/loader/document_load_timing.h
index 73c6bf1..3a834a5d 100644
--- a/third_party/blink/renderer/core/loader/document_load_timing.h
+++ b/third_party/blink/renderer/core/loader/document_load_timing.h
@@ -83,6 +83,8 @@
   void MarkLoadEventStart();
   void MarkLoadEventEnd();
 
+  void MarkActivationStart(base::TimeTicks);
+
   void SetCanRequestFromPreviousDocument(bool value) {
     can_request_from_previous_document_ = value;
   }
@@ -112,6 +114,7 @@
   base::TimeTicks ResponseEnd() const { return response_end_; }
   base::TimeTicks LoadEventStart() const { return load_event_start_; }
   base::TimeTicks LoadEventEnd() const { return load_event_end_; }
+  base::TimeTicks ActivationStart() const { return activation_start_; }
   bool HasCrossOriginRedirect() const { return has_cross_origin_redirect_; }
   bool CanRequestFromPreviousDocument() const {
     return can_request_from_previous_document_;
@@ -152,6 +155,7 @@
   base::TimeTicks response_end_;
   base::TimeTicks load_event_start_;
   base::TimeTicks load_event_end_;
+  base::TimeTicks activation_start_;
   bool has_cross_origin_redirect_;
   bool can_request_from_previous_document_;
 
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 6f87db4..275d61d6 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2635,10 +2635,12 @@
   return token_value;
 }
 
-void DocumentLoader::NotifyPrerenderingDocumentActivated() {
+void DocumentLoader::NotifyPrerenderingDocumentActivated(
+    base::TimeTicks activation_start) {
   DCHECK(!frame_->GetDocument()->IsPrerendering());
   DCHECK(is_prerendering_);
   is_prerendering_ = false;
+  GetTiming().MarkActivationStart(activation_start);
 }
 
 ContentSecurityPolicy* DocumentLoader::CreateCSP() {
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index a553082b..29f255a 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -354,7 +354,7 @@
 
   // Notifies that the prerendering document this loader is working for is
   // activated.
-  void NotifyPrerenderingDocumentActivated();
+  void NotifyPrerenderingDocumentActivated(base::TimeTicks activation_start);
 
   blink::mojom::CodeCacheHost* GetCodeCacheHost();
   void OnCodeCacheHostClosed();
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index 054da346..bd173d1 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -153,8 +153,7 @@
   if (RequiresCompositingForRootScroller(*layer))
     reasons |= CompositingReason::kRootScroller;
 
-  if (RequiresCompositingForScrollDependentPosition(*layer))
-    reasons |= CompositingReason::kScrollDependentPosition;
+  reasons |= CompositingReasonsForScrollDependentPosition(*layer);
 
   if (RequiresCompositingForAffectedByOuterViewportBoundsDelta(object))
     reasons |= CompositingReason::kAffectedByOuterViewportBoundsDelta;
@@ -280,8 +279,7 @@
     }
   }
 
-  if (RequiresCompositingForScrollDependentPosition(layer))
-    direct_reasons |= CompositingReason::kScrollDependentPosition;
+  direct_reasons |= CompositingReasonsForScrollDependentPosition(layer);
 
   if (RequiresCompositingForAffectedByOuterViewportBoundsDelta(layout_object))
     direct_reasons |= CompositingReason::kAffectedByOuterViewportBoundsDelta;
@@ -390,8 +388,10 @@
   return layer.GetLayoutObject().IsGlobalRootScroller();
 }
 
-bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
+CompositingReasons
+CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
     const PaintLayer& layer) {
+  CompositingReasons reasons = CompositingReason::kNone;
   // Don't promote fixed position elements that are descendants of a non-view
   // container, e.g. transformed elements.  They will stay fixed wrt the
   // container rather than the enclosing frame.
@@ -400,20 +400,19 @@
     // position elements are composited under overflow: hidden, which can still
     // have smooth scroll animations.
     LocalFrameView* frame_view = layer.GetLayoutObject().GetFrameView();
-    return frame_view->LayoutViewport()->HasOverflow();
+    if (frame_view->LayoutViewport()->HasOverflow())
+      reasons |= CompositingReason::kFixedPosition;
   }
 
   // Don't promote sticky position elements that cannot move with scrolls.
-  if (layer.SticksToScroller()) {
-    // We check for |HasOverflow| instead of |ScrollsOverflow| to ensure sticky
-    // position elements are composited under overflow: hidden, which can still
-    // have smooth scroll animations.
-    return layer.AncestorScrollContainerLayer()
-        ->GetScrollableArea()
-        ->HasOverflow();
-  }
+  // We check for |HasOverflow| instead of |ScrollsOverflow| to ensure sticky
+  // position elements are composited under overflow: hidden, which can still
+  // have smooth scroll animations.
+  if (layer.SticksToScroller() &&
+      layer.AncestorScrollContainerLayer()->GetScrollableArea()->HasOverflow())
+    reasons |= CompositingReason::kStickyPosition;
 
-  return false;
+  return reasons;
 }
 
 bool CompositingReasonFinder::
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
index 7640882..e865fa8 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
@@ -48,7 +48,8 @@
       const LayoutObject&);
   static bool RequiresCompositingForRootScroller(const PaintLayer&);
 
-  static bool RequiresCompositingForScrollDependentPosition(const PaintLayer&);
+  static CompositingReasons CompositingReasonsForScrollDependentPosition(
+      const PaintLayer&);
 
   static bool RequiresCompositingForAffectedByOuterViewportBoundsDelta(
       const LayoutObject&);
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
index 67da1f6..15ad33b 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -140,27 +140,31 @@
 
   auto& sticky_scrolling =
       *To<LayoutBoxModelObject>(GetLayoutObjectByElementId("sticky-scrolling"));
-  EXPECT_TRUE(
-      CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
-          *sticky_scrolling.Layer()));
+  EXPECT_EQ(
+      CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+          *sticky_scrolling.Layer()),
+      CompositingReason::kStickyPosition);
 
   auto& sticky_no_scrolling = *To<LayoutBoxModelObject>(
       GetLayoutObjectByElementId("sticky-no-scrolling"));
-  EXPECT_FALSE(
-      CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
-          *sticky_no_scrolling.Layer()));
+  EXPECT_EQ(
+      CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+          *sticky_no_scrolling.Layer()),
+      CompositingReason::kNone);
 
   auto& overflow_hidden_scrolling = *To<LayoutBoxModelObject>(
       GetLayoutObjectByElementId("overflow-hidden-scrolling"));
-  EXPECT_TRUE(
-      CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
-          *overflow_hidden_scrolling.Layer()));
+  EXPECT_EQ(
+      CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+          *overflow_hidden_scrolling.Layer()),
+      CompositingReason::kStickyPosition);
 
   auto& overflow_hidden_no_scrolling = *To<LayoutBoxModelObject>(
       GetLayoutObjectByElementId("overflow-hidden-no-scrolling"));
-  EXPECT_FALSE(
-      CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
-          *overflow_hidden_no_scrolling.Layer()));
+  EXPECT_EQ(
+      CompositingReasonFinder::CompositingReasonsForScrollDependentPosition(
+          *overflow_hidden_no_scrolling.Layer()),
+      CompositingReason::kNone);
 
   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
     EXPECT_EQ(kPaintsIntoOwnBacking,
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
index 09d5c4c..bac1b5d5 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
@@ -18,6 +18,7 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/scroll/scroll_types.h"
 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 
 using testing::_;
@@ -922,7 +923,7 @@
 }
 
 TEST_P(PaintLayerScrollableAreaTest,
-       ScrollWithFixedDoesNotNeedCompositingInputsUpdate) {
+       ScrollWithFixedDoesNotNeedCompositingUpdate) {
   SetBodyInnerHTML(R"HTML(
     <style>
       * {
@@ -952,6 +953,9 @@
   scrollable_area->SetScrollOffset(ScrollOffset(0, 1),
                                    mojom::blink::ScrollType::kProgrammatic);
   EXPECT_FALSE(scrollable_area->Layer()->NeedsCompositingInputsUpdate());
+  UpdateAllLifecyclePhasesExceptPaint();
+  EXPECT_FALSE(
+      GetDocument().View()->GetPaintArtifactCompositor()->NeedsUpdate());
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(FloatSize(0, 1), scrollable_area->GetScrollOffset());
 }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 0d45e6f..394c787 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -616,6 +616,14 @@
     state.direct_compositing_reasons =
         full_context_.direct_compositing_reasons &
         CompositingReason::kDirectReasonsForPaintOffsetTranslationProperty;
+    if (state.direct_compositing_reasons & CompositingReason::kFixedPosition &&
+        object_.View()->FirstFragment().PaintProperties()->Scroll()) {
+      state.scroll_translation_for_fixed = object_.View()
+                                               ->FirstFragment()
+                                               .PaintProperties()
+                                               ->ScrollTranslation();
+    }
+
     if (IsA<LayoutView>(object_)) {
       DCHECK(object_.GetFrame());
       state.flags.is_frame_paint_offset_translation = true;
@@ -2166,11 +2174,20 @@
 
     if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
         scroll_translation->Translation2D() != old_scroll_offset) {
-      // Scrolling can change overlap relationship.
+      // Scrolling can change overlap relationship for sticky positioned or
+      // elements fixed to an overflow: hidden view that programmatically
+      // scrolls via script. In this case the fixed transform doesn't have
+      // enough information to perform the expansion - there is no scroll node
+      // to describe the bounds of the scrollable content.
       auto* frame_view = object_.GetFrameView();
-      if (frame_view->HasViewportConstrainedObjects()) {
-        // TODO(crbug.com/1099379): Implement better fixed/sticky overlap
-        // testing.
+      if (frame_view->HasStickyViewportConstrainedObject()) {
+        // TODO(crbug.com/1099379): Implement better sticky overlap testing.
+        frame_view->SetPaintArtifactCompositorNeedsUpdate();
+      } else if (frame_view->HasViewportConstrainedObjects() &&
+                 !frame_view->GetLayoutView()
+                      ->FirstFragment()
+                      .PaintProperties()
+                      ->Scroll()) {
         frame_view->SetPaintArtifactCompositorNeedsUpdate();
       } else if (!object_.IsStackingContext() &&
                  // TODO(wangxianzhu): for accuracy, this should be something
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
index dfb390e..1704d1f 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -6,6 +6,7 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/features.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/platform/wtf/vector.h"
 
 namespace blink {
@@ -107,6 +108,15 @@
     if (RuntimeEnabledFeatures::Prerender2Enabled(execution_context)) {
       push_candidates(mojom::blink::SpeculationAction::kPrerender,
                       rule_set->prerender_rules());
+
+      // Set the flag to evict the cached data of Session Storage when the
+      // document is frozen or unload to avoid reusing old data in the cache
+      // after the session storage has been modified by another renderer
+      // process. See crbug.com/1215680 for more details.
+      LocalFrame* frame = GetSupplementable()->GetFrame();
+      if (frame->IsMainFrame()) {
+        frame->SetEvictCachedSessionStorageOnFreezeOrUnload();
+      }
     }
   }
 
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
index 0f0a139..bd912fb 100644
--- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
+++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
@@ -227,7 +227,8 @@
       // This includes totally invalid ones and ones with unacceptable schemes.
       R"({"source": "list",
           "urls": [
-            "valid.html", "mailto:alice@example.com", "http://@:"
+            "valid.html", "mailto:alice@example.com", "http://@:",
+            "blob:https://bar"
            ]
          }]})",
       KURL("https://example.com/"));
diff --git a/third_party/blink/renderer/core/timing/build.gni b/third_party/blink/renderer/core/timing/build.gni
index c12d93b..e19ead1 100644
--- a/third_party/blink/renderer/core/timing/build.gni
+++ b/third_party/blink/renderer/core/timing/build.gni
@@ -39,6 +39,8 @@
   "performance_navigation.h",
   "performance_navigation_timing.cc",
   "performance_navigation_timing.h",
+  "performance_navigation_timing_activation_start.cc",
+  "performance_navigation_timing_activation_start.h",
   "performance_observer.cc",
   "performance_observer.h",
   "performance_observer_entry_list.cc",
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing.cc b/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
index fa42819..67ee52f 100644
--- a/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
@@ -13,7 +13,9 @@
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/performance_entry_names.h"
 #include "third_party/blink/renderer/core/timing/performance.h"
+#include "third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
 namespace blink {
@@ -318,5 +320,12 @@
   builder.AddNumber("loadEventEnd", loadEventEnd());
   builder.AddString("type", type());
   builder.AddNumber("redirectCount", redirectCount());
+
+  if (RuntimeEnabledFeatures::Prerender2Enabled(
+          ExecutionContext::From(builder.GetScriptState()))) {
+    builder.AddNumber(
+        "activationStart",
+        PerformanceNavigationTimingActivationStart::activationStart(*this));
+  }
 }
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing.h b/third_party/blink/renderer/core/timing/performance_navigation_timing.h
index 1c5f76ef..ca71acbe 100644
--- a/third_party/blink/renderer/core/timing/performance_navigation_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_navigation_timing.h
@@ -69,6 +69,8 @@
   void BuildJSONValue(V8ObjectBuilder&) const override;
 
  private:
+  friend class PerformanceNavigationTimingActivationStart;
+
   static AtomicString GetNavigationType(WebNavigationType, const Document*);
 
   const DocumentTiming* GetDocumentTiming() const;
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc b/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc
new file mode 100644
index 0000000..504088e
--- /dev/null
+++ b/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.cc
@@ -0,0 +1,25 @@
+// 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/timing/performance_navigation_timing_activation_start.h"
+
+#include "third_party/blink/renderer/core/loader/document_load_timing.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
+
+namespace blink {
+
+// static
+DOMHighResTimeStamp PerformanceNavigationTimingActivationStart::activationStart(
+    const PerformanceNavigationTiming& performance_navigation_timing) {
+  DocumentLoadTiming* timing =
+      performance_navigation_timing.GetDocumentLoadTiming();
+  if (!timing)
+    return 0.0;
+  return Performance::MonotonicTimeToDOMHighResTimeStamp(
+      performance_navigation_timing.TimeOrigin(), timing->ActivationStart(),
+      false /* allow_negative_value */,
+      performance_navigation_timing.CrossOriginIsolatedCapability());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h b/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.h
new file mode 100644
index 0000000..c42f599
--- /dev/null
+++ b/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.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_TIMING_PERFORMANCE_NAVIGATION_TIMING_ACTIVATION_START_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_ACTIVATION_START_H_
+
+#include "third_party/blink/renderer/core/timing/performance_navigation_timing.h"
+
+namespace blink {
+
+class PerformanceNavigationTimingActivationStart final {
+ public:
+  static DOMHighResTimeStamp activationStart(
+      const PerformanceNavigationTiming& performance_navigation_timing);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_ACTIVATION_START_H_
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl b/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl
new file mode 100644
index 0000000..62f799d
--- /dev/null
+++ b/third_party/blink/renderer/core/timing/performance_navigation_timing_activation_start.idl
@@ -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.
+
+// https://jeremyroman.github.io/alternate-loading-modes/#performance-navigation-timing-extension
+[
+    ImplementedAs=PerformanceNavigationTimingActivationStart,
+    RuntimeEnabled=Prerender2
+] partial interface PerformanceNavigationTiming {
+    readonly attribute DOMHighResTimeStamp activationStart;
+};
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc
index 4078634..c067633 100644
--- a/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -363,6 +363,12 @@
     storage_namespace->CloneTo(WebString::FromLatin1(clone_to_namespace));
 }
 
+void ModulesInitializer::EvictSessionStorageCachedData(Page* page) {
+  StorageNamespace* storage_namespace = StorageNamespace::From(page);
+  if (storage_namespace)
+    storage_namespace->EvictSessionStorageCachedData();
+}
+
 void ModulesInitializer::DidChangeManifest(LocalFrame& frame) {
   ManifestManager::From(*frame.DomWindow())->DidChangeManifest();
 }
diff --git a/third_party/blink/renderer/modules/modules_initializer.h b/third_party/blink/renderer/modules/modules_initializer.h
index 4769e54..707b72f 100644
--- a/third_party/blink/renderer/modules/modules_initializer.h
+++ b/third_party/blink/renderer/modules/modules_initializer.h
@@ -48,6 +48,7 @@
   void CloneSessionStorage(
       Page* clone_from_page,
       const SessionStorageNamespaceId& clone_to_namespace) override;
+  void EvictSessionStorageCachedData(Page*) override;
 
   void DidChangeManifest(LocalFrame&) override;
   void NotifyOrientationChanged(LocalFrame&) override;
diff --git a/third_party/blink/renderer/modules/storage/cached_storage_area.cc b/third_party/blink/renderer/modules/storage/cached_storage_area.cc
index 4b98ae5e..114f3a8f 100644
--- a/third_party/blink/renderer/modules/storage/cached_storage_area.cc
+++ b/third_party/blink/renderer/modules/storage/cached_storage_area.cc
@@ -792,4 +792,8 @@
   NOTREACHED();
 }
 
+void CachedStorageArea::EvictCachedData() {
+  map_.reset();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/storage/cached_storage_area.h b/third_party/blink/renderer/modules/storage/cached_storage_area.h
index 68caa52..bc90840 100644
--- a/third_party/blink/renderer/modules/storage/cached_storage_area.h
+++ b/third_party/blink/renderer/modules/storage/cached_storage_area.h
@@ -102,6 +102,8 @@
     return is_session_storage_for_prerendering_;
   }
 
+  void EvictCachedData();
+
   void SetRemoteAreaForTesting(
       mojo::PendingRemote<mojom::blink::StorageArea> area) {
     remote_area_.Bind(std::move(area));
diff --git a/third_party/blink/renderer/modules/storage/storage_namespace.cc b/third_party/blink/renderer/modules/storage/storage_namespace.cc
index 234567d1..363ab62 100644
--- a/third_party/blink/renderer/modules/storage/storage_namespace.cc
+++ b/third_party/blink/renderer/modules/storage/storage_namespace.cc
@@ -119,6 +119,16 @@
       /*is_session_storage_for_prerendering=*/true);
 }
 
+void StorageNamespace::EvictSessionStorageCachedData() {
+  // Currently this is called to evict the cached data only when prerendering
+  // was triggered. TODO(crbug.com/1215680): investigate if more cache eviction
+  // is needed for non-prerender use cases.
+  DCHECK(IsSessionStorage());
+  for (auto& entry : cached_areas_) {
+    entry.value->EvictCachedData();
+  }
+}
+
 void StorageNamespace::CloneTo(const String& target) {
   DCHECK(IsSessionStorage()) << "Cannot clone a local storage namespace.";
   EnsureConnected();
diff --git a/third_party/blink/renderer/modules/storage/storage_namespace.h b/third_party/blink/renderer/modules/storage/storage_namespace.h
index ec36582..b7d2d28 100644
--- a/third_party/blink/renderer/modules/storage/storage_namespace.h
+++ b/third_party/blink/renderer/modules/storage/storage_namespace.h
@@ -87,6 +87,8 @@
   scoped_refptr<CachedStorageArea> CreateCachedAreaForPrerender(
       const SecurityOrigin* origin);
 
+  void EvictSessionStorageCachedData();
+
   // Only valid to call this if |this| and |target| are session storage
   // namespaces.
   void CloneTo(const String& target);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 18c0ef6..1a4f05d 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -542,7 +542,7 @@
   GeometryMapper::LocalToAncestorVisualRect(
       property_tree_state, ancestor_state, visual_rect,
       kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect,
-      kExpandVisualRectForAnimation);
+      kExpandVisualRectForCompositingOverlap);
   return visual_rect.Rect();
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
index b0f2223..55baccd9 100644
--- a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -41,8 +41,9 @@
      "Has an active accelerated backdrop filter animation or transition"},
     {CompositingReason::kXrOverlay, "xrOverlay",
      "Is DOM overlay for WebXR immersive-ar mode"},
-    {CompositingReason::kScrollDependentPosition, "scrollDependentPosition",
-     "Is fixed or sticky position"},
+    {CompositingReason::kFixedPosition, "fixedPosition", "Is fixed position"},
+    {CompositingReason::kStickyPosition, "stickyPosition",
+     "Is sticky position"},
     {CompositingReason::kOverflowScrolling, "overflowScrolling",
      "Is a scrollable overflow element"},
     {CompositingReason::kOverflowScrollingParent, "overflowScrollingParent",
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/third_party/blink/renderer/platform/graphics/compositing_reasons.h
index 0fc88cb..e85c6bd 100644
--- a/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -31,7 +31,8 @@
   V(ActiveFilterAnimation)                                                    \
   V(ActiveBackdropFilterAnimation)                                            \
   V(AffectedByOuterViewportBoundsDelta)                                       \
-  V(ScrollDependentPosition)                                                  \
+  V(FixedPosition)                                                            \
+  V(StickyPosition)                                                           \
   V(OverflowScrolling)                                                        \
   V(OverflowScrollingParent)                                                  \
   V(OutOfFlowClipping)                                                        \
@@ -131,10 +132,12 @@
         kWillChangeFilter | kWillChangeOther | kBackdropFilter |
         kWillChangeBackdropFilter,
 
+    kComboScrollDependentPosition = kFixedPosition | kStickyPosition,
+
     kComboAllDirectNonStyleDeterminedReasons =
         kVideo | kCanvas | kPlugin | kIFrame | kSVGRoot |
         kOverflowScrollingParent | kOutOfFlowClipping | kVideoOverlay |
-        kXrOverlay | kRoot | kRootScroller | kScrollDependentPosition |
+        kXrOverlay | kRoot | kRootScroller | kComboScrollDependentPosition |
         kAffectedByOuterViewportBoundsDelta | kBackfaceInvisibility3DAncestor |
         kDocumentTransitionSharedElement,
 
@@ -142,7 +145,7 @@
                              kComboAllDirectNonStyleDeterminedReasons,
 
     kComboAllCompositedScrollingDeterminedReasons =
-        kScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
+        kComboScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
         kOverflowScrolling,
 
     kComboCompositedDescendants =
@@ -164,7 +167,7 @@
     kPreventingSubpixelAccumulationReasons = kWillChangeTransform,
 
     kDirectReasonsForPaintOffsetTranslationProperty =
-        kScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
+        kComboScrollDependentPosition | kAffectedByOuterViewportBoundsDelta |
         kVideo | kCanvas | kPlugin | kIFrame | kSVGRoot,
     kDirectReasonsForTransformProperty =
         k3DTransform | kTrivial3DTransform | kWillChangeTransform |
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
index db720b1..73b71bc0 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
@@ -9,14 +9,51 @@
 
 namespace blink {
 
+namespace {
+
+// Walk up from the local transform to the ancestor. If the last transform
+// before hitting the ancestor is a fixed node, expand based on the min and
+// max scroll offsets.
+void ExpandFixedBoundsInScroller(const TransformPaintPropertyNode* local,
+                                 const TransformPaintPropertyNode* ancestor,
+                                 FloatClipRect& rect_to_map) {
+  const TransformPaintPropertyNode* current = local->UnaliasedParent();
+  const TransformPaintPropertyNode* previous = local;
+  while (current != nullptr && current != ancestor) {
+    previous = current;
+    current = current->UnaliasedParent();
+  }
+
+  const auto* node = previous->ScrollTranslationForFixed();
+  if (!node)
+    return;
+
+  DCHECK(node->ScrollNode());
+
+  // First move the rect back to the min scroll offset, by accounting for the
+  // current scroll offset.
+  FloatSize scroll_offset = node->Translation2D();
+  rect_to_map.Rect().Move(scroll_offset);
+
+  // Calculate the max scroll offset and expand by that amount. The max scroll
+  // offset is the contents size minus one viewport's worth of space (i.e. the
+  // container rect size).
+  IntSize contents_size = node->ScrollNode()->ContentsSize();
+  IntSize container_size = node->ScrollNode()->ContainerRect().Size();
+  rect_to_map.Rect().Expand(FloatSize(contents_size - container_size));
+}
+
+}  // namespace
+
 GeometryMapper::Translation2DOrMatrix
 GeometryMapper::SourceToDestinationProjection(
     const TransformPaintPropertyNode& source,
     const TransformPaintPropertyNode& destination) {
   bool has_animation = false;
+  bool has_fixed = false;
   bool success = false;
-  return SourceToDestinationProjectionInternal(source, destination,
-                                               has_animation, success);
+  return SourceToDestinationProjectionInternal(
+      source, destination, has_animation, has_fixed, success);
 }
 
 // Returns flatten(destination_to_screen)^-1 * flatten(source_to_screen)
@@ -63,14 +100,17 @@
     const TransformPaintPropertyNode& source,
     const TransformPaintPropertyNode& destination,
     bool& has_animation,
+    bool& has_fixed,
     bool& success) {
   has_animation = false;
+  has_fixed = false;
   success = true;
 
   if (&source == &destination)
     return Translation2DOrMatrix();
 
   if (source.Parent() && &destination == &source.Parent()->Unalias()) {
+    has_fixed = source.RequiresCompositingForFixedPosition();
     if (source.IsIdentityOr2DTranslation()) {
       // We always use full matrix for animating transforms.
       DCHECK(!source.HasActiveTransformAnimation());
@@ -95,6 +135,8 @@
   const auto& source_cache = source.GetTransformCache();
   const auto& destination_cache = destination.GetTransformCache();
 
+  has_fixed |= source_cache.has_fixed();
+
   // Case 1a (fast path of case 1b): check if source and destination are under
   // the same 2d translation root.
   if (source_cache.root_of_2d_translation() ==
@@ -153,11 +195,11 @@
     FloatClipRect& mapping_rect,
     OverlayScrollbarClipBehavior clip_behavior,
     InclusiveIntersectOrNot inclusive_behavior,
-    ExpandVisualRectForAnimationOrNot expand_for_animation) {
+    ExpandVisualRectForCompositingOverlapOrNot expand) {
   bool success = false;
   bool result = LocalToAncestorVisualRectInternal(
       local_state, ancestor_state, mapping_rect, clip_behavior,
-      inclusive_behavior, expand_for_animation, success);
+      inclusive_behavior, expand, success);
   DCHECK(success);
   return result;
 }
@@ -168,7 +210,7 @@
     FloatClipRect& rect_to_map,
     OverlayScrollbarClipBehavior clip_behavior,
     InclusiveIntersectOrNot inclusive_behavior,
-    ExpandVisualRectForAnimationOrNot expand_for_animation,
+    ExpandVisualRectForCompositingOverlapOrNot expand,
     bool& success) {
   if (local_state == ancestor_state) {
     success = true;
@@ -178,13 +220,14 @@
   if (&local_state.Effect() != &ancestor_state.Effect()) {
     return SlowLocalToAncestorVisualRectWithEffects(
         local_state, ancestor_state, rect_to_map, clip_behavior,
-        inclusive_behavior, expand_for_animation, success);
+        inclusive_behavior, expand, success);
   }
 
   bool has_animation = false;
+  bool has_fixed = false;
   const auto& translation_2d_or_matrix = SourceToDestinationProjectionInternal(
       local_state.Transform(), ancestor_state.Transform(), has_animation,
-      success);
+      has_fixed, success);
   if (!success) {
     // A failure implies either source-to-plane or destination-to-plane being
     // singular. A notable example of singular source-to-plane from valid CSS:
@@ -202,18 +245,22 @@
     return false;
   }
 
-  if (has_animation && expand_for_animation == kExpandVisualRectForAnimation) {
+  if (has_animation && expand == kExpandVisualRectForCompositingOverlap) {
     // Assume during the animation the transform can map |rect_to_map| to
     // anywhere. Ancestor clips will still apply.
     // TODO(crbug.com/1026653): Use animation bounds instead of infinite rect.
     rect_to_map = InfiniteLooseFloatClipRect();
   } else {
     translation_2d_or_matrix.MapFloatClipRect(rect_to_map);
+    if (has_fixed && expand == kExpandVisualRectForCompositingOverlap) {
+      ExpandFixedBoundsInScroller(&local_state.Transform(),
+                                  &ancestor_state.Transform(), rect_to_map);
+    }
   }
 
   FloatClipRect clip_rect = LocalToAncestorClipRectInternal(
       local_state.Clip(), ancestor_state.Clip(), ancestor_state.Transform(),
-      clip_behavior, inclusive_behavior, expand_for_animation, success);
+      clip_behavior, inclusive_behavior, expand, success);
   if (success) {
     // This is where we propagate the roundedness and tightness of |clip_rect|
     // to |rect_to_map|.
@@ -242,7 +289,7 @@
     FloatClipRect& mapping_rect,
     OverlayScrollbarClipBehavior clip_behavior,
     InclusiveIntersectOrNot inclusive_behavior,
-    ExpandVisualRectForAnimationOrNot expand_for_animation,
+    ExpandVisualRectForCompositingOverlapOrNot expand,
     bool& success) {
   PropertyTreeState last_transform_and_clip_state(
       local_state.Transform(), local_state.Clip(),
@@ -253,7 +300,7 @@
        effect && effect != &ancestor_effect;
        effect = effect->UnaliasedParent()) {
     if (effect->HasActiveFilterAnimation() &&
-        expand_for_animation == kExpandVisualRectForAnimation) {
+        expand == kExpandVisualRectForCompositingOverlap) {
       // Assume during the animation the filter can map |rect_to_map| to
       // anywhere. Ancestor clips will still apply.
       // TODO(crbug.com/1026653): Use animation bounds instead of infinite rect.
@@ -272,7 +319,7 @@
         effect->OutputClip()->Unalias(), EffectPaintPropertyNode::Root());
     bool intersects = LocalToAncestorVisualRectInternal(
         last_transform_and_clip_state, transform_and_clip_state, mapping_rect,
-        clip_behavior, inclusive_behavior, expand_for_animation, success);
+        clip_behavior, inclusive_behavior, expand, success);
     if (!success || !intersects) {
       success = true;
       mapping_rect = FloatClipRect(FloatRect());
@@ -288,8 +335,7 @@
       EffectPaintPropertyNode::Root());
   bool intersects = LocalToAncestorVisualRectInternal(
       last_transform_and_clip_state, final_transform_and_clip_state,
-      mapping_rect, clip_behavior, inclusive_behavior, expand_for_animation,
-      success);
+      mapping_rect, clip_behavior, inclusive_behavior, expand, success);
 
   // Many effects (e.g. filters, clip-paths) can make a clip rect not tight.
   mapping_rect.ClearIsTight();
@@ -308,7 +354,8 @@
   bool success = false;
   auto result = LocalToAncestorClipRectInternal(
       local_clip, ancestor_clip, ancestor_state.Transform(), clip_behavior,
-      kNonInclusiveIntersect, kDontExpandVisualRectForAnimation, success);
+      kNonInclusiveIntersect, kDontExpandVisualRectForCompositingOverlap,
+      success);
   DCHECK(success);
 
   // Many effects (e.g. filters, clip-paths) can make a clip rect not tight.
@@ -335,7 +382,7 @@
     const TransformPaintPropertyNode& ancestor_transform,
     OverlayScrollbarClipBehavior clip_behavior,
     InclusiveIntersectOrNot inclusive_behavior,
-    ExpandVisualRectForAnimationOrNot expand_for_animation,
+    ExpandVisualRectForCompositingOverlapOrNot expand,
     bool& success) {
   if (&descendant_clip == &ancestor_clip) {
     success = true;
@@ -362,7 +409,7 @@
       cached_clip = clip_node->GetClipCache().GetCachedClip(clip_and_transform);
 
     if (cached_clip && cached_clip->has_transform_animation &&
-        expand_for_animation == kExpandVisualRectForAnimation) {
+        expand == kExpandVisualRectForCompositingOverlap) {
       // Don't use cached clip if it's transformed by any animating transform.
       cached_clip = nullptr;
     }
@@ -394,17 +441,18 @@
   for (auto it = intermediate_nodes.rbegin(); it != intermediate_nodes.rend();
        ++it) {
     bool has_animation = false;
+    bool has_fixed = false;
     const auto& translation_2d_or_matrix =
         SourceToDestinationProjectionInternal(
             (*it)->LocalTransformSpace().Unalias(), ancestor_transform,
-            has_animation, success);
+            has_animation, has_fixed, success);
     if (!success) {
       success = true;
       return FloatClipRect(FloatRect());
     }
 
     // Don't apply this clip if it's transformed by any animating transform.
-    if (has_animation && expand_for_animation == kExpandVisualRectForAnimation)
+    if (has_animation && expand == kExpandVisualRectForCompositingOverlap)
       continue;
 
     // This is where we generate the roundedness and tightness of clip rect
@@ -424,7 +472,7 @@
   // Clips that are inclusive intersected or expanded for animation are not
   // cached at present.
   DCHECK(inclusive_behavior == kInclusiveIntersect ||
-         expand_for_animation == kExpandVisualRectForAnimation ||
+         expand == kExpandVisualRectForCompositingOverlap ||
          descendant_clip.GetClipCache()
                  .GetCachedClip(clip_and_transform)
                  ->clip_rect == clip);
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
index 1b3a89b..9c6a917 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -18,15 +18,27 @@
 // Clips can use FloatRect::Intersect or FloatRect::InclusiveIntersect.
 enum InclusiveIntersectOrNot { kNonInclusiveIntersect, kInclusiveIntersect };
 
-// Whether to expand the visual or clip rect to infinity when we meet any
-// animating transform or filter when walking from a descendant state to an
+// When performing overlap testing during compositing, we may need to expand the
+// visual rect in two cases when mapping from descendant state to ancestor
+// state: mapping through a fixed transform node to the viewport it is attached
+// to, and mapping through an animating transform or filter.
+//
+// This allows for a more conservative overlap test that assumes potentially
+// more overlap than we'd encounter otherwise, in order to reduce the need to
+// re-run overlap testing in response to things like scrolling.
+//
+// The expansion for fixed covers all coordinates where the fixed content may
+// end up when the scroller is at the end of the extents.
+//
+// For animation, the visual or clip rect is expanded to infinity when we meet
+// any animating transform or filter when walking from a descendant state to an
 // ancestor state, when mapping a visual rect or getting the accumulated clip
 // rect. After we expanded the rect, we will still apply ancestor clips when
 // continuing walking up the tree. TODO(crbug.com/1026653): Consider animation
 // bounds instead of using infinite rect.
-enum ExpandVisualRectForAnimationOrNot {
-  kDontExpandVisualRectForAnimation,
-  kExpandVisualRectForAnimation,
+enum ExpandVisualRectForCompositingOverlapOrNot {
+  kDontExpandVisualRectForCompositingOverlap,
+  kExpandVisualRectForCompositingOverlap,
 };
 
 // GeometryMapper is a helper class for fast computations of transformed and
@@ -186,9 +198,10 @@
     }
 
     bool has_animation = false;
+    bool has_fixed = false;
     bool success = false;
     const auto& source_to_destination = SourceToDestinationProjectionInternal(
-        source, destination, has_animation, success);
+        source, destination, has_animation, has_fixed, success);
     if (!success)
       mapping_rect = Rect();
     else
@@ -263,11 +276,11 @@
       FloatClipRect& mapping_rect,
       OverlayScrollbarClipBehavior clip = kIgnoreOverlayScrollbarSize,
       InclusiveIntersectOrNot intersect = kNonInclusiveIntersect,
-      ExpandVisualRectForAnimationOrNot animation =
-          kDontExpandVisualRectForAnimation) {
+      ExpandVisualRectForCompositingOverlapOrNot expand =
+          kDontExpandVisualRectForCompositingOverlap) {
     return LocalToAncestorVisualRect(local_state.Unalias(),
                                      ancestor_state.Unalias(), mapping_rect,
-                                     clip, intersect, animation);
+                                     clip, intersect, expand);
   }
   static bool LocalToAncestorVisualRect(
       const PropertyTreeState& local_state,
@@ -275,7 +288,8 @@
       FloatClipRect& mapping_rect,
       OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize,
       InclusiveIntersectOrNot = kNonInclusiveIntersect,
-      ExpandVisualRectForAnimationOrNot = kDontExpandVisualRectForAnimation);
+      ExpandVisualRectForCompositingOverlapOrNot =
+          kDontExpandVisualRectForCompositingOverlap);
 
   static void ClearCache();
 
@@ -289,6 +303,7 @@
       const TransformPaintPropertyNode& source,
       const TransformPaintPropertyNode& destination,
       bool& has_animation,
+      bool& has_fixed,
       bool& success);
 
   static FloatClipRect LocalToAncestorClipRectInternal(
@@ -297,7 +312,7 @@
       const TransformPaintPropertyNode& ancestor_transform,
       OverlayScrollbarClipBehavior,
       InclusiveIntersectOrNot,
-      ExpandVisualRectForAnimationOrNot,
+      ExpandVisualRectForCompositingOverlapOrNot,
       bool& success);
 
   // The return value has the same meaning as that for
@@ -308,7 +323,7 @@
       FloatClipRect& mapping_rect,
       OverlayScrollbarClipBehavior,
       InclusiveIntersectOrNot,
-      ExpandVisualRectForAnimationOrNot,
+      ExpandVisualRectForCompositingOverlapOrNot,
       bool& success);
 
   // The return value has the same meaning as that for
@@ -319,7 +334,7 @@
       FloatClipRect& mapping_rect,
       OverlayScrollbarClipBehavior,
       InclusiveIntersectOrNot,
-      ExpandVisualRectForAnimationOrNot,
+      ExpandVisualRectForCompositingOverlapOrNot,
       bool& success);
 
   static void MoveRect(FloatRect& rect, const FloatSize& delta) {
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
index 0f2a1ff..33ddcd3 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -36,7 +36,8 @@
       bool& success) {
     GeometryMapper::LocalToAncestorVisualRectInternal(
         local_state, ancestor_state, mapping_rect, kIgnoreOverlayScrollbarSize,
-        kNonInclusiveIntersect, kDontExpandVisualRectForAnimation, success);
+        kNonInclusiveIntersect, kDontExpandVisualRectForCompositingOverlap,
+        success);
   }
 
   void CheckMappings();
@@ -52,7 +53,7 @@
   PropertyTreeStateOrAlias ancestor_state = PropertyTreeState::Root();
   FloatRect input_rect;
   FloatClipRect expected_visual_rect;
-  absl::optional<FloatClipRect> expected_visual_rect_expanded_for_animation;
+  absl::optional<FloatClipRect> expected_visual_rect_expanded_for_compositing;
   FloatSize expected_translation_2d;
   absl::optional<TransformationMatrix> expected_transform;
   FloatClipRect expected_clip;
@@ -94,9 +95,9 @@
   GeometryMapper::LocalToAncestorVisualRect(
       local_state, ancestor_state, actual_visual_rect,
       kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect,
-      kExpandVisualRectForAnimation);
-  EXPECT_CLIP_RECT_EQ(expected_visual_rect_expanded_for_animation
-                          ? *expected_visual_rect_expanded_for_animation
+      kExpandVisualRectForCompositingOverlap);
+  EXPECT_CLIP_RECT_EQ(expected_visual_rect_expanded_for_compositing
+                          ? *expected_visual_rect_expanded_for_compositing
                           : expected_visual_rect,
                       actual_visual_rect);
 }
@@ -560,7 +561,7 @@
   expected_visual_rect.Intersect(FloatClipRect(clip->UnsnappedClipRect()));
   expected_visual_rect.Map(*expected_transform);
   // The clip has animating transform, so it doesn't apply to the visual rect.
-  expected_visual_rect_expanded_for_animation = InfiniteLooseFloatClipRect();
+  expected_visual_rect_expanded_for_compositing = InfiniteLooseFloatClipRect();
   EXPECT_FALSE(expected_visual_rect.IsTight());
   expected_clip = FloatClipRect(clip->UnsnappedClipRect());
   expected_clip.Map(*expected_transform);
@@ -605,8 +606,8 @@
   EXPECT_TRUE(expected_clip.IsTight());
   // The visual rect is expanded first to infinity because of the transform
   // animation, then clipped by the clip.
-  expected_visual_rect_expanded_for_animation = expected_clip;
-  expected_visual_rect_expanded_for_animation->ClearIsTight();
+  expected_visual_rect_expanded_for_compositing = expected_clip;
+  expected_visual_rect_expanded_for_compositing->ClearIsTight();
   CheckMappings();
 }
 
@@ -664,9 +665,56 @@
   // The visual rect is expanded to infinity because of the transform animation,
   // then clipped by clip1. clip2 doesn't apply because it's below the animating
   // transform.
-  expected_visual_rect_expanded_for_animation =
+  expected_visual_rect_expanded_for_compositing =
       FloatClipRect(clip1->UnsnappedClipRect());
-  expected_visual_rect_expanded_for_animation->ClearIsTight();
+  expected_visual_rect_expanded_for_compositing->ClearIsTight();
+  CheckMappings();
+}
+
+TEST_P(GeometryMapperTest, ExpandVisualRectForFixed) {
+  auto above_viewport = CreateTransform(t0(), TransformationMatrix());
+  auto viewport = CreateTransform(*above_viewport, TransformationMatrix());
+  auto scroll_translation = CreateScrollTranslation(
+      *viewport, -100, -200, IntRect(0, 0, 800, 600), IntSize(2400, 1800),
+      CompositingReason::kOverflowScrolling);
+
+  auto fixed_translate = TransformationMatrix().Translate(100, 0);
+
+  const FloatSize fixed_offset(200, 200);
+  TransformPaintPropertyNode::State fixed_state{fixed_offset, nullptr,
+                                                scroll_translation};
+  fixed_state.direct_compositing_reasons = CompositingReason::kFixedPosition;
+  auto fixed_transform =
+      TransformPaintPropertyNode::Create(*viewport, std::move(fixed_state));
+
+  const FloatSize child_of_fixed_offset(50, 50);
+  TransformPaintPropertyNode::State child_of_fixed_state{child_of_fixed_offset};
+  auto child_of_fixed = TransformPaintPropertyNode::Create(
+      *fixed_transform, std::move(child_of_fixed_state));
+
+  local_state.SetTransform(*child_of_fixed);
+  ancestor_state.SetTransform(*viewport);
+
+  const FloatSize child_of_fixed_size(100, 100);
+  input_rect = FloatRect(FloatPoint(), child_of_fixed_size);
+
+  const FloatSize descendant_offset = fixed_offset + child_of_fixed_offset;
+  expected_translation_2d = descendant_offset;
+  expected_transformed_rect =
+      FloatRect(FloatPoint(descendant_offset), child_of_fixed_size);
+  expected_visual_rect = FloatClipRect(expected_transformed_rect);
+  expected_visual_rect_expanded_for_compositing =
+      FloatClipRect(FloatRect(150, 50, 1700, 1300));
+
+  CheckMappings();
+
+  // If we're not mapping to the viewport, the fixed rect should not be
+  // expanded.
+  ancestor_state.SetTransform(*above_viewport);
+  expected_transform = TransformationMatrix().Translate(
+      descendant_offset.Width(), descendant_offset.Height());
+  expected_visual_rect.ClearIsTight();
+  expected_visual_rect_expanded_for_compositing = expected_visual_rect;
   CheckMappings();
 }
 
@@ -876,9 +924,9 @@
   // The visual rect is expanded to infinity because of the filter animation,
   // the clipped by clip1. clip2 doesn't apply because it's below the animating
   // filter.
-  expected_visual_rect_expanded_for_animation =
+  expected_visual_rect_expanded_for_compositing =
       FloatClipRect(clip1->UnsnappedClipRect());
-  expected_visual_rect_expanded_for_animation->ClearIsTight();
+  expected_visual_rect_expanded_for_compositing->ClearIsTight();
   CheckMappings();
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
index afbb15b..410e1eb05 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
@@ -40,6 +40,7 @@
   const GeometryMapperTransformCache& parent =
       node.UnaliasedParent()->GetTransformCache();
 
+  has_fixed_ = node.RequiresCompositingForFixedPosition() || parent.has_fixed_;
   // screen_transform_ will be updated only when needed.
   screen_transform_ = nullptr;
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
index da3cb0d..a7b9993 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
@@ -112,6 +112,8 @@
            plane_root_transform_->has_animation;
   }
 
+  bool has_fixed() const { return has_fixed_; }
+
  private:
   friend class GeometryMapperTransformCacheTest;
 
@@ -203,6 +205,9 @@
   };
   std::unique_ptr<ScreenTransform> screen_transform_;
 
+  // Whether or not there is a fixed position transform to the root.
+  bool has_fixed_ = false;
+
   unsigned cache_generation_ = s_global_generation - 1;
   DISALLOW_COPY_AND_ASSIGN(GeometryMapperTransformCache);
 };
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
index c85b65a2b..bf844a8 100644
--- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
@@ -12,11 +12,9 @@
   DEFINE_STATIC_REF(
       TransformPaintPropertyNode, root,
       base::AdoptRef(new TransformPaintPropertyNode(
-          nullptr,
-          State{
-              FloatSize(), &ScrollPaintPropertyNode::Root(),
-              State::Flags{false /* flattens_inherited_transform */,
-                           false /* in_subtree_of_page_scale */}})));
+          nullptr, State{FloatSize(), &ScrollPaintPropertyNode::Root(), nullptr,
+                         State::Flags{false /* flattens_inherited_transform */,
+                                      false /* in_subtree_of_page_scale */}})));
   return *root;
 }
 
@@ -81,6 +79,12 @@
   }
   if (state_.scroll)
     json->SetString("scroll", String::Format("%p", state_.scroll.get()));
+
+  if (state_.scroll_translation_for_fixed) {
+    json->SetString(
+        "scroll_translation_for_fixed",
+        String::Format("%p", state_.scroll_translation_for_fixed.get()));
+  }
   return json;
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
index 1bab0511a..5222435 100644
--- a/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
+++ b/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
@@ -160,6 +160,8 @@
   struct State {
     TransformAndOrigin transform_and_origin;
     scoped_refptr<const ScrollPaintPropertyNode> scroll;
+    scoped_refptr<const TransformPaintPropertyNode>
+        scroll_translation_for_fixed;
     // Use bitfield packing instead of separate bools to save space.
     struct Flags {
       bool flattens_inherited_transform : 1;
@@ -200,7 +202,9 @@
           backface_visibility != other.backface_visibility ||
           rendering_context_id != other.rendering_context_id ||
           compositor_element_id != other.compositor_element_id ||
-          scroll != other.scroll || !StickyConstraintEquals(other) ||
+          scroll != other.scroll ||
+          scroll_translation_for_fixed != other.scroll_translation_for_fixed ||
+          !StickyConstraintEquals(other) ||
           visible_frame_element_id != other.visible_frame_element_id) {
         return PaintPropertyChangeType::kChangedOnlyValues;
       }
@@ -322,6 +326,10 @@
     return state_.scroll.get();
   }
 
+  const TransformPaintPropertyNode* ScrollTranslationForFixed() const {
+    return state_.scroll_translation_for_fixed.get();
+  }
+
   // If true, this node is translated by the viewport bounds delta, which is
   // used to keep bottom-fixed elements appear fixed to the bottom of the
   // screen in the presence of URL bar movement.
@@ -414,9 +422,13 @@
            CompositingReason::kActiveTransformAnimation;
   }
 
+  bool RequiresCompositingForFixedPosition() const {
+    return DirectCompositingReasons() & CompositingReason::kFixedPosition;
+  }
+
   bool RequiresCompositingForScrollDependentPosition() const {
     return DirectCompositingReasons() &
-           CompositingReason::kScrollDependentPosition;
+           CompositingReason::kComboScrollDependentPosition;
   }
 
   CompositingReasons DirectCompositingReasonsForDebugging() const {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 89fef926..76c1f98 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -610,6 +610,10 @@
       status: "experimental",
     },
     {
+      name: "CSSPseudoHas",
+      status: "test",
+    },
+    {
       // When an audio, video, or similar resource is "playing"
       // or "paused".
       // https://www.w3.org/TR/selectors-4/#video-state
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.cc b/third_party/blink/renderer/platform/weborigin/kurl.cc
index 5e36294c..ef97c833 100644
--- a/third_party/blink/renderer/platform/weborigin/kurl.cc
+++ b/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -442,7 +442,28 @@
   return ComponentString(parsed_.path);
 }
 
+namespace {
+
+bool IsASCIITabOrNewline(UChar ch) {
+  return ch == '\t' || ch == '\r' || ch == '\n';
+}
+
+// See https://url.spec.whatwg.org/#concept-basic-url-parser:
+// 3. Remove all ASCII tab or newline from |input|.
+//
+// Matches url::RemoveURLWhitespace.
+String RemoveURLWhitespace(const String& input) {
+  return input.RemoveCharacters(IsASCIITabOrNewline);
+}
+
+}  // namespace
+
 bool KURL::SetProtocol(const String& protocol) {
+  // We should remove whitespace from |protocol| according to spec, but Firefox
+  // and Safari don't do it.
+  // - https://url.spec.whatwg.org/#dom-url-protocol
+  // - https://github.com/whatwg/url/issues/609
+
   // Firefox and IE remove everything after the first ':'.
   wtf_size_t separator_position = protocol.find(':');
   String new_protocol = protocol.Substring(0, separator_position);
@@ -544,7 +565,8 @@
 
 }  // namespace
 
-void KURL::SetHost(const String& host) {
+void KURL::SetHost(const String& input) {
+  String host = RemoveURLWhitespace(input);
   wtf_size_t value_end = FindHostEnd(host, IsHierarchical());
   String truncated_host = host.Substring(0, value_end);
   StringUTF8Adaptor host_utf8(truncated_host);
@@ -554,10 +576,12 @@
   ReplaceComponents(replacements);
 }
 
-void KURL::SetHostAndPort(const String& orig_host_and_port) {
+void KURL::SetHostAndPort(const String& input) {
   // This method intentionally does very sloppy parsing for backwards
   // compatibility. See https://url.spec.whatwg.org/#host-state for what we
   // theoretically should be doing.
+
+  String orig_host_and_port = RemoveURLWhitespace(input);
   wtf_size_t value_end = FindHostEnd(orig_host_and_port, IsHierarchical());
   String host_and_port = orig_host_and_port.Substring(0, value_end);
 
@@ -616,7 +640,8 @@
   ReplaceComponents(replacements);
 }
 
-void KURL::SetPort(const String& port) {
+void KURL::SetPort(const String& input) {
+  String port = RemoveURLWhitespace(input);
   String parsed_port = ParsePortFromStringPosition(port, 0);
   if (!parsed_port.IsEmpty())
     SetPort(parsed_port.ToUInt());
@@ -645,6 +670,9 @@
 
   // The canonicalizer will clear any usernames that are empty, so we
   // don't have to explicitly call ClearUsername() here.
+  //
+  // Unlike other setters, we do not remove whitespace per spec:
+  // https://url.spec.whatwg.org/#dom-url-username
   StringUTF8Adaptor user_utf8(user);
   url::Replacements<char> replacements;
   replacements.SetUsername(CharactersOrEmpty(user_utf8),
@@ -660,6 +688,9 @@
 
   // The canonicalizer will clear any passwords that are empty, so we
   // don't have to explicitly call ClearUsername() here.
+  //
+  // Unlike other setters, we do not remove whitespace per spec:
+  // https://url.spec.whatwg.org/#dom-url-password
   StringUTF8Adaptor pass_utf8(pass);
   url::Replacements<char> replacements;
   replacements.SetPassword(CharactersOrEmpty(pass_utf8),
@@ -667,12 +698,13 @@
   ReplaceComponents(replacements);
 }
 
-void KURL::SetFragmentIdentifier(const String& fragment) {
+void KURL::SetFragmentIdentifier(const String& input) {
   // This function is commonly called to clear the ref, which we
   // normally don't have, so we optimize this case.
-  if (fragment.IsNull() && !parsed_.ref.is_valid())
+  if (input.IsNull() && !parsed_.ref.is_valid())
     return;
 
+  String fragment = RemoveURLWhitespace(input);
   StringUTF8Adaptor fragment_utf8(fragment);
 
   url::Replacements<char> replacements;
@@ -691,7 +723,8 @@
   ReplaceComponents(replacements);
 }
 
-void KURL::SetQuery(const String& query) {
+void KURL::SetQuery(const String& input) {
+  String query = RemoveURLWhitespace(input);
   StringUTF8Adaptor query_utf8(query);
   url::Replacements<char> replacements;
   if (query.IsNull()) {
@@ -715,9 +748,10 @@
   ReplaceComponents(replacements);
 }
 
-void KURL::SetPath(const String& path) {
+void KURL::SetPath(const String& input) {
   // Empty paths will be canonicalized to "/", so we don't have to worry
   // about calling ClearPath().
+  String path = RemoveURLWhitespace(input);
   StringUTF8Adaptor path_utf8(path);
   url::Replacements<char> replacements;
   replacements.SetPath(CharactersOrEmpty(path_utf8),
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
index f8e67108..a8d361a0 100644
--- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint
+++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -43,10 +43,6 @@
 crbug.com/1123189 virtual/threaded-composited-iframes/external/wpt/is-input-pending/security/cross-origin-subframe-masked-pointer-events-mixed-2.sub.html [ Failure ]
 crbug.com/1123189 virtual/threaded-composited-iframes/external/wpt/is-input-pending/security/cross-origin-subframe-complex-clip.sub.html [ Failure ]
 
-# Fixed-position element gets composited/decomposited on overlap change during scroll.
-crbug.com/1099379 compositing/squashing/squash-above-fixed-1.html [ Failure ]
-crbug.com/1099379 compositing/squashing/squash-above-fixed-3.html [ Failure ]
-
 # FragmentClip hierarchy issue. Will be fixed by LayoutNGBlockFragmentation.
 crbug.com/1157199 external/wpt/css/css-paint-api/column-count-crash.https.html [ Crash ]
 crbug.com/1157199 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/column-count-crash.https.html [ Crash ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a7bc0b13..f9e2268 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4344,7 +4344,7 @@
 crbug.com/681468 [ Win ] virtual/scalefactor200withzoom/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass Timeout ]
 crbug.com/681468 [ Win ] virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass Timeout ]
 
-crbug.com/1157857 [ Mac ] virtual/percent-based-scrolling/max-percent-delta-cross-origin-iframes.html [ Pass Timeout ]
+crbug.com/1157857 virtual/percent-based-scrolling/max-percent-delta-cross-origin-iframes.html [ Failure Pass Timeout ]
 
 crbug.com/683800 [ Win7 Debug ] external/wpt/selection/* [ Failure Pass ]
 
@@ -6924,9 +6924,6 @@
 crbug.com/1048761 external/wpt/websockets/interfaces/WebSocket/events/018.html?wpt_flags=h2 [ Failure ]
 crbug.com/1048761 external/wpt/websockets/interfaces/WebSocket/send/006.html?wpt_flags=h2 [ Failure ]
 
-# Temporarily disable to unblock a WebRTC roll
-crbug.com/webrtc/10686 external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ]
-
 # Fix to unblock wpt-importer
 crbug.com/1209223 external/wpt/css/css-typed-om/idlharness.html [ Failure ]
 crbug.com/1209223 external/wpt/html/dom/idlharness.https.html?exclude=(Document|Window|HTML.\*) [ Failure ]
@@ -6978,3 +6975,7 @@
 crbug.com/1215575 [ Mac11.0 ] fast/peerconnection/RTCPeerConnection-sdes-gcm.html [ Pass Timeout ]
 crbug.com/1215581 [ Mac11.0 ] svg/filters/feImage-preserveAspectRatio-all.svg [ Pass Failure ]
 crbug.com/1215584 [ Mac11.0 ] inspector-protocol/layout-fonts/lang-fallback.js [ Pass Failure ]
+
+# Sheriff 2021-06-03
+crbug.com/1185121 fast/scroll-snap/animate-fling-to-snap-points-1.html [ Pass Failure ]
+crbug.com/1215949 external/wpt/pointerevents/pointerevent_iframe-touch-action-none_touch.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
index 8f172fff..59d02c5 100644
--- a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
+++ b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
@@ -10,55 +10,61 @@
 # Test fails when run on Android.
 crbug.com/1197454 external/wpt/document-policy/experimental-features/unsized-media.tentative.https.sub.html [ Failure ]
 
+# Basic card is not supported in WebLayer.
+crbug.com/1213456 external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https.html [ Skip ]
+
+# Periodic background sync is not supported in WebLayer.
+crbug.com/1091211 external/wpt/periodic-background-sync/periodicsync.https.window.html [ Skip ]
+
 # This test is flaky.
 crbug.com/1126079 external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html [ Crash Pass Timeout ]
 
 # Web notifications are not supported in WebLayer.
-crbug.com/1025610 external/wpt/notifications/idlharness.https.any.html [ Failure ]
-crbug.com/1025610 external/wpt/notifications/idlharness.https.any.serviceworker.html [ Failure ]
-crbug.com/1025610 external/wpt/notifications/idlharness.https.any.sharedworker.html [ Failure ]
-crbug.com/1025610 external/wpt/notifications/idlharness.https.any.worker.html [ Failure ]
-crbug.com/1025610 external/wpt/notifications/instance.html [ Failure ]
-crbug.com/1025610 external/wpt/notifications/permission.html [ Failure ]
+crbug.com/1025610 external/wpt/notifications/idlharness.https.any.html [ Skip ]
+crbug.com/1025610 external/wpt/notifications/idlharness.https.any.serviceworker.html [ Skip ]
+crbug.com/1025610 external/wpt/notifications/idlharness.https.any.sharedworker.html [ Skip ]
+crbug.com/1025610 external/wpt/notifications/idlharness.https.any.worker.html [ Skip ]
+crbug.com/1025610 external/wpt/notifications/instance.html [ Skip ]
+crbug.com/1025610 external/wpt/notifications/permission.html [ Skip ]
 
 # Portals are not yet supported in WebLayer.
-crbug.com/1174856 external/wpt/portals/csp/frame-src.sub.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/history/history-manipulation-inside-portal-with-subframes.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/history/history-manipulation-inside-portal.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portal-activate-data.html [ Failure Timeout ]
-crbug.com/1174856 external/wpt/portals/portal-activate-default.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portal-activate-event.html [ Failure Timeout ]
-crbug.com/1174856 external/wpt/portals/portal-non-http-navigation.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portal-onload-event.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-activate-inside-portal.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-activate-resolution.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-activate-twice.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-activate-while-unloading.html [ Timeout ]
-crbug.com/1174856 external/wpt/portals/portals-adopt-predecessor.html [ Failure Timeout ]
-crbug.com/1174856 external/wpt/portals/portals-close-window.html [ Failure Pass ]
-crbug.com/1174856 external/wpt/portals/portals-focus.sub.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-host-exposure.sub.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-host-hidden-after-activation.html [ Failure Timeout ]
-crbug.com/1174856 external/wpt/portals/portals-host-post-message.sub.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-navigate-after-adoption.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-nested.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-post-message.sub.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-referrer-inherit-header.html [ Failure Pass ]
-crbug.com/1174856 external/wpt/portals/portals-referrer-inherit-meta.html [ Failure Pass ]
-crbug.com/1174856 external/wpt/portals/portals-referrer.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-repeated-activate.html [ Failure ]
-crbug.com/1174856 external/wpt/portals/portals-set-src-after-activate.html [ Failure Timeout ]
-crbug.com/1174856 external/wpt/portals/predecessor-fires-unload.html [ Failure Timeout ]
-crbug.com/1174856 external/wpt/portals/xfo/portals-xfo-sameorigin.html [ Failure ]
+crbug.com/1174856 external/wpt/portals/csp/frame-src.sub.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/history/history-manipulation-inside-portal-with-subframes.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/history/history-manipulation-inside-portal.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portal-activate-data.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portal-activate-default.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portal-activate-event.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portal-non-http-navigation.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portal-onload-event.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-activate-inside-portal.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-activate-resolution.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-activate-twice.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-activate-while-unloading.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-adopt-predecessor.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-close-window.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-focus.sub.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-host-exposure.sub.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-host-hidden-after-activation.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-host-post-message.sub.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-navigate-after-adoption.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-nested.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-post-message.sub.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-referrer-inherit-header.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-referrer-inherit-meta.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-referrer.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-repeated-activate.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/portals-set-src-after-activate.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/predecessor-fires-unload.html [ Skip ]
+crbug.com/1174856 external/wpt/portals/xfo/portals-xfo-sameorigin.html [ Skip ]
 
 # This test fails in WebLayer and Clank.
 crbug.com/1145401 external/wpt/presentation-api/controlling-ua/getAvailability.https.html [ Failure ]
 
 # Push API is not supported in WebLayer.
-crbug.com/1025610 external/wpt/push-api/idlharness.https.any.html [ Failure ]
-crbug.com/1025610 external/wpt/push-api/idlharness.https.any.serviceworker.html [ Failure ]
-crbug.com/1025610 external/wpt/push-api/idlharness.https.any.sharedworker.html [ Failure ]
-crbug.com/1025610 external/wpt/push-api/idlharness.https.any.worker.html [ Failure ]
+crbug.com/1025610 external/wpt/push-api/idlharness.https.any.html [ Skip ]
+crbug.com/1025610 external/wpt/push-api/idlharness.https.any.serviceworker.html [ Skip ]
+crbug.com/1025610 external/wpt/push-api/idlharness.https.any.sharedworker.html [ Skip ]
+crbug.com/1025610 external/wpt/push-api/idlharness.https.any.worker.html [ Skip ]
 
 # Several scroll animations tests fail in WebLayer and Clank.
 crbug.com/1198063 external/wpt/scroll-animations/css/at-scroll-timeline-start-end.html [ Failure ]
@@ -1264,7 +1270,6 @@
 crbug.com/1050754 external/wpt/paint-timing/with-first-paint/sibling-painting-first-image.html [ Failure ]
 crbug.com/1050754 external/wpt/payment-handler/can-make-payment-event.https.html [ Failure Timeout ]
 crbug.com/1050754 external/wpt/payment-handler/respond-with-minimal-ui.https.html [ Failure Timeout ]
-crbug.com/1050754 external/wpt/payment-method-basic-card/payment-request-canmakepayment-method.https.html [ Failure Timeout ]
 crbug.com/1050754 external/wpt/payment-request/constructor_convert_method_data.https.html [ Pass Timeout ]
 crbug.com/1050754 external/wpt/payment-request/payment-request-abort-method.https.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/payment-request/payment-request-canmakepayment-method.https.html [ Timeout ]
@@ -1275,7 +1280,6 @@
 crbug.com/1050754 external/wpt/payment-request/show-consume-activation.https.html [ Failure Timeout ]
 crbug.com/1050754 external/wpt/payment-request/show-method-optional-promise-rejects.https.html [ Pass ]
 crbug.com/1050754 external/wpt/performance-timeline/idlharness.any.sharedworker.html [ Failure ]
-crbug.com/1050754 external/wpt/periodic-background-sync/periodicsync.https.window.html [ Failure ]
 crbug.com/1050754 external/wpt/permissions-policy/picture-in-picture-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html [ Failure ]
 crbug.com/1050754 external/wpt/permissions-policy/picture-in-picture-allowed-by-permissions-policy-attribute.https.sub.html [ Failure ]
 crbug.com/1050754 external/wpt/permissions-policy/picture-in-picture-allowed-by-permissions-policy.https.sub.html [ Failure ]
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt
new file mode 100644
index 0000000..c1eb11d1
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt
@@ -0,0 +1,106 @@
+Before:
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutView #document",
+      "bounds": [300, 150],
+      "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed'",
+      "bounds": [30, 30],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='overlapped'",
+      "position": [8, 1008],
+      "bounds": [40, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFA500",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
+After scroll:
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutView #document",
+      "bounds": [300, 150],
+      "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed'",
+      "bounds": [30, 30],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='overlapped'",
+      "position": [8, 102],
+      "bounds": [40, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFA500",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap.html b/third_party/blink/web_tests/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap.html
new file mode 100644
index 0000000..d0e4bec
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!-- This test validates that overlap testing for fixed within an iframe with
+     overflow hidden either correctly performs overlap testing with an expanded
+     rect for the fixed content up front (pre-CAP) or invalidates appropriately
+     so that overlap testing is re-run when the scroll offset updates. Note
+     that this runs in an iframe to specifically test the case where there is
+     no paint property scroll node for iframe with overflow: hidden (root will
+     always have scroll translation and scroll node). If the CAP implementation
+     ends up changing to include this type of (uncommon) overlap testing,
+     rebaseline the expected.txt to have the same layer tree structure before
+     and after the scroll update. -->
+<iframe id="iframe" srcdoc="
+  <style>
+    html { overflow: hidden; }
+    .fixed {
+      position: fixed;
+      bottom: 20px;
+      width: 30px;
+      height: 30px;
+      background: blue;
+    }
+    .tall { height: 1000px; }
+    .overlapped {
+      position: relative;
+      width: 40px;
+      height: 40px;
+      background: orange;
+      z-index: 1;
+    }
+  </style>
+  <body>
+    <div class='fixed'></div>
+    <div class='tall'></div>
+    <div class='overlapped'></div>
+"></iframe>
+
+<pre></pre>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+if (window.testRunner && window.internals) {
+  testRunner.dumpAsText();
+  testRunner.waitUntilDone();
+  internals.settings.setPreferCompositingToLCDTextEnabled(true);
+}
+
+let iframe = document.querySelector('iframe');
+iframe.addEventListener('load', function() {
+  runAfterLayoutAndPaint(function() {
+    if (window.testRunner) {
+      let dumpText = "Before:\n" + internals.layerTreeAsText(document);
+      let iframeHtmlElem = iframe.contentDocument.documentElement;
+      iframeHtmlElem.scrollTop = iframeHtmlElem.offsetHeight;
+      runAfterLayoutAndPaint(function() {
+        dumpText += "\nAfter scroll:\n" + internals.layerTreeAsText(document);
+        document.querySelector('pre').textContent = dumpText;
+      }, true);
+    }
+  });
+});
+</script>
+
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-nested-fixed-position-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-nested-fixed-position-expected.txt
new file mode 100644
index 0000000..baeb604f
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-nested-fixed-position-expected.txt
@@ -0,0 +1,54 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 1061],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed parent'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFF00"
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed nested'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFF00",
+      "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='overlapped with-parent'",
+      "position": [8, 208],
+      "bounds": [20, 20],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='overlapped with-nested')",
+      "position": [258, 228],
+      "bounds": [20, 20],
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [785, 0],
+      "bounds": [15, 600],
+      "contentsOpaque": true
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [200, 0, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-nested-fixed-position.html b/third_party/blink/web_tests/compositing/layer-creation/overlap-nested-fixed-position.html
new file mode 100644
index 0000000..cdd1776
--- /dev/null
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-nested-fixed-position.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<style>
+.fixed {
+  position: fixed;
+  width: 100px;
+  height: 100px;
+  background-color: yellow;
+}
+
+.parent {
+  top: 0px;
+  left: 0px;
+}
+
+.nested {
+  left: 200px;
+}
+
+.overlapped {
+  position: relative;
+  top: 200px;
+  width: 20px;
+  height: 20px;
+  background: blue;
+  z-index: 1;
+}
+
+.with-nested {
+  left: 250px;
+}
+
+.tall {
+  height: 1000px;
+}
+
+</style>
+
+<!-- This test validates that overlap testing for nested fixed (as long as
+     still attached to the viewport) expands fixed rect.
+     In the below markup, the two .overlapped elements should be detected as
+     overlapping with the expanded fixed rects, respectively. -->
+<div class="fixed parent">
+  <div class="fixed nested"></div>
+</div>
+<div class="overlapped with-parent"></div>
+<div class="overlapped with-nested"></div>
+<div class="tall"></div>
+
+<pre></pre>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<script>
+if (window.testRunner && window.internals) {
+  testRunner.dumpAsText();
+  testRunner.waitUntilDone();
+  internals.settings.setPreferCompositingToLCDTextEnabled(true);
+}
+
+runAfterLayoutAndPaint(function() {
+  if (window.testRunner)
+    document.querySelector('pre').textContent = internals.layerTreeAsText(document);
+}, true);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-item-auto-margins-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-item-auto-margins-001.html
new file mode 100644
index 0000000..be5eb6e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-item-auto-margins-001.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1213878">
+<meta name="assert" content="Auto margin alignment should be safe.">
+<style>
+#grid {
+  display: grid;
+  width: 100px;
+  height: 100px;
+  background: red;
+  grid-template: 0px / 0px;
+}
+
+#grid > div {
+  width: 100px;
+  height: 100px;
+  background: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="grid">
+  <div style="margin: auto;"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-item-auto-margins-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-item-auto-margins-002.html
new file mode 100644
index 0000000..037794e6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-item-auto-margins-002.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1213878">
+<meta name="assert" content="Auto margin alignment should be safe.">
+<style>
+#grid {
+  display: grid;
+  width: 100px;
+  height: 100px;
+  background: red;
+  grid-template: 0px / 0px;
+}
+
+#grid > div {
+  width: 100px;
+  height: 100px;
+  background: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="grid">
+  <div style="margin-left: auto; margin-top: auto;"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-basic-expected.txt b/third_party/blink/web_tests/external/wpt/css/selectors/has-basic-expected.txt
new file mode 100644
index 0000000..e27b6f99
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-basic-expected.txt
@@ -0,0 +1,26 @@
+This is a testharness.js-based test.
+PASS :has(#a) matches expected elements
+PASS :has(.ancestor) matches expected elements
+PASS :has(.target) matches expected elements
+PASS :has(.descendant) matches expected elements
+PASS .parent:has(.target) matches expected elements
+PASS :has(.sibling ~ .target) matches expected elements
+PASS .parent:has(.sibling ~ .target) matches expected elements
+PASS :has(:is(.target ~ .sibling .descendant)) matches expected elements
+PASS .parent:has(:is(.target ~ .sibling .descendant)) matches expected elements
+PASS .sibling:has(.descendant) ~ .target matches expected elements
+PASS :has(.sibling:has(.descendant) ~ .target) matches expected elements
+PASS :has(.sibling:has(.descendant) ~ .target) ~ .parent > .descendant matches expected elements
+PASS :has(:scope .target) matches expected elements
+PASS :has(:scope > .parent) matches expected elements
+FAIL :has(> .target) matches expected elements Failed to execute 'querySelectorAll' on 'Element': ':has(> .target)' is not a valid selector.
+FAIL :has(:scope > .target) matches expected elements assert_equals: expected "b,f,h" but got ""
+FAIL .target:has(+ .sibling) matches expected elements Failed to execute 'querySelectorAll' on 'Element': '.target:has(+ .sibling)' is not a valid selector.
+FAIL .target:has(:scope + .sibling) matches expected elements assert_equals: expected "i" but got ""
+FAIL .parent:has(~ #h) matches expected elements Failed to execute 'querySelectorAll' on 'Element': '.parent:has(~ #h)' is not a valid selector.
+FAIL .parent:has(:scope ~ #h) matches expected elements assert_equals: expected "b,f" but got ""
+PASS .sibling:has(.descendant) matches expected element
+PASS closest(.ancestor:has(.descendant)) returns expected element
+PASS :has(.target ~ .sibling .descendant) matches expectedly
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-basic.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-basic.html
new file mode 100644
index 0000000..3cd6e11
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-basic.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Basic matching behavior of :has pseudo class</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/selectors/#relational">
+
+<main id=main>
+  <div id=a class="ancestor">
+    <div id=b class="parent ancestor">
+      <div id=c class="sibling descendant">
+        <div id=d class="descendant"></div>
+      </div>
+      <div id=e class="target descendant"></div>
+    </div>
+    <div id=f class="parent ancestor">
+      <div id=g class="target descendant"></div>
+    </div>
+    <div id=h class="parent ancestor">
+      <div id=i class="target descendant"></div>
+      <div id=j class="sibling descendant">
+        <div id=k class="descendant"></div>
+      </div>
+    </div>
+  </div>
+</main>
+
+<script>
+  function formatElements(elements) {
+    return elements.map(e => e.id).sort().join();
+  }
+
+  // Test that |selector| returns the given elements in #main.
+  function test_selector_all(selector, expected) {
+    test(function() {
+      let actual = Array.from(main.querySelectorAll(selector));
+      assert_equals(formatElements(actual), formatElements(expected));
+    }, `${selector} matches expected elements`);
+  }
+
+  // Test that |selector| returns the given element in #main.
+  function test_selector(selector, expected) {
+    test(function() {
+      assert_equals(main.querySelector(selector), expected);
+    }, `${selector} matches expected element`);
+  }
+
+  // Test that |selector| returns the given closest element.
+  function test_closest(node, selector, expected) {
+    test(function() {
+      assert_equals(node.closest(selector), expected);
+    }, `closest(${selector}) returns expected element`);
+  }
+
+  // Test that |selector| returns matching status.
+  function test_matches(node, selector, expected) {
+    test(function() {
+      assert_equals(node.matches(selector), expected);
+    }, `${selector} matches expectedly`);
+  }
+
+  test_selector_all(':has(#a)', []);
+  test_selector_all(':has(.ancestor)', [a]);
+  test_selector_all(':has(.target)', [a, b, f, h]);
+  test_selector_all(':has(.descendant)', [a, b, f, h, j]);
+  test_selector_all('.parent:has(.target)', [b, f, h]);
+  test_selector_all(':has(.sibling ~ .target)', [a, b]);
+  test_selector_all('.parent:has(.sibling ~ .target)', [b]);
+  test_selector_all(':has(:is(.target ~ .sibling .descendant))', [a, h, j]);
+  test_selector_all('.parent:has(:is(.target ~ .sibling .descendant))', [h]);
+  test_selector_all('.sibling:has(.descendant) ~ .target', [e]);
+  test_selector_all(':has(.sibling:has(.descendant) ~ .target)', [a, b]);
+  test_selector_all(
+      ':has(.sibling:has(.descendant) ~ .target) ~ .parent > .descendant',
+      [g, i, j]);
+  test_selector_all(':has(:scope .target)', [a, b, f, h]);
+  test_selector_all(':has(:scope > .parent)', [a]);
+  test_selector_all(':has(> .target)', [b, f, h]);
+  test_selector_all(':has(:scope > .target)', [b, f, h]);
+  test_selector_all('.target:has(+ .sibling)', [i]);
+  test_selector_all('.target:has(:scope + .sibling)', [i]);
+  test_selector_all('.parent:has(~ #h)', [b, f]);
+  test_selector_all('.parent:has(:scope ~ #h)', [b, f]);
+  test_selector('.sibling:has(.descendant)', c);
+  test_closest(k, '.ancestor:has(.descendant)', h);
+  test_matches(h, ':has(.target ~ .sibling .descendant)', true);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt
new file mode 100644
index 0000000..0737472
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt
@@ -0,0 +1,33 @@
+This is a testharness.js-based test.
+PASS ":has(a)" should be a valid selector
+PASS ":has(#a)" should be a valid selector
+PASS ":has(.a)" should be a valid selector
+PASS ":has([a])" should be a valid selector
+PASS ":has([a=\"b\"])" should be a valid selector
+PASS ":has([a|=\"b\"])" should be a valid selector
+PASS ":has(:hover)" should be a valid selector
+PASS "*:has(.a)" should be a valid selector
+PASS ".a:has(.b)" should be a valid selector
+PASS ".a:has(:scope .b)" should be a valid selector
+FAIL ".a:has(> .b)" should be a valid selector Failed to execute 'querySelector' on 'Document': '.a:has(> .b)' is not a valid selector.
+PASS ".a:has(:scope > .b)" should be a valid selector
+FAIL ".a:has(~ .b)" should be a valid selector Failed to execute 'querySelector' on 'Document': '.a:has(~ .b)' is not a valid selector.
+PASS ".a:has(:scope ~ .b)" should be a valid selector
+FAIL ".a:has(+ .b)" should be a valid selector Failed to execute 'querySelector' on 'Document': '.a:has(+ .b)' is not a valid selector.
+PASS ".a:has(:scope + .b)" should be a valid selector
+PASS ".a:has(.b) .c" should be a valid selector
+PASS ".a .b:has(.c)" should be a valid selector
+PASS ".a .b:has(.c .d)" should be a valid selector
+PASS ".a .b:has(.c .d) .e" should be a valid selector
+PASS ".a:has(.b:has(.c))" should be a valid selector
+PASS ".a:has(.b:is(.c .d))" should be a valid selector
+PASS ".a:has(.b:is(.c:has(.d) .e))" should be a valid selector
+PASS ".a:is(.b:has(.c) .d)" should be a valid selector
+PASS ".a:not(:has(.b))" should be a valid selector
+PASS ".a:has(:not(.b))" should be a valid selector
+PASS ".a:has(.b):has(.c)" should be a valid selector
+PASS "*|*:has(*)" should be a valid selector
+PASS ":has(*|*)" should be a valid selector
+PASS ".a:has()" should be an invalid selector
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html
new file mode 100644
index 0000000..61382fd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Selectors: The relational pseudo-class</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#has-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+<script>
+  test_valid_selector(':has(a)');
+  test_valid_selector(':has(#a)');
+  test_valid_selector(':has(.a)');
+  test_valid_selector(':has([a])');
+  test_valid_selector(':has([a="b"])');
+  test_valid_selector(':has([a|="b"])');
+  test_valid_selector(':has(:hover)');
+  test_valid_selector('*:has(.a)', ['*:has(.a)', ':has(.a)']);
+  test_valid_selector('.a:has(.b)');
+  test_valid_selector('.a:has(:scope .b)');
+  test_valid_selector('.a:has(> .b)');
+  test_valid_selector('.a:has(:scope > .b)');
+  test_valid_selector('.a:has(~ .b)');
+  test_valid_selector('.a:has(:scope ~ .b)');
+  test_valid_selector('.a:has(+ .b)');
+  test_valid_selector('.a:has(:scope + .b)');
+  test_valid_selector('.a:has(.b) .c');
+  test_valid_selector('.a .b:has(.c)');
+  test_valid_selector('.a .b:has(.c .d)');
+  test_valid_selector('.a .b:has(.c .d) .e');
+  test_valid_selector('.a:has(.b:has(.c))');
+  test_valid_selector('.a:has(.b:is(.c .d))');
+  test_valid_selector('.a:has(.b:is(.c:has(.d) .e))');
+  test_valid_selector('.a:is(.b:has(.c) .d)');
+  test_valid_selector('.a:not(:has(.b))');
+  test_valid_selector('.a:has(:not(.b))');
+  test_valid_selector('.a:has(.b):has(.c)');
+  test_valid_selector('*|*:has(*)', ':has(*)');
+  test_valid_selector(':has(*|*)', ':has(*)');
+  test_invalid_selector('.a:has()');
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter.html b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter.html
index 1afef46..da6859b 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter.html
@@ -32,6 +32,10 @@
 }
 </script>"></iframe>
 <script>
+  // Tests with '\x0A' (i.e., '\n') don't conform to the URL Standard as of the
+  // time of writing, as according to spec they should be ignored.
+  // See https://github.com/whatwg/url/issues/609.
+
   let broken = [
     '\x00',
     '\x01',
@@ -93,7 +97,7 @@
   async_test((t) => {
     self.onload = t.step_func(() => {
       self.onmessage = t.step_func((e) => {
-        assert_array_equals(e.data, ("SyntaxError ".repeat(49) + "SyntaxError").split(" "))
+        assert_array_equals(e.data, broken.map(() => "SyntaxError"))
         c++
         if(c === 2) {
           t.done()
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt
index 82bebb6..2de2e3a 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 260 tests; 80 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 260 tests; 149 PASS, 111 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setting protocol with leading U+0000 (https:)
 PASS Setting protocol with U+0000 before inserted colon (https:)
 PASS Setting username with leading U+0000 (https:)
@@ -34,24 +34,24 @@
 PASS Setting password with leading U+0009 (https:)
 PASS Setting password with middle U+0009 (https:)
 PASS Setting password with trailing U+0009 (https:)
-FAIL Setting host with leading U+0009 (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with leading U+0009 (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with middle U+0009 (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with middle U+0009 (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with trailing U+0009 (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with trailing U+0009 (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting port with leading U+0009 (https:) assert_equals: property expected "9000" but got "8000"
-FAIL Setting port with middle U+0009 (https:) assert_equals: property expected "9000" but got "90"
+PASS Setting host with leading U+0009 (https:)
+PASS Setting hostname with leading U+0009 (https:)
+PASS Setting host with middle U+0009 (https:)
+PASS Setting hostname with middle U+0009 (https:)
+PASS Setting host with trailing U+0009 (https:)
+PASS Setting hostname with trailing U+0009 (https:)
+PASS Setting port with leading U+0009 (https:)
+PASS Setting port with middle U+0009 (https:)
 PASS Setting port with trailing U+0009 (https:)
-FAIL Setting pathname with leading U+0009 (https:) assert_equals: property expected "/test" but got "/%09test"
-FAIL Setting pathname with middle U+0009 (https:) assert_equals: property expected "/test" but got "/te%09st"
-FAIL Setting pathname with trailing U+0009 (https:) assert_equals: property expected "/test" but got "/test%09"
-FAIL Setting search with leading U+0009 (https:) assert_equals: property expected "?test" but got "?%09test"
-FAIL Setting search with middle U+0009 (https:) assert_equals: property expected "?test" but got "?te%09st"
-FAIL Setting search with trailing U+0009 (https:) assert_equals: property expected "?test" but got "?test%09"
-FAIL Setting hash with leading U+0009 (https:) assert_equals: property expected "#test" but got "#%09test"
-FAIL Setting hash with middle U+0009 (https:) assert_equals: property expected "#test" but got "#te%09st"
-FAIL Setting hash with trailing U+0009 (https:) assert_equals: property expected "#test" but got "#test%09"
+PASS Setting pathname with leading U+0009 (https:)
+PASS Setting pathname with middle U+0009 (https:)
+PASS Setting pathname with trailing U+0009 (https:)
+PASS Setting search with leading U+0009 (https:)
+PASS Setting search with middle U+0009 (https:)
+PASS Setting search with trailing U+0009 (https:)
+PASS Setting hash with leading U+0009 (https:)
+PASS Setting hash with middle U+0009 (https:)
+PASS Setting hash with trailing U+0009 (https:)
 FAIL Setting protocol with leading U+000A (https:) assert_equals: property expected "http:" but got "https:"
 FAIL Setting protocol with U+000A before inserted colon (https:) assert_equals: property expected "http:" but got "https:"
 PASS Setting username with leading U+000A (https:)
@@ -60,24 +60,24 @@
 PASS Setting password with leading U+000A (https:)
 PASS Setting password with middle U+000A (https:)
 PASS Setting password with trailing U+000A (https:)
-FAIL Setting host with leading U+000A (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with leading U+000A (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with middle U+000A (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with middle U+000A (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with trailing U+000A (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with trailing U+000A (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting port with leading U+000A (https:) assert_equals: property expected "9000" but got "8000"
-FAIL Setting port with middle U+000A (https:) assert_equals: property expected "9000" but got "90"
+PASS Setting host with leading U+000A (https:)
+PASS Setting hostname with leading U+000A (https:)
+PASS Setting host with middle U+000A (https:)
+PASS Setting hostname with middle U+000A (https:)
+PASS Setting host with trailing U+000A (https:)
+PASS Setting hostname with trailing U+000A (https:)
+PASS Setting port with leading U+000A (https:)
+PASS Setting port with middle U+000A (https:)
 PASS Setting port with trailing U+000A (https:)
-FAIL Setting pathname with leading U+000A (https:) assert_equals: property expected "/test" but got "/%0Atest"
-FAIL Setting pathname with middle U+000A (https:) assert_equals: property expected "/test" but got "/te%0Ast"
-FAIL Setting pathname with trailing U+000A (https:) assert_equals: property expected "/test" but got "/test%0A"
-FAIL Setting search with leading U+000A (https:) assert_equals: property expected "?test" but got "?%0Atest"
-FAIL Setting search with middle U+000A (https:) assert_equals: property expected "?test" but got "?te%0Ast"
-FAIL Setting search with trailing U+000A (https:) assert_equals: property expected "?test" but got "?test%0A"
-FAIL Setting hash with leading U+000A (https:) assert_equals: property expected "#test" but got "#%0Atest"
-FAIL Setting hash with middle U+000A (https:) assert_equals: property expected "#test" but got "#te%0Ast"
-FAIL Setting hash with trailing U+000A (https:) assert_equals: property expected "#test" but got "#test%0A"
+PASS Setting pathname with leading U+000A (https:)
+PASS Setting pathname with middle U+000A (https:)
+PASS Setting pathname with trailing U+000A (https:)
+PASS Setting search with leading U+000A (https:)
+PASS Setting search with middle U+000A (https:)
+PASS Setting search with trailing U+000A (https:)
+PASS Setting hash with leading U+000A (https:)
+PASS Setting hash with middle U+000A (https:)
+PASS Setting hash with trailing U+000A (https:)
 FAIL Setting protocol with leading U+000D (https:) assert_equals: property expected "http:" but got "https:"
 FAIL Setting protocol with U+000D before inserted colon (https:) assert_equals: property expected "http:" but got "https:"
 PASS Setting username with leading U+000D (https:)
@@ -86,24 +86,24 @@
 PASS Setting password with leading U+000D (https:)
 PASS Setting password with middle U+000D (https:)
 PASS Setting password with trailing U+000D (https:)
-FAIL Setting host with leading U+000D (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with leading U+000D (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with middle U+000D (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with middle U+000D (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with trailing U+000D (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with trailing U+000D (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting port with leading U+000D (https:) assert_equals: property expected "9000" but got "8000"
-FAIL Setting port with middle U+000D (https:) assert_equals: property expected "9000" but got "90"
+PASS Setting host with leading U+000D (https:)
+PASS Setting hostname with leading U+000D (https:)
+PASS Setting host with middle U+000D (https:)
+PASS Setting hostname with middle U+000D (https:)
+PASS Setting host with trailing U+000D (https:)
+PASS Setting hostname with trailing U+000D (https:)
+PASS Setting port with leading U+000D (https:)
+PASS Setting port with middle U+000D (https:)
 PASS Setting port with trailing U+000D (https:)
-FAIL Setting pathname with leading U+000D (https:) assert_equals: property expected "/test" but got "/%0Dtest"
-FAIL Setting pathname with middle U+000D (https:) assert_equals: property expected "/test" but got "/te%0Dst"
-FAIL Setting pathname with trailing U+000D (https:) assert_equals: property expected "/test" but got "/test%0D"
-FAIL Setting search with leading U+000D (https:) assert_equals: property expected "?test" but got "?%0Dtest"
-FAIL Setting search with middle U+000D (https:) assert_equals: property expected "?test" but got "?te%0Dst"
-FAIL Setting search with trailing U+000D (https:) assert_equals: property expected "?test" but got "?test%0D"
-FAIL Setting hash with leading U+000D (https:) assert_equals: property expected "#test" but got "#%0Dtest"
-FAIL Setting hash with middle U+000D (https:) assert_equals: property expected "#test" but got "#te%0Dst"
-FAIL Setting hash with trailing U+000D (https:) assert_equals: property expected "#test" but got "#test%0D"
+PASS Setting pathname with leading U+000D (https:)
+PASS Setting pathname with middle U+000D (https:)
+PASS Setting pathname with trailing U+000D (https:)
+PASS Setting search with leading U+000D (https:)
+PASS Setting search with middle U+000D (https:)
+PASS Setting search with trailing U+000D (https:)
+PASS Setting hash with leading U+000D (https:)
+PASS Setting hash with middle U+000D (https:)
+PASS Setting hash with trailing U+000D (https:)
 PASS Setting protocol with leading U+001F (https:)
 PASS Setting protocol with U+001F before inserted colon (https:)
 PASS Setting username with leading U+001F (https:)
@@ -176,12 +176,12 @@
 FAIL Setting pathname with leading U+0009 (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with middle U+0009 (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with trailing U+0009 (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
-FAIL Setting search with leading U+0009 (wpt++:) assert_equals: property expected "?test" but got "?%09test"
-FAIL Setting search with middle U+0009 (wpt++:) assert_equals: property expected "?test" but got "?te%09st"
-FAIL Setting search with trailing U+0009 (wpt++:) assert_equals: property expected "?test" but got "?test%09"
-FAIL Setting hash with leading U+0009 (wpt++:) assert_equals: property expected "#test" but got "#%09test"
-FAIL Setting hash with middle U+0009 (wpt++:) assert_equals: property expected "#test" but got "#te%09st"
-FAIL Setting hash with trailing U+0009 (wpt++:) assert_equals: property expected "#test" but got "#test%09"
+PASS Setting search with leading U+0009 (wpt++:)
+PASS Setting search with middle U+0009 (wpt++:)
+PASS Setting search with trailing U+0009 (wpt++:)
+PASS Setting hash with leading U+0009 (wpt++:)
+PASS Setting hash with middle U+0009 (wpt++:)
+PASS Setting hash with trailing U+0009 (wpt++:)
 FAIL Setting protocol with leading U+000A (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting protocol with U+000A before inserted colon (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting username with leading U+000A (wpt++:) assert_equals: property expected "%0Atest" but got ""
@@ -202,12 +202,12 @@
 FAIL Setting pathname with leading U+000A (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with middle U+000A (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with trailing U+000A (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
-FAIL Setting search with leading U+000A (wpt++:) assert_equals: property expected "?test" but got "?%0Atest"
-FAIL Setting search with middle U+000A (wpt++:) assert_equals: property expected "?test" but got "?te%0Ast"
-FAIL Setting search with trailing U+000A (wpt++:) assert_equals: property expected "?test" but got "?test%0A"
-FAIL Setting hash with leading U+000A (wpt++:) assert_equals: property expected "#test" but got "#%0Atest"
-FAIL Setting hash with middle U+000A (wpt++:) assert_equals: property expected "#test" but got "#te%0Ast"
-FAIL Setting hash with trailing U+000A (wpt++:) assert_equals: property expected "#test" but got "#test%0A"
+PASS Setting search with leading U+000A (wpt++:)
+PASS Setting search with middle U+000A (wpt++:)
+PASS Setting search with trailing U+000A (wpt++:)
+PASS Setting hash with leading U+000A (wpt++:)
+PASS Setting hash with middle U+000A (wpt++:)
+PASS Setting hash with trailing U+000A (wpt++:)
 FAIL Setting protocol with leading U+000D (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting protocol with U+000D before inserted colon (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting username with leading U+000D (wpt++:) assert_equals: property expected "%0Dtest" but got ""
@@ -228,12 +228,12 @@
 FAIL Setting pathname with leading U+000D (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with middle U+000D (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with trailing U+000D (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
-FAIL Setting search with leading U+000D (wpt++:) assert_equals: property expected "?test" but got "?%0Dtest"
-FAIL Setting search with middle U+000D (wpt++:) assert_equals: property expected "?test" but got "?te%0Dst"
-FAIL Setting search with trailing U+000D (wpt++:) assert_equals: property expected "?test" but got "?test%0D"
-FAIL Setting hash with leading U+000D (wpt++:) assert_equals: property expected "#test" but got "#%0Dtest"
-FAIL Setting hash with middle U+000D (wpt++:) assert_equals: property expected "#test" but got "#te%0Dst"
-FAIL Setting hash with trailing U+000D (wpt++:) assert_equals: property expected "#test" but got "#test%0D"
+PASS Setting search with leading U+000D (wpt++:)
+PASS Setting search with middle U+000D (wpt++:)
+PASS Setting search with trailing U+000D (wpt++:)
+PASS Setting hash with leading U+000D (wpt++:)
+PASS Setting hash with middle U+000D (wpt++:)
+PASS Setting hash with trailing U+000D (wpt++:)
 PASS Setting protocol with leading U+001F (wpt++:)
 PASS Setting protocol with U+001F before inserted colon (wpt++:)
 FAIL Setting username with leading U+001F (wpt++:) assert_equals: property expected "%1Ftest" but got ""
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt
index 82bebb6..2de2e3a 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 260 tests; 80 PASS, 180 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 260 tests; 149 PASS, 111 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setting protocol with leading U+0000 (https:)
 PASS Setting protocol with U+0000 before inserted colon (https:)
 PASS Setting username with leading U+0000 (https:)
@@ -34,24 +34,24 @@
 PASS Setting password with leading U+0009 (https:)
 PASS Setting password with middle U+0009 (https:)
 PASS Setting password with trailing U+0009 (https:)
-FAIL Setting host with leading U+0009 (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with leading U+0009 (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with middle U+0009 (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with middle U+0009 (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with trailing U+0009 (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with trailing U+0009 (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting port with leading U+0009 (https:) assert_equals: property expected "9000" but got "8000"
-FAIL Setting port with middle U+0009 (https:) assert_equals: property expected "9000" but got "90"
+PASS Setting host with leading U+0009 (https:)
+PASS Setting hostname with leading U+0009 (https:)
+PASS Setting host with middle U+0009 (https:)
+PASS Setting hostname with middle U+0009 (https:)
+PASS Setting host with trailing U+0009 (https:)
+PASS Setting hostname with trailing U+0009 (https:)
+PASS Setting port with leading U+0009 (https:)
+PASS Setting port with middle U+0009 (https:)
 PASS Setting port with trailing U+0009 (https:)
-FAIL Setting pathname with leading U+0009 (https:) assert_equals: property expected "/test" but got "/%09test"
-FAIL Setting pathname with middle U+0009 (https:) assert_equals: property expected "/test" but got "/te%09st"
-FAIL Setting pathname with trailing U+0009 (https:) assert_equals: property expected "/test" but got "/test%09"
-FAIL Setting search with leading U+0009 (https:) assert_equals: property expected "?test" but got "?%09test"
-FAIL Setting search with middle U+0009 (https:) assert_equals: property expected "?test" but got "?te%09st"
-FAIL Setting search with trailing U+0009 (https:) assert_equals: property expected "?test" but got "?test%09"
-FAIL Setting hash with leading U+0009 (https:) assert_equals: property expected "#test" but got "#%09test"
-FAIL Setting hash with middle U+0009 (https:) assert_equals: property expected "#test" but got "#te%09st"
-FAIL Setting hash with trailing U+0009 (https:) assert_equals: property expected "#test" but got "#test%09"
+PASS Setting pathname with leading U+0009 (https:)
+PASS Setting pathname with middle U+0009 (https:)
+PASS Setting pathname with trailing U+0009 (https:)
+PASS Setting search with leading U+0009 (https:)
+PASS Setting search with middle U+0009 (https:)
+PASS Setting search with trailing U+0009 (https:)
+PASS Setting hash with leading U+0009 (https:)
+PASS Setting hash with middle U+0009 (https:)
+PASS Setting hash with trailing U+0009 (https:)
 FAIL Setting protocol with leading U+000A (https:) assert_equals: property expected "http:" but got "https:"
 FAIL Setting protocol with U+000A before inserted colon (https:) assert_equals: property expected "http:" but got "https:"
 PASS Setting username with leading U+000A (https:)
@@ -60,24 +60,24 @@
 PASS Setting password with leading U+000A (https:)
 PASS Setting password with middle U+000A (https:)
 PASS Setting password with trailing U+000A (https:)
-FAIL Setting host with leading U+000A (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with leading U+000A (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with middle U+000A (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with middle U+000A (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with trailing U+000A (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with trailing U+000A (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting port with leading U+000A (https:) assert_equals: property expected "9000" but got "8000"
-FAIL Setting port with middle U+000A (https:) assert_equals: property expected "9000" but got "90"
+PASS Setting host with leading U+000A (https:)
+PASS Setting hostname with leading U+000A (https:)
+PASS Setting host with middle U+000A (https:)
+PASS Setting hostname with middle U+000A (https:)
+PASS Setting host with trailing U+000A (https:)
+PASS Setting hostname with trailing U+000A (https:)
+PASS Setting port with leading U+000A (https:)
+PASS Setting port with middle U+000A (https:)
 PASS Setting port with trailing U+000A (https:)
-FAIL Setting pathname with leading U+000A (https:) assert_equals: property expected "/test" but got "/%0Atest"
-FAIL Setting pathname with middle U+000A (https:) assert_equals: property expected "/test" but got "/te%0Ast"
-FAIL Setting pathname with trailing U+000A (https:) assert_equals: property expected "/test" but got "/test%0A"
-FAIL Setting search with leading U+000A (https:) assert_equals: property expected "?test" but got "?%0Atest"
-FAIL Setting search with middle U+000A (https:) assert_equals: property expected "?test" but got "?te%0Ast"
-FAIL Setting search with trailing U+000A (https:) assert_equals: property expected "?test" but got "?test%0A"
-FAIL Setting hash with leading U+000A (https:) assert_equals: property expected "#test" but got "#%0Atest"
-FAIL Setting hash with middle U+000A (https:) assert_equals: property expected "#test" but got "#te%0Ast"
-FAIL Setting hash with trailing U+000A (https:) assert_equals: property expected "#test" but got "#test%0A"
+PASS Setting pathname with leading U+000A (https:)
+PASS Setting pathname with middle U+000A (https:)
+PASS Setting pathname with trailing U+000A (https:)
+PASS Setting search with leading U+000A (https:)
+PASS Setting search with middle U+000A (https:)
+PASS Setting search with trailing U+000A (https:)
+PASS Setting hash with leading U+000A (https:)
+PASS Setting hash with middle U+000A (https:)
+PASS Setting hash with trailing U+000A (https:)
 FAIL Setting protocol with leading U+000D (https:) assert_equals: property expected "http:" but got "https:"
 FAIL Setting protocol with U+000D before inserted colon (https:) assert_equals: property expected "http:" but got "https:"
 PASS Setting username with leading U+000D (https:)
@@ -86,24 +86,24 @@
 PASS Setting password with leading U+000D (https:)
 PASS Setting password with middle U+000D (https:)
 PASS Setting password with trailing U+000D (https:)
-FAIL Setting host with leading U+000D (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with leading U+000D (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with middle U+000D (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with middle U+000D (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting host with trailing U+000D (https:) assert_equals: property expected "test:8000" but got "host:8000"
-FAIL Setting hostname with trailing U+000D (https:) assert_equals: property expected "test" but got "host"
-FAIL Setting port with leading U+000D (https:) assert_equals: property expected "9000" but got "8000"
-FAIL Setting port with middle U+000D (https:) assert_equals: property expected "9000" but got "90"
+PASS Setting host with leading U+000D (https:)
+PASS Setting hostname with leading U+000D (https:)
+PASS Setting host with middle U+000D (https:)
+PASS Setting hostname with middle U+000D (https:)
+PASS Setting host with trailing U+000D (https:)
+PASS Setting hostname with trailing U+000D (https:)
+PASS Setting port with leading U+000D (https:)
+PASS Setting port with middle U+000D (https:)
 PASS Setting port with trailing U+000D (https:)
-FAIL Setting pathname with leading U+000D (https:) assert_equals: property expected "/test" but got "/%0Dtest"
-FAIL Setting pathname with middle U+000D (https:) assert_equals: property expected "/test" but got "/te%0Dst"
-FAIL Setting pathname with trailing U+000D (https:) assert_equals: property expected "/test" but got "/test%0D"
-FAIL Setting search with leading U+000D (https:) assert_equals: property expected "?test" but got "?%0Dtest"
-FAIL Setting search with middle U+000D (https:) assert_equals: property expected "?test" but got "?te%0Dst"
-FAIL Setting search with trailing U+000D (https:) assert_equals: property expected "?test" but got "?test%0D"
-FAIL Setting hash with leading U+000D (https:) assert_equals: property expected "#test" but got "#%0Dtest"
-FAIL Setting hash with middle U+000D (https:) assert_equals: property expected "#test" but got "#te%0Dst"
-FAIL Setting hash with trailing U+000D (https:) assert_equals: property expected "#test" but got "#test%0D"
+PASS Setting pathname with leading U+000D (https:)
+PASS Setting pathname with middle U+000D (https:)
+PASS Setting pathname with trailing U+000D (https:)
+PASS Setting search with leading U+000D (https:)
+PASS Setting search with middle U+000D (https:)
+PASS Setting search with trailing U+000D (https:)
+PASS Setting hash with leading U+000D (https:)
+PASS Setting hash with middle U+000D (https:)
+PASS Setting hash with trailing U+000D (https:)
 PASS Setting protocol with leading U+001F (https:)
 PASS Setting protocol with U+001F before inserted colon (https:)
 PASS Setting username with leading U+001F (https:)
@@ -176,12 +176,12 @@
 FAIL Setting pathname with leading U+0009 (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with middle U+0009 (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with trailing U+0009 (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
-FAIL Setting search with leading U+0009 (wpt++:) assert_equals: property expected "?test" but got "?%09test"
-FAIL Setting search with middle U+0009 (wpt++:) assert_equals: property expected "?test" but got "?te%09st"
-FAIL Setting search with trailing U+0009 (wpt++:) assert_equals: property expected "?test" but got "?test%09"
-FAIL Setting hash with leading U+0009 (wpt++:) assert_equals: property expected "#test" but got "#%09test"
-FAIL Setting hash with middle U+0009 (wpt++:) assert_equals: property expected "#test" but got "#te%09st"
-FAIL Setting hash with trailing U+0009 (wpt++:) assert_equals: property expected "#test" but got "#test%09"
+PASS Setting search with leading U+0009 (wpt++:)
+PASS Setting search with middle U+0009 (wpt++:)
+PASS Setting search with trailing U+0009 (wpt++:)
+PASS Setting hash with leading U+0009 (wpt++:)
+PASS Setting hash with middle U+0009 (wpt++:)
+PASS Setting hash with trailing U+0009 (wpt++:)
 FAIL Setting protocol with leading U+000A (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting protocol with U+000A before inserted colon (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting username with leading U+000A (wpt++:) assert_equals: property expected "%0Atest" but got ""
@@ -202,12 +202,12 @@
 FAIL Setting pathname with leading U+000A (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with middle U+000A (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with trailing U+000A (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
-FAIL Setting search with leading U+000A (wpt++:) assert_equals: property expected "?test" but got "?%0Atest"
-FAIL Setting search with middle U+000A (wpt++:) assert_equals: property expected "?test" but got "?te%0Ast"
-FAIL Setting search with trailing U+000A (wpt++:) assert_equals: property expected "?test" but got "?test%0A"
-FAIL Setting hash with leading U+000A (wpt++:) assert_equals: property expected "#test" but got "#%0Atest"
-FAIL Setting hash with middle U+000A (wpt++:) assert_equals: property expected "#test" but got "#te%0Ast"
-FAIL Setting hash with trailing U+000A (wpt++:) assert_equals: property expected "#test" but got "#test%0A"
+PASS Setting search with leading U+000A (wpt++:)
+PASS Setting search with middle U+000A (wpt++:)
+PASS Setting search with trailing U+000A (wpt++:)
+PASS Setting hash with leading U+000A (wpt++:)
+PASS Setting hash with middle U+000A (wpt++:)
+PASS Setting hash with trailing U+000A (wpt++:)
 FAIL Setting protocol with leading U+000D (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting protocol with U+000D before inserted colon (wpt++:) assert_equals: property expected "wpt--:" but got "wpt++:"
 FAIL Setting username with leading U+000D (wpt++:) assert_equals: property expected "%0Dtest" but got ""
@@ -228,12 +228,12 @@
 FAIL Setting pathname with leading U+000D (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with middle U+000D (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
 FAIL Setting pathname with trailing U+000D (wpt++:) assert_equals: property expected "/test" but got "//username:password@host:8000/path"
-FAIL Setting search with leading U+000D (wpt++:) assert_equals: property expected "?test" but got "?%0Dtest"
-FAIL Setting search with middle U+000D (wpt++:) assert_equals: property expected "?test" but got "?te%0Dst"
-FAIL Setting search with trailing U+000D (wpt++:) assert_equals: property expected "?test" but got "?test%0D"
-FAIL Setting hash with leading U+000D (wpt++:) assert_equals: property expected "#test" but got "#%0Dtest"
-FAIL Setting hash with middle U+000D (wpt++:) assert_equals: property expected "#test" but got "#te%0Dst"
-FAIL Setting hash with trailing U+000D (wpt++:) assert_equals: property expected "#test" but got "#test%0D"
+PASS Setting search with leading U+000D (wpt++:)
+PASS Setting search with middle U+000D (wpt++:)
+PASS Setting search with trailing U+000D (wpt++:)
+PASS Setting hash with leading U+000D (wpt++:)
+PASS Setting hash with middle U+000D (wpt++:)
+PASS Setting hash with trailing U+000D (wpt++:)
 PASS Setting protocol with leading U+001F (wpt++:)
 PASS Setting protocol with U+001F before inserted colon (wpt++:)
 FAIL Setting username with leading U+001F (wpt++:) assert_equals: property expected "%1Ftest" but got ""
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats-expected.txt
index 84cb4f1..75425233 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 310 tests; 195 PASS, 115 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 310 tests; 196 PASS, 114 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS getStats succeeds
 PASS Validating stats
 PASS codec's payloadType
@@ -111,7 +111,7 @@
 PASS outbound-rtp's totalPacketSendDelay
 FAIL outbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
 PASS outbound-rtp's qualityLimitationReason
-FAIL outbound-rtp's qualityLimitationDurations assert_true: Is qualityLimitationDurations present expected true got false
+PASS outbound-rtp's qualityLimitationDurations
 PASS outbound-rtp's qualityLimitationResolutionChanges
 FAIL outbound-rtp's perDscpPacketsSent assert_true: Is perDscpPacketsSent present expected true got false
 PASS outbound-rtp's nackCount
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-expected.txt
index 70b716a..f47b750 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-expected.txt
@@ -13,6 +13,13 @@
       "backgroundColor": "#C0C0C0"
     },
     {
+      "name": "LayoutNGBlockFlow HTML",
+      "position": [8, 13],
+      "bounds": [769, 1000],
+      "contentsOpaqueForText": true,
+      "drawsContent": false
+    },
+    {
       "name": "VerticalScrollbar",
       "position": [785, 0],
       "bounds": [15, 600]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter-expected.txt
index 4973188c..f50960f 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter-expected.txt
@@ -12,6 +12,13 @@
       "contentsOpaqueForText": true
     },
     {
+      "name": "LayoutNGBlockFlow HTML",
+      "position": [8, 13],
+      "bounds": [769, 1000],
+      "contentsOpaqueForText": true,
+      "drawsContent": false
+    },
+    {
       "name": "VerticalScrollbar",
       "position": [785, 0],
       "bounds": [15, 600]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt
new file mode 100644
index 0000000..42058e0a
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt
@@ -0,0 +1,88 @@
+Before:
+{
+  "layers": [
+    {
+      "name": "Scrolling background of LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed'",
+      "bounds": [30, 30],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
+After scroll:
+{
+  "layers": [
+    {
+      "name": "Scrolling background of LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed'",
+      "bounds": [30, 30],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='overlapped'",
+      "position": [8, 102],
+      "bounds": [40, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFA500",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-nested-fixed-position-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-nested-fixed-position-expected.txt
new file mode 100644
index 0000000..d576bc4
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-nested-fixed-position-expected.txt
@@ -0,0 +1,54 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling background of LayoutView #document",
+      "bounds": [785, 1061],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed parent'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFF00"
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='fixed nested'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFF00",
+      "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='overlapped with-parent'",
+      "position": [8, 208],
+      "bounds": [20, 20],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='overlapped with-nested'",
+      "position": [258, 228],
+      "bounds": [20, 20],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "VerticalScrollbar",
+      "position": [785, 0],
+      "bounds": [15, 600]
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [200, 0, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
index d7ad3894..f451e77 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -262,7 +262,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute' class='positionAbsolute positioned'",
       "position": [6, 6],
-      "bounds": [101, 136],
+      "bounds": [101, 108],
       "contentsOpaqueForText": true,
       "transform": 16
     },
@@ -395,7 +395,7 @@
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled'",
       "position": [6, 6],
-      "bounds": [75, 136],
+      "bounds": [75, 108],
       "contentsOpaqueForText": true,
       "transform": 28
     },
@@ -493,6 +493,13 @@
       "transform": 14
     },
     {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute' class='scrolled onTop'",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "contentsOpaqueForText": true,
+      "transform": 16
+    },
+    {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
@@ -508,13 +515,19 @@
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled onTop'",
-      "position": [6, 118],
-      "bounds": [75, 24],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "contentsOpaqueForText": true,
       "transform": 24
     },
     {
+      "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled onTop'",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "contentsOpaqueForText": true,
+      "transform": 28
+    },
+    {
       "name": "VerticalScrollbar",
       "position": [785, 0],
       "bounds": [15, 600]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/html/details_summary/details-position-expected.png b/third_party/blink/web_tests/flag-specific/composite-after-paint/html/details_summary/details-position-expected.png
index b8394b23a..480abbf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/html/details_summary/details-position-expected.png
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/html/details_summary/details-position-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/absolute-position-changed-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/absolute-position-changed-expected.txt
index 3b8dc08..823a6bd 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/absolute-position-changed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/absolute-position-changed-expected.txt
@@ -5,9 +5,6 @@
       "bounds": [800, 2016],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
-      "invalidations": [
-        [100, 500, 100, 100]
-      ],
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/fixed-after-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/fixed-after-scroll-expected.txt
index 5955a2e..9d38ff44 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/fixed-after-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/fixed-after-scroll-expected.txt
@@ -5,9 +5,6 @@
       "bounds": [785, 2016],
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
-      "invalidations": [
-        [8, 200, 100, 100]
-      ],
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt
new file mode 100644
index 0000000..7a58d91
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-hidden-scroll-with-fixed-overlap-expected.txt
@@ -0,0 +1,106 @@
+Before:
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutView #document",
+      "bounds": [300, 150],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "bounds": [30, 30],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='overlapped'",
+      "position": [8, 1008],
+      "bounds": [40, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFA500",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
+After scroll:
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutView #document",
+      "bounds": [300, 150],
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='fixed'",
+      "bounds": [30, 30],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='overlapped'",
+      "position": [8, 102],
+      "bounds": [40, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFA500",
+      "transform": 1
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [8, 100, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-nested-fixed-position-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-nested-fixed-position-expected.txt
new file mode 100644
index 0000000..48ff1317
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-nested-fixed-position-expected.txt
@@ -0,0 +1,54 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 1061],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='fixed parent'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFF00"
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='fixed nested'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFF00",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV class='overlapped with-parent'",
+      "position": [8, 208],
+      "bounds": [20, 20],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='overlapped with-nested')",
+      "position": [258, 228],
+      "bounds": [20, 20],
+      "backgroundColor": "#0000FF"
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [785, 0],
+      "bounds": [15, 600],
+      "contentsOpaque": true
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [200, 0, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/webrtc-stats/supported-stats-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/webrtc-stats/supported-stats-expected.txt
deleted file mode 100644
index 007d350..0000000
--- a/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/webrtc-stats/supported-stats-expected.txt
+++ /dev/null
@@ -1,311 +0,0 @@
-This is a testharness.js-based test.
-Found 307 tests; 195 PASS, 112 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS getStats succeeds
-PASS Validating stats
-PASS codec's payloadType
-FAIL codec's codecType assert_true: Is codecType present expected true got false
-PASS codec's transportId
-PASS codec's mimeType
-PASS codec's clockRate
-PASS codec's channels
-PASS codec's sdpFmtpLine
-PASS codec's timestamp
-PASS codec's type
-PASS codec's id
-FAIL inbound-rtp's receiverId assert_true: Is receiverId present expected true got false
-PASS inbound-rtp's remoteId
-PASS inbound-rtp's framesDecoded
-PASS inbound-rtp's keyFramesDecoded
-PASS inbound-rtp's frameWidth
-PASS inbound-rtp's frameHeight
-FAIL inbound-rtp's frameBitDepth assert_true: Is frameBitDepth present expected true got false
-PASS inbound-rtp's framesPerSecond
-PASS inbound-rtp's qpSum
-PASS inbound-rtp's totalDecodeTime
-PASS inbound-rtp's totalInterFrameDelay
-PASS inbound-rtp's totalSquaredInterFrameDelay
-FAIL inbound-rtp's voiceActivityFlag assert_true: Is voiceActivityFlag present expected true got false
-PASS inbound-rtp's lastPacketReceivedTimestamp
-FAIL inbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
-PASS inbound-rtp's headerBytesReceived
-PASS inbound-rtp's fecPacketsReceived
-PASS inbound-rtp's fecPacketsDiscarded
-PASS inbound-rtp's bytesReceived
-FAIL inbound-rtp's packetsFailedDecryption assert_true: Is packetsFailedDecryption present expected true got false
-FAIL inbound-rtp's packetsDuplicated assert_true: Is packetsDuplicated present expected true got false
-FAIL inbound-rtp's perDscpPacketsReceived assert_true: Is perDscpPacketsReceived present expected true got false
-PASS inbound-rtp's nackCount
-PASS inbound-rtp's firCount
-PASS inbound-rtp's pliCount
-FAIL inbound-rtp's sliCount assert_true: Is sliCount present expected true got false
-FAIL inbound-rtp's totalProcessingDelay assert_true: Is totalProcessingDelay present expected true got false
-FAIL inbound-rtp's estimatedPlayoutTimestamp assert_true: Is estimatedPlayoutTimestamp present expected true got false
-PASS inbound-rtp's jitterBufferDelay
-PASS inbound-rtp's jitterBufferEmittedCount
-PASS inbound-rtp's totalSamplesReceived
-FAIL inbound-rtp's totalSamplesDecoded assert_true: Is totalSamplesDecoded present expected true got false
-FAIL inbound-rtp's samplesDecodedWithSilk assert_true: Is samplesDecodedWithSilk present expected true got false
-FAIL inbound-rtp's samplesDecodedWithCelt assert_true: Is samplesDecodedWithCelt present expected true got false
-PASS inbound-rtp's concealedSamples
-PASS inbound-rtp's silentConcealedSamples
-PASS inbound-rtp's concealmentEvents
-PASS inbound-rtp's insertedSamplesForDeceleration
-PASS inbound-rtp's removedSamplesForAcceleration
-PASS inbound-rtp's audioLevel
-PASS inbound-rtp's totalAudioEnergy
-PASS inbound-rtp's totalSamplesDuration
-PASS inbound-rtp's framesReceived
-PASS inbound-rtp's decoderImplementation
-PASS inbound-rtp's packetsReceived
-PASS inbound-rtp's packetsLost
-PASS inbound-rtp's jitter
-FAIL inbound-rtp's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
-FAIL inbound-rtp's packetsRepaired assert_true: Is packetsRepaired present expected true got false
-FAIL inbound-rtp's burstPacketsLost assert_true: Is burstPacketsLost present expected true got false
-FAIL inbound-rtp's burstPacketsDiscarded assert_true: Is burstPacketsDiscarded present expected true got false
-FAIL inbound-rtp's burstLossCount assert_true: Is burstLossCount present expected true got false
-FAIL inbound-rtp's burstDiscardCount assert_true: Is burstDiscardCount present expected true got false
-FAIL inbound-rtp's burstLossRate assert_true: Is burstLossRate present expected true got false
-FAIL inbound-rtp's burstDiscardRate assert_true: Is burstDiscardRate present expected true got false
-FAIL inbound-rtp's gapLossRate assert_true: Is gapLossRate present expected true got false
-FAIL inbound-rtp's gapDiscardRate assert_true: Is gapDiscardRate present expected true got false
-PASS inbound-rtp's framesDropped
-FAIL inbound-rtp's partialFramesLost assert_true: Is partialFramesLost present expected true got false
-FAIL inbound-rtp's fullFramesLost assert_true: Is fullFramesLost present expected true got false
-PASS inbound-rtp's ssrc
-PASS inbound-rtp's kind
-PASS inbound-rtp's transportId
-PASS inbound-rtp's codecId
-PASS inbound-rtp's timestamp
-PASS inbound-rtp's type
-PASS inbound-rtp's id
-FAIL outbound-rtp's rtxSsrc assert_true: Is rtxSsrc present expected true got false
-PASS outbound-rtp's mediaSourceId
-FAIL outbound-rtp's senderId assert_true: Is senderId present expected true got false
-PASS outbound-rtp's remoteId
-FAIL outbound-rtp's rid assert_true: Is rid present expected true got false
-FAIL outbound-rtp's lastPacketSentTimestamp assert_true: Is lastPacketSentTimestamp present expected true got false
-PASS outbound-rtp's headerBytesSent
-FAIL outbound-rtp's packetsDiscardedOnSend assert_true: Is packetsDiscardedOnSend present expected true got false
-FAIL outbound-rtp's bytesDiscardedOnSend assert_true: Is bytesDiscardedOnSend present expected true got false
-FAIL outbound-rtp's fecPacketsSent assert_true: Is fecPacketsSent present expected true got false
-PASS outbound-rtp's retransmittedPacketsSent
-PASS outbound-rtp's retransmittedBytesSent
-FAIL outbound-rtp's targetBitrate assert_true: Is targetBitrate present expected true got false
-PASS outbound-rtp's totalEncodedBytesTarget
-PASS outbound-rtp's frameWidth
-PASS outbound-rtp's frameHeight
-FAIL outbound-rtp's frameBitDepth assert_true: Is frameBitDepth present expected true got false
-PASS outbound-rtp's framesPerSecond
-PASS outbound-rtp's framesSent
-PASS outbound-rtp's hugeFramesSent
-PASS outbound-rtp's framesEncoded
-PASS outbound-rtp's keyFramesEncoded
-FAIL outbound-rtp's framesDiscardedOnSend assert_true: Is framesDiscardedOnSend present expected true got false
-PASS outbound-rtp's qpSum
-FAIL outbound-rtp's totalSamplesSent assert_true: Is totalSamplesSent present expected true got false
-FAIL outbound-rtp's samplesEncodedWithSilk assert_true: Is samplesEncodedWithSilk present expected true got false
-FAIL outbound-rtp's samplesEncodedWithCelt assert_true: Is samplesEncodedWithCelt present expected true got false
-FAIL outbound-rtp's voiceActivityFlag assert_true: Is voiceActivityFlag present expected true got false
-PASS outbound-rtp's totalEncodeTime
-PASS outbound-rtp's totalPacketSendDelay
-FAIL outbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
-PASS outbound-rtp's qualityLimitationReason
-FAIL outbound-rtp's qualityLimitationDurations assert_true: Is qualityLimitationDurations present expected true got false
-PASS outbound-rtp's qualityLimitationResolutionChanges
-FAIL outbound-rtp's perDscpPacketsSent assert_true: Is perDscpPacketsSent present expected true got false
-PASS outbound-rtp's nackCount
-PASS outbound-rtp's firCount
-PASS outbound-rtp's pliCount
-FAIL outbound-rtp's sliCount assert_true: Is sliCount present expected true got false
-PASS outbound-rtp's encoderImplementation
-PASS outbound-rtp's packetsSent
-PASS outbound-rtp's bytesSent
-PASS outbound-rtp's ssrc
-PASS outbound-rtp's kind
-PASS outbound-rtp's transportId
-PASS outbound-rtp's codecId
-PASS outbound-rtp's timestamp
-PASS outbound-rtp's type
-PASS outbound-rtp's id
-PASS remote-inbound-rtp's localId
-PASS remote-inbound-rtp's roundTripTime
-PASS remote-inbound-rtp's totalRoundTripTime
-PASS remote-inbound-rtp's fractionLost
-FAIL remote-inbound-rtp's reportsReceived assert_true: Is reportsReceived present expected true got false
-PASS remote-inbound-rtp's roundTripTimeMeasurements
-FAIL remote-inbound-rtp's packetsReceived assert_true: Is packetsReceived present expected true got false
-PASS remote-inbound-rtp's packetsLost
-PASS remote-inbound-rtp's jitter
-FAIL remote-inbound-rtp's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
-FAIL remote-inbound-rtp's packetsRepaired assert_true: Is packetsRepaired present expected true got false
-FAIL remote-inbound-rtp's burstPacketsLost assert_true: Is burstPacketsLost present expected true got false
-FAIL remote-inbound-rtp's burstPacketsDiscarded assert_true: Is burstPacketsDiscarded present expected true got false
-FAIL remote-inbound-rtp's burstLossCount assert_true: Is burstLossCount present expected true got false
-FAIL remote-inbound-rtp's burstDiscardCount assert_true: Is burstDiscardCount present expected true got false
-FAIL remote-inbound-rtp's burstLossRate assert_true: Is burstLossRate present expected true got false
-FAIL remote-inbound-rtp's burstDiscardRate assert_true: Is burstDiscardRate present expected true got false
-FAIL remote-inbound-rtp's gapLossRate assert_true: Is gapLossRate present expected true got false
-FAIL remote-inbound-rtp's gapDiscardRate assert_true: Is gapDiscardRate present expected true got false
-FAIL remote-inbound-rtp's framesDropped assert_true: Is framesDropped present expected true got false
-FAIL remote-inbound-rtp's partialFramesLost assert_true: Is partialFramesLost present expected true got false
-FAIL remote-inbound-rtp's fullFramesLost assert_true: Is fullFramesLost present expected true got false
-PASS remote-inbound-rtp's ssrc
-PASS remote-inbound-rtp's kind
-PASS remote-inbound-rtp's transportId
-PASS remote-inbound-rtp's codecId
-PASS remote-inbound-rtp's timestamp
-PASS remote-inbound-rtp's type
-PASS remote-inbound-rtp's id
-PASS remote-outbound-rtp's localId
-PASS remote-outbound-rtp's remoteTimestamp
-PASS remote-outbound-rtp's reportsSent
-PASS remote-outbound-rtp's packetsSent
-PASS remote-outbound-rtp's bytesSent
-PASS remote-outbound-rtp's ssrc
-PASS remote-outbound-rtp's kind
-PASS remote-outbound-rtp's transportId
-PASS remote-outbound-rtp's codecId
-PASS remote-outbound-rtp's timestamp
-PASS remote-outbound-rtp's type
-PASS remote-outbound-rtp's id
-FAIL csrc's contributorSsrc assert_true: Is contributorSsrc present expected true got false
-FAIL csrc's inboundRtpStreamId assert_true: Is inboundRtpStreamId present expected true got false
-FAIL csrc's packetsContributedTo assert_true: Is packetsContributedTo present expected true got false
-FAIL csrc's audioLevel assert_true: Is audioLevel present expected true got false
-FAIL csrc's timestamp assert_true: Is timestamp present expected true got false
-FAIL csrc's type assert_true: Is type present expected true got false
-FAIL csrc's id assert_true: Is id present expected true got false
-PASS peer-connection's dataChannelsOpened
-PASS peer-connection's dataChannelsClosed
-FAIL peer-connection's dataChannelsRequested assert_true: Is dataChannelsRequested present expected true got false
-FAIL peer-connection's dataChannelsAccepted assert_true: Is dataChannelsAccepted present expected true got false
-PASS peer-connection's timestamp
-PASS peer-connection's type
-PASS peer-connection's id
-PASS data-channel's label
-PASS data-channel's protocol
-PASS data-channel's dataChannelIdentifier
-PASS data-channel's state
-PASS data-channel's messagesSent
-PASS data-channel's bytesSent
-PASS data-channel's messagesReceived
-PASS data-channel's bytesReceived
-PASS data-channel's timestamp
-PASS data-channel's type
-PASS data-channel's id
-PASS media-source's audioLevel
-PASS media-source's totalAudioEnergy
-PASS media-source's totalSamplesDuration
-FAIL media-source's echoReturnLoss assert_true: Is echoReturnLoss present expected true got false
-FAIL media-source's echoReturnLossEnhancement assert_true: Is echoReturnLossEnhancement present expected true got false
-PASS media-source's width
-PASS media-source's height
-FAIL media-source's bitDepth assert_true: Is bitDepth present expected true got false
-PASS media-source's frames
-PASS media-source's framesPerSecond
-PASS media-source's trackIdentifier
-PASS media-source's kind
-FAIL media-source's relayedSource assert_true: Is relayedSource present expected true got false
-PASS media-source's timestamp
-PASS media-source's type
-PASS media-source's id
-FAIL sender's mediaSourceId assert_true: Is mediaSourceId present expected true got false
-FAIL sender's trackIdentifier assert_true: Is trackIdentifier present expected true got false
-FAIL sender's ended assert_true: Is ended present expected true got false
-FAIL sender's kind assert_true: Is kind present expected true got false
-FAIL sender's timestamp assert_true: Is timestamp present expected true got false
-FAIL sender's type assert_true: Is type present expected true got false
-FAIL sender's id assert_true: Is id present expected true got false
-FAIL receiver's trackIdentifier assert_true: Is trackIdentifier present expected true got false
-FAIL receiver's ended assert_true: Is ended present expected true got false
-FAIL receiver's kind assert_true: Is kind present expected true got false
-FAIL receiver's timestamp assert_true: Is timestamp present expected true got false
-FAIL receiver's type assert_true: Is type present expected true got false
-FAIL receiver's id assert_true: Is id present expected true got false
-PASS transport's packetsSent
-PASS transport's packetsReceived
-PASS transport's bytesSent
-PASS transport's bytesReceived
-FAIL transport's rtcpTransportStatsId assert_true: Is rtcpTransportStatsId present expected true got false
-FAIL transport's iceRole assert_true: Is iceRole present expected true got false
-FAIL transport's iceLocalUsernameFragment assert_true: Is iceLocalUsernameFragment present expected true got false
-PASS transport's dtlsState
-FAIL transport's iceState assert_true: Is iceState present expected true got false
-PASS transport's selectedCandidatePairId
-PASS transport's localCertificateId
-PASS transport's remoteCertificateId
-PASS transport's tlsVersion
-PASS transport's dtlsCipher
-PASS transport's srtpCipher
-FAIL transport's tlsGroup assert_true: Is tlsGroup present expected true got false
-PASS transport's selectedCandidatePairChanges
-PASS transport's timestamp
-PASS transport's type
-PASS transport's id
-PASS candidate-pair's transportId
-PASS candidate-pair's localCandidateId
-PASS candidate-pair's remoteCandidateId
-PASS candidate-pair's state
-PASS candidate-pair's nominated
-FAIL candidate-pair's packetsSent assert_true: Is packetsSent present expected true got false
-FAIL candidate-pair's packetsReceived assert_true: Is packetsReceived present expected true got false
-PASS candidate-pair's bytesSent
-PASS candidate-pair's bytesReceived
-FAIL candidate-pair's lastPacketSentTimestamp assert_true: Is lastPacketSentTimestamp present expected true got false
-FAIL candidate-pair's lastPacketReceivedTimestamp assert_true: Is lastPacketReceivedTimestamp present expected true got false
-FAIL candidate-pair's firstRequestTimestamp assert_true: Is firstRequestTimestamp present expected true got false
-FAIL candidate-pair's lastRequestTimestamp assert_true: Is lastRequestTimestamp present expected true got false
-FAIL candidate-pair's lastResponseTimestamp assert_true: Is lastResponseTimestamp present expected true got false
-PASS candidate-pair's totalRoundTripTime
-PASS candidate-pair's currentRoundTripTime
-PASS candidate-pair's availableOutgoingBitrate
-FAIL candidate-pair's availableIncomingBitrate assert_true: Is availableIncomingBitrate present expected true got false
-FAIL candidate-pair's circuitBreakerTriggerCount assert_true: Is circuitBreakerTriggerCount present expected true got false
-PASS candidate-pair's requestsReceived
-PASS candidate-pair's requestsSent
-PASS candidate-pair's responsesReceived
-PASS candidate-pair's responsesSent
-FAIL candidate-pair's retransmissionsReceived assert_true: Is retransmissionsReceived present expected true got false
-FAIL candidate-pair's retransmissionsSent assert_true: Is retransmissionsSent present expected true got false
-PASS candidate-pair's consentRequestsSent
-FAIL candidate-pair's consentExpiredTimestamp assert_true: Is consentExpiredTimestamp present expected true got false
-FAIL candidate-pair's packetsDiscardedOnSend assert_true: Is packetsDiscardedOnSend present expected true got false
-FAIL candidate-pair's bytesDiscardedOnSend assert_true: Is bytesDiscardedOnSend present expected true got false
-FAIL candidate-pair's requestBytesSent assert_true: Is requestBytesSent present expected true got false
-FAIL candidate-pair's consentRequestBytesSent assert_true: Is consentRequestBytesSent present expected true got false
-FAIL candidate-pair's responseBytesSent assert_true: Is responseBytesSent present expected true got false
-PASS candidate-pair's timestamp
-PASS candidate-pair's type
-PASS candidate-pair's id
-PASS local-candidate's transportId
-PASS local-candidate's address
-PASS local-candidate's port
-PASS local-candidate's protocol
-PASS local-candidate's candidateType
-PASS local-candidate's priority
-FAIL local-candidate's url assert_true: Is url present expected true got false
-FAIL local-candidate's relayProtocol assert_true: Is relayProtocol present expected true got false
-PASS local-candidate's timestamp
-PASS local-candidate's type
-PASS local-candidate's id
-PASS remote-candidate's transportId
-PASS remote-candidate's address
-PASS remote-candidate's port
-PASS remote-candidate's protocol
-PASS remote-candidate's candidateType
-PASS remote-candidate's priority
-FAIL remote-candidate's url assert_true: Is url present expected true got false
-FAIL remote-candidate's relayProtocol assert_true: Is relayProtocol present expected true got false
-PASS remote-candidate's timestamp
-PASS remote-candidate's type
-PASS remote-candidate's id
-PASS certificate's fingerprint
-PASS certificate's fingerprintAlgorithm
-PASS certificate's base64Certificate
-FAIL certificate's issuerCertificateId assert_true: Is issuerCertificateId present expected true got false
-PASS certificate's timestamp
-PASS certificate's type
-PASS certificate's id
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/webrtc-stats/supported-stats-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/webrtc-stats/supported-stats-expected.txt
deleted file mode 100644
index 84cb4f1..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/webrtc-stats/supported-stats-expected.txt
+++ /dev/null
@@ -1,314 +0,0 @@
-This is a testharness.js-based test.
-Found 310 tests; 195 PASS, 115 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS getStats succeeds
-PASS Validating stats
-PASS codec's payloadType
-FAIL codec's codecType assert_true: Is codecType present expected true got false
-PASS codec's transportId
-PASS codec's mimeType
-PASS codec's clockRate
-PASS codec's channels
-PASS codec's sdpFmtpLine
-PASS codec's timestamp
-PASS codec's type
-PASS codec's id
-FAIL inbound-rtp's receiverId assert_true: Is receiverId present expected true got false
-PASS inbound-rtp's remoteId
-PASS inbound-rtp's framesDecoded
-PASS inbound-rtp's keyFramesDecoded
-PASS inbound-rtp's frameWidth
-PASS inbound-rtp's frameHeight
-FAIL inbound-rtp's frameBitDepth assert_true: Is frameBitDepth present expected true got false
-PASS inbound-rtp's framesPerSecond
-PASS inbound-rtp's qpSum
-PASS inbound-rtp's totalDecodeTime
-PASS inbound-rtp's totalInterFrameDelay
-PASS inbound-rtp's totalSquaredInterFrameDelay
-FAIL inbound-rtp's voiceActivityFlag assert_true: Is voiceActivityFlag present expected true got false
-PASS inbound-rtp's lastPacketReceivedTimestamp
-FAIL inbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
-PASS inbound-rtp's headerBytesReceived
-PASS inbound-rtp's fecPacketsReceived
-PASS inbound-rtp's fecPacketsDiscarded
-PASS inbound-rtp's bytesReceived
-FAIL inbound-rtp's packetsFailedDecryption assert_true: Is packetsFailedDecryption present expected true got false
-FAIL inbound-rtp's packetsDuplicated assert_true: Is packetsDuplicated present expected true got false
-FAIL inbound-rtp's perDscpPacketsReceived assert_true: Is perDscpPacketsReceived present expected true got false
-PASS inbound-rtp's nackCount
-PASS inbound-rtp's firCount
-PASS inbound-rtp's pliCount
-FAIL inbound-rtp's sliCount assert_true: Is sliCount present expected true got false
-FAIL inbound-rtp's totalProcessingDelay assert_true: Is totalProcessingDelay present expected true got false
-FAIL inbound-rtp's estimatedPlayoutTimestamp assert_true: Is estimatedPlayoutTimestamp present expected true got false
-PASS inbound-rtp's jitterBufferDelay
-PASS inbound-rtp's jitterBufferEmittedCount
-PASS inbound-rtp's totalSamplesReceived
-FAIL inbound-rtp's totalSamplesDecoded assert_true: Is totalSamplesDecoded present expected true got false
-FAIL inbound-rtp's samplesDecodedWithSilk assert_true: Is samplesDecodedWithSilk present expected true got false
-FAIL inbound-rtp's samplesDecodedWithCelt assert_true: Is samplesDecodedWithCelt present expected true got false
-PASS inbound-rtp's concealedSamples
-PASS inbound-rtp's silentConcealedSamples
-PASS inbound-rtp's concealmentEvents
-PASS inbound-rtp's insertedSamplesForDeceleration
-PASS inbound-rtp's removedSamplesForAcceleration
-PASS inbound-rtp's audioLevel
-PASS inbound-rtp's totalAudioEnergy
-PASS inbound-rtp's totalSamplesDuration
-PASS inbound-rtp's framesReceived
-PASS inbound-rtp's decoderImplementation
-PASS inbound-rtp's packetsReceived
-PASS inbound-rtp's packetsLost
-PASS inbound-rtp's jitter
-FAIL inbound-rtp's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
-FAIL inbound-rtp's packetsRepaired assert_true: Is packetsRepaired present expected true got false
-FAIL inbound-rtp's burstPacketsLost assert_true: Is burstPacketsLost present expected true got false
-FAIL inbound-rtp's burstPacketsDiscarded assert_true: Is burstPacketsDiscarded present expected true got false
-FAIL inbound-rtp's burstLossCount assert_true: Is burstLossCount present expected true got false
-FAIL inbound-rtp's burstDiscardCount assert_true: Is burstDiscardCount present expected true got false
-FAIL inbound-rtp's burstLossRate assert_true: Is burstLossRate present expected true got false
-FAIL inbound-rtp's burstDiscardRate assert_true: Is burstDiscardRate present expected true got false
-FAIL inbound-rtp's gapLossRate assert_true: Is gapLossRate present expected true got false
-FAIL inbound-rtp's gapDiscardRate assert_true: Is gapDiscardRate present expected true got false
-PASS inbound-rtp's framesDropped
-FAIL inbound-rtp's partialFramesLost assert_true: Is partialFramesLost present expected true got false
-FAIL inbound-rtp's fullFramesLost assert_true: Is fullFramesLost present expected true got false
-PASS inbound-rtp's ssrc
-PASS inbound-rtp's kind
-PASS inbound-rtp's transportId
-PASS inbound-rtp's codecId
-PASS inbound-rtp's timestamp
-PASS inbound-rtp's type
-PASS inbound-rtp's id
-FAIL outbound-rtp's rtxSsrc assert_true: Is rtxSsrc present expected true got false
-PASS outbound-rtp's mediaSourceId
-FAIL outbound-rtp's senderId assert_true: Is senderId present expected true got false
-PASS outbound-rtp's remoteId
-FAIL outbound-rtp's rid assert_true: Is rid present expected true got false
-FAIL outbound-rtp's lastPacketSentTimestamp assert_true: Is lastPacketSentTimestamp present expected true got false
-PASS outbound-rtp's headerBytesSent
-FAIL outbound-rtp's packetsDiscardedOnSend assert_true: Is packetsDiscardedOnSend present expected true got false
-FAIL outbound-rtp's bytesDiscardedOnSend assert_true: Is bytesDiscardedOnSend present expected true got false
-FAIL outbound-rtp's fecPacketsSent assert_true: Is fecPacketsSent present expected true got false
-PASS outbound-rtp's retransmittedPacketsSent
-PASS outbound-rtp's retransmittedBytesSent
-FAIL outbound-rtp's targetBitrate assert_true: Is targetBitrate present expected true got false
-PASS outbound-rtp's totalEncodedBytesTarget
-PASS outbound-rtp's frameWidth
-PASS outbound-rtp's frameHeight
-FAIL outbound-rtp's frameBitDepth assert_true: Is frameBitDepth present expected true got false
-PASS outbound-rtp's framesPerSecond
-PASS outbound-rtp's framesSent
-PASS outbound-rtp's hugeFramesSent
-PASS outbound-rtp's framesEncoded
-PASS outbound-rtp's keyFramesEncoded
-FAIL outbound-rtp's framesDiscardedOnSend assert_true: Is framesDiscardedOnSend present expected true got false
-PASS outbound-rtp's qpSum
-FAIL outbound-rtp's totalSamplesSent assert_true: Is totalSamplesSent present expected true got false
-FAIL outbound-rtp's samplesEncodedWithSilk assert_true: Is samplesEncodedWithSilk present expected true got false
-FAIL outbound-rtp's samplesEncodedWithCelt assert_true: Is samplesEncodedWithCelt present expected true got false
-FAIL outbound-rtp's voiceActivityFlag assert_true: Is voiceActivityFlag present expected true got false
-PASS outbound-rtp's totalEncodeTime
-PASS outbound-rtp's totalPacketSendDelay
-FAIL outbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
-PASS outbound-rtp's qualityLimitationReason
-FAIL outbound-rtp's qualityLimitationDurations assert_true: Is qualityLimitationDurations present expected true got false
-PASS outbound-rtp's qualityLimitationResolutionChanges
-FAIL outbound-rtp's perDscpPacketsSent assert_true: Is perDscpPacketsSent present expected true got false
-PASS outbound-rtp's nackCount
-PASS outbound-rtp's firCount
-PASS outbound-rtp's pliCount
-FAIL outbound-rtp's sliCount assert_true: Is sliCount present expected true got false
-PASS outbound-rtp's encoderImplementation
-PASS outbound-rtp's packetsSent
-PASS outbound-rtp's bytesSent
-PASS outbound-rtp's ssrc
-PASS outbound-rtp's kind
-PASS outbound-rtp's transportId
-PASS outbound-rtp's codecId
-PASS outbound-rtp's timestamp
-PASS outbound-rtp's type
-PASS outbound-rtp's id
-PASS remote-inbound-rtp's localId
-PASS remote-inbound-rtp's roundTripTime
-PASS remote-inbound-rtp's totalRoundTripTime
-PASS remote-inbound-rtp's fractionLost
-FAIL remote-inbound-rtp's reportsReceived assert_true: Is reportsReceived present expected true got false
-PASS remote-inbound-rtp's roundTripTimeMeasurements
-FAIL remote-inbound-rtp's packetsReceived assert_true: Is packetsReceived present expected true got false
-PASS remote-inbound-rtp's packetsLost
-PASS remote-inbound-rtp's jitter
-FAIL remote-inbound-rtp's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
-FAIL remote-inbound-rtp's packetsRepaired assert_true: Is packetsRepaired present expected true got false
-FAIL remote-inbound-rtp's burstPacketsLost assert_true: Is burstPacketsLost present expected true got false
-FAIL remote-inbound-rtp's burstPacketsDiscarded assert_true: Is burstPacketsDiscarded present expected true got false
-FAIL remote-inbound-rtp's burstLossCount assert_true: Is burstLossCount present expected true got false
-FAIL remote-inbound-rtp's burstDiscardCount assert_true: Is burstDiscardCount present expected true got false
-FAIL remote-inbound-rtp's burstLossRate assert_true: Is burstLossRate present expected true got false
-FAIL remote-inbound-rtp's burstDiscardRate assert_true: Is burstDiscardRate present expected true got false
-FAIL remote-inbound-rtp's gapLossRate assert_true: Is gapLossRate present expected true got false
-FAIL remote-inbound-rtp's gapDiscardRate assert_true: Is gapDiscardRate present expected true got false
-FAIL remote-inbound-rtp's framesDropped assert_true: Is framesDropped present expected true got false
-FAIL remote-inbound-rtp's partialFramesLost assert_true: Is partialFramesLost present expected true got false
-FAIL remote-inbound-rtp's fullFramesLost assert_true: Is fullFramesLost present expected true got false
-PASS remote-inbound-rtp's ssrc
-PASS remote-inbound-rtp's kind
-PASS remote-inbound-rtp's transportId
-PASS remote-inbound-rtp's codecId
-PASS remote-inbound-rtp's timestamp
-PASS remote-inbound-rtp's type
-PASS remote-inbound-rtp's id
-PASS remote-outbound-rtp's localId
-PASS remote-outbound-rtp's remoteTimestamp
-PASS remote-outbound-rtp's reportsSent
-FAIL remote-outbound-rtp's roundTripTime assert_true: Is roundTripTime present expected true got false
-FAIL remote-outbound-rtp's totalRoundTripTime assert_true: Is totalRoundTripTime present expected true got false
-FAIL remote-outbound-rtp's roundTripTimeMeasurements assert_true: Is roundTripTimeMeasurements present expected true got false
-PASS remote-outbound-rtp's packetsSent
-PASS remote-outbound-rtp's bytesSent
-PASS remote-outbound-rtp's ssrc
-PASS remote-outbound-rtp's kind
-PASS remote-outbound-rtp's transportId
-PASS remote-outbound-rtp's codecId
-PASS remote-outbound-rtp's timestamp
-PASS remote-outbound-rtp's type
-PASS remote-outbound-rtp's id
-FAIL csrc's contributorSsrc assert_true: Is contributorSsrc present expected true got false
-FAIL csrc's inboundRtpStreamId assert_true: Is inboundRtpStreamId present expected true got false
-FAIL csrc's packetsContributedTo assert_true: Is packetsContributedTo present expected true got false
-FAIL csrc's audioLevel assert_true: Is audioLevel present expected true got false
-FAIL csrc's timestamp assert_true: Is timestamp present expected true got false
-FAIL csrc's type assert_true: Is type present expected true got false
-FAIL csrc's id assert_true: Is id present expected true got false
-PASS peer-connection's dataChannelsOpened
-PASS peer-connection's dataChannelsClosed
-FAIL peer-connection's dataChannelsRequested assert_true: Is dataChannelsRequested present expected true got false
-FAIL peer-connection's dataChannelsAccepted assert_true: Is dataChannelsAccepted present expected true got false
-PASS peer-connection's timestamp
-PASS peer-connection's type
-PASS peer-connection's id
-PASS data-channel's label
-PASS data-channel's protocol
-PASS data-channel's dataChannelIdentifier
-PASS data-channel's state
-PASS data-channel's messagesSent
-PASS data-channel's bytesSent
-PASS data-channel's messagesReceived
-PASS data-channel's bytesReceived
-PASS data-channel's timestamp
-PASS data-channel's type
-PASS data-channel's id
-PASS media-source's audioLevel
-PASS media-source's totalAudioEnergy
-PASS media-source's totalSamplesDuration
-FAIL media-source's echoReturnLoss assert_true: Is echoReturnLoss present expected true got false
-FAIL media-source's echoReturnLossEnhancement assert_true: Is echoReturnLossEnhancement present expected true got false
-PASS media-source's width
-PASS media-source's height
-FAIL media-source's bitDepth assert_true: Is bitDepth present expected true got false
-PASS media-source's frames
-PASS media-source's framesPerSecond
-PASS media-source's trackIdentifier
-PASS media-source's kind
-FAIL media-source's relayedSource assert_true: Is relayedSource present expected true got false
-PASS media-source's timestamp
-PASS media-source's type
-PASS media-source's id
-FAIL sender's mediaSourceId assert_true: Is mediaSourceId present expected true got false
-FAIL sender's trackIdentifier assert_true: Is trackIdentifier present expected true got false
-FAIL sender's ended assert_true: Is ended present expected true got false
-FAIL sender's kind assert_true: Is kind present expected true got false
-FAIL sender's timestamp assert_true: Is timestamp present expected true got false
-FAIL sender's type assert_true: Is type present expected true got false
-FAIL sender's id assert_true: Is id present expected true got false
-FAIL receiver's trackIdentifier assert_true: Is trackIdentifier present expected true got false
-FAIL receiver's ended assert_true: Is ended present expected true got false
-FAIL receiver's kind assert_true: Is kind present expected true got false
-FAIL receiver's timestamp assert_true: Is timestamp present expected true got false
-FAIL receiver's type assert_true: Is type present expected true got false
-FAIL receiver's id assert_true: Is id present expected true got false
-PASS transport's packetsSent
-PASS transport's packetsReceived
-PASS transport's bytesSent
-PASS transport's bytesReceived
-FAIL transport's rtcpTransportStatsId assert_true: Is rtcpTransportStatsId present expected true got false
-FAIL transport's iceRole assert_true: Is iceRole present expected true got false
-FAIL transport's iceLocalUsernameFragment assert_true: Is iceLocalUsernameFragment present expected true got false
-PASS transport's dtlsState
-FAIL transport's iceState assert_true: Is iceState present expected true got false
-PASS transport's selectedCandidatePairId
-PASS transport's localCertificateId
-PASS transport's remoteCertificateId
-PASS transport's tlsVersion
-PASS transport's dtlsCipher
-PASS transport's srtpCipher
-FAIL transport's tlsGroup assert_true: Is tlsGroup present expected true got false
-PASS transport's selectedCandidatePairChanges
-PASS transport's timestamp
-PASS transport's type
-PASS transport's id
-PASS candidate-pair's transportId
-PASS candidate-pair's localCandidateId
-PASS candidate-pair's remoteCandidateId
-PASS candidate-pair's state
-PASS candidate-pair's nominated
-FAIL candidate-pair's packetsSent assert_true: Is packetsSent present expected true got false
-FAIL candidate-pair's packetsReceived assert_true: Is packetsReceived present expected true got false
-PASS candidate-pair's bytesSent
-PASS candidate-pair's bytesReceived
-FAIL candidate-pair's lastPacketSentTimestamp assert_true: Is lastPacketSentTimestamp present expected true got false
-FAIL candidate-pair's lastPacketReceivedTimestamp assert_true: Is lastPacketReceivedTimestamp present expected true got false
-FAIL candidate-pair's firstRequestTimestamp assert_true: Is firstRequestTimestamp present expected true got false
-FAIL candidate-pair's lastRequestTimestamp assert_true: Is lastRequestTimestamp present expected true got false
-FAIL candidate-pair's lastResponseTimestamp assert_true: Is lastResponseTimestamp present expected true got false
-PASS candidate-pair's totalRoundTripTime
-PASS candidate-pair's currentRoundTripTime
-PASS candidate-pair's availableOutgoingBitrate
-FAIL candidate-pair's availableIncomingBitrate assert_true: Is availableIncomingBitrate present expected true got false
-FAIL candidate-pair's circuitBreakerTriggerCount assert_true: Is circuitBreakerTriggerCount present expected true got false
-PASS candidate-pair's requestsReceived
-PASS candidate-pair's requestsSent
-PASS candidate-pair's responsesReceived
-PASS candidate-pair's responsesSent
-FAIL candidate-pair's retransmissionsReceived assert_true: Is retransmissionsReceived present expected true got false
-FAIL candidate-pair's retransmissionsSent assert_true: Is retransmissionsSent present expected true got false
-PASS candidate-pair's consentRequestsSent
-FAIL candidate-pair's consentExpiredTimestamp assert_true: Is consentExpiredTimestamp present expected true got false
-FAIL candidate-pair's packetsDiscardedOnSend assert_true: Is packetsDiscardedOnSend present expected true got false
-FAIL candidate-pair's bytesDiscardedOnSend assert_true: Is bytesDiscardedOnSend present expected true got false
-FAIL candidate-pair's requestBytesSent assert_true: Is requestBytesSent present expected true got false
-FAIL candidate-pair's consentRequestBytesSent assert_true: Is consentRequestBytesSent present expected true got false
-FAIL candidate-pair's responseBytesSent assert_true: Is responseBytesSent present expected true got false
-PASS candidate-pair's timestamp
-PASS candidate-pair's type
-PASS candidate-pair's id
-PASS local-candidate's transportId
-PASS local-candidate's address
-PASS local-candidate's port
-PASS local-candidate's protocol
-PASS local-candidate's candidateType
-PASS local-candidate's priority
-FAIL local-candidate's url assert_true: Is url present expected true got false
-FAIL local-candidate's relayProtocol assert_true: Is relayProtocol present expected true got false
-PASS local-candidate's timestamp
-PASS local-candidate's type
-PASS local-candidate's id
-PASS remote-candidate's transportId
-PASS remote-candidate's address
-PASS remote-candidate's port
-PASS remote-candidate's protocol
-PASS remote-candidate's candidateType
-PASS remote-candidate's priority
-FAIL remote-candidate's url assert_true: Is url present expected true got false
-FAIL remote-candidate's relayProtocol assert_true: Is relayProtocol present expected true got false
-PASS remote-candidate's timestamp
-PASS remote-candidate's type
-PASS remote-candidate's id
-PASS certificate's fingerprint
-PASS certificate's fingerprintAlgorithm
-PASS certificate's base64Certificate
-FAIL certificate's issuerCertificateId assert_true: Is issuerCertificateId present expected true got false
-PASS certificate's timestamp
-PASS certificate's type
-PASS certificate's id
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webrtc-stats/supported-stats-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webrtc-stats/supported-stats-expected.txt
deleted file mode 100644
index 9781bfe..0000000
--- a/third_party/blink/web_tests/platform/mac/external/wpt/webrtc-stats/supported-stats-expected.txt
+++ /dev/null
@@ -1,314 +0,0 @@
-This is a testharness.js-based test.
-Found 310 tests; 115 PASS, 195 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS getStats succeeds
-PASS Validating stats
-PASS codec's payloadType
-FAIL codec's codecType assert_true: Is codecType present expected true got false
-PASS codec's transportId
-PASS codec's mimeType
-PASS codec's clockRate
-PASS codec's channels
-PASS codec's sdpFmtpLine
-PASS codec's timestamp
-PASS codec's type
-PASS codec's id
-FAIL inbound-rtp's receiverId assert_true: Is receiverId present expected true got false
-FAIL inbound-rtp's remoteId assert_true: Is remoteId present expected true got false
-PASS inbound-rtp's framesDecoded
-PASS inbound-rtp's keyFramesDecoded
-FAIL inbound-rtp's frameWidth assert_true: Is frameWidth present expected true got false
-FAIL inbound-rtp's frameHeight assert_true: Is frameHeight present expected true got false
-FAIL inbound-rtp's frameBitDepth assert_true: Is frameBitDepth present expected true got false
-FAIL inbound-rtp's framesPerSecond assert_true: Is framesPerSecond present expected true got false
-FAIL inbound-rtp's qpSum assert_true: Is qpSum present expected true got false
-PASS inbound-rtp's totalDecodeTime
-PASS inbound-rtp's totalInterFrameDelay
-PASS inbound-rtp's totalSquaredInterFrameDelay
-FAIL inbound-rtp's voiceActivityFlag assert_true: Is voiceActivityFlag present expected true got false
-FAIL inbound-rtp's lastPacketReceivedTimestamp assert_true: Is lastPacketReceivedTimestamp present expected true got false
-FAIL inbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
-PASS inbound-rtp's headerBytesReceived
-PASS inbound-rtp's fecPacketsReceived
-PASS inbound-rtp's fecPacketsDiscarded
-PASS inbound-rtp's bytesReceived
-FAIL inbound-rtp's packetsFailedDecryption assert_true: Is packetsFailedDecryption present expected true got false
-FAIL inbound-rtp's packetsDuplicated assert_true: Is packetsDuplicated present expected true got false
-FAIL inbound-rtp's perDscpPacketsReceived assert_true: Is perDscpPacketsReceived present expected true got false
-PASS inbound-rtp's nackCount
-PASS inbound-rtp's firCount
-PASS inbound-rtp's pliCount
-FAIL inbound-rtp's sliCount assert_true: Is sliCount present expected true got false
-FAIL inbound-rtp's totalProcessingDelay assert_true: Is totalProcessingDelay present expected true got false
-FAIL inbound-rtp's estimatedPlayoutTimestamp assert_true: Is estimatedPlayoutTimestamp present expected true got false
-PASS inbound-rtp's jitterBufferDelay
-PASS inbound-rtp's jitterBufferEmittedCount
-PASS inbound-rtp's totalSamplesReceived
-FAIL inbound-rtp's totalSamplesDecoded assert_true: Is totalSamplesDecoded present expected true got false
-FAIL inbound-rtp's samplesDecodedWithSilk assert_true: Is samplesDecodedWithSilk present expected true got false
-FAIL inbound-rtp's samplesDecodedWithCelt assert_true: Is samplesDecodedWithCelt present expected true got false
-PASS inbound-rtp's concealedSamples
-PASS inbound-rtp's silentConcealedSamples
-PASS inbound-rtp's concealmentEvents
-PASS inbound-rtp's insertedSamplesForDeceleration
-PASS inbound-rtp's removedSamplesForAcceleration
-FAIL inbound-rtp's audioLevel assert_true: Is audioLevel present expected true got false
-PASS inbound-rtp's totalAudioEnergy
-PASS inbound-rtp's totalSamplesDuration
-PASS inbound-rtp's framesReceived
-PASS inbound-rtp's decoderImplementation
-PASS inbound-rtp's packetsReceived
-PASS inbound-rtp's packetsLost
-PASS inbound-rtp's jitter
-FAIL inbound-rtp's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
-FAIL inbound-rtp's packetsRepaired assert_true: Is packetsRepaired present expected true got false
-FAIL inbound-rtp's burstPacketsLost assert_true: Is burstPacketsLost present expected true got false
-FAIL inbound-rtp's burstPacketsDiscarded assert_true: Is burstPacketsDiscarded present expected true got false
-FAIL inbound-rtp's burstLossCount assert_true: Is burstLossCount present expected true got false
-FAIL inbound-rtp's burstDiscardCount assert_true: Is burstDiscardCount present expected true got false
-FAIL inbound-rtp's burstLossRate assert_true: Is burstLossRate present expected true got false
-FAIL inbound-rtp's burstDiscardRate assert_true: Is burstDiscardRate present expected true got false
-FAIL inbound-rtp's gapLossRate assert_true: Is gapLossRate present expected true got false
-FAIL inbound-rtp's gapDiscardRate assert_true: Is gapDiscardRate present expected true got false
-PASS inbound-rtp's framesDropped
-FAIL inbound-rtp's partialFramesLost assert_true: Is partialFramesLost present expected true got false
-FAIL inbound-rtp's fullFramesLost assert_true: Is fullFramesLost present expected true got false
-PASS inbound-rtp's ssrc
-PASS inbound-rtp's kind
-PASS inbound-rtp's transportId
-FAIL inbound-rtp's codecId assert_true: Is codecId present expected true got false
-PASS inbound-rtp's timestamp
-PASS inbound-rtp's type
-PASS inbound-rtp's id
-FAIL outbound-rtp's rtxSsrc assert_true: Is rtxSsrc present expected true got false
-PASS outbound-rtp's mediaSourceId
-FAIL outbound-rtp's senderId assert_true: Is senderId present expected true got false
-FAIL outbound-rtp's remoteId assert_true: Is remoteId present expected true got false
-FAIL outbound-rtp's rid assert_true: Is rid present expected true got false
-FAIL outbound-rtp's lastPacketSentTimestamp assert_true: Is lastPacketSentTimestamp present expected true got false
-PASS outbound-rtp's headerBytesSent
-FAIL outbound-rtp's packetsDiscardedOnSend assert_true: Is packetsDiscardedOnSend present expected true got false
-FAIL outbound-rtp's bytesDiscardedOnSend assert_true: Is bytesDiscardedOnSend present expected true got false
-FAIL outbound-rtp's fecPacketsSent assert_true: Is fecPacketsSent present expected true got false
-PASS outbound-rtp's retransmittedPacketsSent
-PASS outbound-rtp's retransmittedBytesSent
-FAIL outbound-rtp's targetBitrate assert_true: Is targetBitrate present expected true got false
-PASS outbound-rtp's totalEncodedBytesTarget
-FAIL outbound-rtp's frameWidth assert_true: Is frameWidth present expected true got false
-FAIL outbound-rtp's frameHeight assert_true: Is frameHeight present expected true got false
-FAIL outbound-rtp's frameBitDepth assert_true: Is frameBitDepth present expected true got false
-FAIL outbound-rtp's framesPerSecond assert_true: Is framesPerSecond present expected true got false
-PASS outbound-rtp's framesSent
-PASS outbound-rtp's hugeFramesSent
-PASS outbound-rtp's framesEncoded
-PASS outbound-rtp's keyFramesEncoded
-FAIL outbound-rtp's framesDiscardedOnSend assert_true: Is framesDiscardedOnSend present expected true got false
-FAIL outbound-rtp's qpSum assert_true: Is qpSum present expected true got false
-FAIL outbound-rtp's totalSamplesSent assert_true: Is totalSamplesSent present expected true got false
-FAIL outbound-rtp's samplesEncodedWithSilk assert_true: Is samplesEncodedWithSilk present expected true got false
-FAIL outbound-rtp's samplesEncodedWithCelt assert_true: Is samplesEncodedWithCelt present expected true got false
-FAIL outbound-rtp's voiceActivityFlag assert_true: Is voiceActivityFlag present expected true got false
-PASS outbound-rtp's totalEncodeTime
-PASS outbound-rtp's totalPacketSendDelay
-FAIL outbound-rtp's averageRtcpInterval assert_true: Is averageRtcpInterval present expected true got false
-PASS outbound-rtp's qualityLimitationReason
-FAIL outbound-rtp's qualityLimitationDurations assert_true: Is qualityLimitationDurations present expected true got false
-PASS outbound-rtp's qualityLimitationResolutionChanges
-FAIL outbound-rtp's perDscpPacketsSent assert_true: Is perDscpPacketsSent present expected true got false
-PASS outbound-rtp's nackCount
-PASS outbound-rtp's firCount
-PASS outbound-rtp's pliCount
-FAIL outbound-rtp's sliCount assert_true: Is sliCount present expected true got false
-PASS outbound-rtp's encoderImplementation
-PASS outbound-rtp's packetsSent
-PASS outbound-rtp's bytesSent
-PASS outbound-rtp's ssrc
-PASS outbound-rtp's kind
-PASS outbound-rtp's transportId
-PASS outbound-rtp's codecId
-PASS outbound-rtp's timestamp
-PASS outbound-rtp's type
-PASS outbound-rtp's id
-FAIL remote-inbound-rtp's localId assert_true: Is localId present expected true got false
-FAIL remote-inbound-rtp's roundTripTime assert_true: Is roundTripTime present expected true got false
-FAIL remote-inbound-rtp's totalRoundTripTime assert_true: Is totalRoundTripTime present expected true got false
-FAIL remote-inbound-rtp's fractionLost assert_true: Is fractionLost present expected true got false
-FAIL remote-inbound-rtp's reportsReceived assert_true: Is reportsReceived present expected true got false
-FAIL remote-inbound-rtp's roundTripTimeMeasurements assert_true: Is roundTripTimeMeasurements present expected true got false
-FAIL remote-inbound-rtp's packetsReceived assert_true: Is packetsReceived present expected true got false
-FAIL remote-inbound-rtp's packetsLost assert_true: Is packetsLost present expected true got false
-FAIL remote-inbound-rtp's jitter assert_true: Is jitter present expected true got false
-FAIL remote-inbound-rtp's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
-FAIL remote-inbound-rtp's packetsRepaired assert_true: Is packetsRepaired present expected true got false
-FAIL remote-inbound-rtp's burstPacketsLost assert_true: Is burstPacketsLost present expected true got false
-FAIL remote-inbound-rtp's burstPacketsDiscarded assert_true: Is burstPacketsDiscarded present expected true got false
-FAIL remote-inbound-rtp's burstLossCount assert_true: Is burstLossCount present expected true got false
-FAIL remote-inbound-rtp's burstDiscardCount assert_true: Is burstDiscardCount present expected true got false
-FAIL remote-inbound-rtp's burstLossRate assert_true: Is burstLossRate present expected true got false
-FAIL remote-inbound-rtp's burstDiscardRate assert_true: Is burstDiscardRate present expected true got false
-FAIL remote-inbound-rtp's gapLossRate assert_true: Is gapLossRate present expected true got false
-FAIL remote-inbound-rtp's gapDiscardRate assert_true: Is gapDiscardRate present expected true got false
-FAIL remote-inbound-rtp's framesDropped assert_true: Is framesDropped present expected true got false
-FAIL remote-inbound-rtp's partialFramesLost assert_true: Is partialFramesLost present expected true got false
-FAIL remote-inbound-rtp's fullFramesLost assert_true: Is fullFramesLost present expected true got false
-FAIL remote-inbound-rtp's ssrc assert_true: Is ssrc present expected true got false
-FAIL remote-inbound-rtp's kind assert_true: Is kind present expected true got false
-FAIL remote-inbound-rtp's transportId assert_true: Is transportId present expected true got false
-FAIL remote-inbound-rtp's codecId assert_true: Is codecId present expected true got false
-FAIL remote-inbound-rtp's timestamp assert_true: Is timestamp present expected true got false
-FAIL remote-inbound-rtp's type assert_true: Is type present expected true got false
-FAIL remote-inbound-rtp's id assert_true: Is id present expected true got false
-FAIL remote-outbound-rtp's localId assert_true: Is localId present expected true got false
-FAIL remote-outbound-rtp's remoteTimestamp assert_true: Is remoteTimestamp present expected true got false
-FAIL remote-outbound-rtp's reportsSent assert_true: Is reportsSent present expected true got false
-FAIL remote-outbound-rtp's roundTripTime assert_true: Is roundTripTime present expected true got false
-FAIL remote-outbound-rtp's totalRoundTripTime assert_true: Is totalRoundTripTime present expected true got false
-FAIL remote-outbound-rtp's roundTripTimeMeasurements assert_true: Is roundTripTimeMeasurements present expected true got false
-FAIL remote-outbound-rtp's packetsSent assert_true: Is packetsSent present expected true got false
-FAIL remote-outbound-rtp's bytesSent assert_true: Is bytesSent present expected true got false
-FAIL remote-outbound-rtp's ssrc assert_true: Is ssrc present expected true got false
-FAIL remote-outbound-rtp's kind assert_true: Is kind present expected true got false
-FAIL remote-outbound-rtp's transportId assert_true: Is transportId present expected true got false
-FAIL remote-outbound-rtp's codecId assert_true: Is codecId present expected true got false
-FAIL remote-outbound-rtp's timestamp assert_true: Is timestamp present expected true got false
-FAIL remote-outbound-rtp's type assert_true: Is type present expected true got false
-FAIL remote-outbound-rtp's id assert_true: Is id present expected true got false
-FAIL csrc's contributorSsrc assert_true: Is contributorSsrc present expected true got false
-FAIL csrc's inboundRtpStreamId assert_true: Is inboundRtpStreamId present expected true got false
-FAIL csrc's packetsContributedTo assert_true: Is packetsContributedTo present expected true got false
-FAIL csrc's audioLevel assert_true: Is audioLevel present expected true got false
-FAIL csrc's timestamp assert_true: Is timestamp present expected true got false
-FAIL csrc's type assert_true: Is type present expected true got false
-FAIL csrc's id assert_true: Is id present expected true got false
-PASS peer-connection's dataChannelsOpened
-PASS peer-connection's dataChannelsClosed
-FAIL peer-connection's dataChannelsRequested assert_true: Is dataChannelsRequested present expected true got false
-FAIL peer-connection's dataChannelsAccepted assert_true: Is dataChannelsAccepted present expected true got false
-PASS peer-connection's timestamp
-PASS peer-connection's type
-PASS peer-connection's id
-PASS data-channel's label
-PASS data-channel's protocol
-PASS data-channel's dataChannelIdentifier
-PASS data-channel's state
-PASS data-channel's messagesSent
-PASS data-channel's bytesSent
-PASS data-channel's messagesReceived
-PASS data-channel's bytesReceived
-PASS data-channel's timestamp
-PASS data-channel's type
-PASS data-channel's id
-PASS media-source's audioLevel
-PASS media-source's totalAudioEnergy
-PASS media-source's totalSamplesDuration
-FAIL media-source's echoReturnLoss assert_true: Is echoReturnLoss present expected true got false
-FAIL media-source's echoReturnLossEnhancement assert_true: Is echoReturnLossEnhancement present expected true got false
-PASS media-source's width
-PASS media-source's height
-FAIL media-source's bitDepth assert_true: Is bitDepth present expected true got false
-PASS media-source's frames
-PASS media-source's framesPerSecond
-PASS media-source's trackIdentifier
-PASS media-source's kind
-FAIL media-source's relayedSource assert_true: Is relayedSource present expected true got false
-PASS media-source's timestamp
-PASS media-source's type
-PASS media-source's id
-FAIL sender's mediaSourceId assert_true: Is mediaSourceId present expected true got false
-FAIL sender's trackIdentifier assert_true: Is trackIdentifier present expected true got false
-FAIL sender's ended assert_true: Is ended present expected true got false
-FAIL sender's kind assert_true: Is kind present expected true got false
-FAIL sender's timestamp assert_true: Is timestamp present expected true got false
-FAIL sender's type assert_true: Is type present expected true got false
-FAIL sender's id assert_true: Is id present expected true got false
-FAIL receiver's trackIdentifier assert_true: Is trackIdentifier present expected true got false
-FAIL receiver's ended assert_true: Is ended present expected true got false
-FAIL receiver's kind assert_true: Is kind present expected true got false
-FAIL receiver's timestamp assert_true: Is timestamp present expected true got false
-FAIL receiver's type assert_true: Is type present expected true got false
-FAIL receiver's id assert_true: Is id present expected true got false
-PASS transport's packetsSent
-PASS transport's packetsReceived
-PASS transport's bytesSent
-PASS transport's bytesReceived
-FAIL transport's rtcpTransportStatsId assert_true: Is rtcpTransportStatsId present expected true got false
-FAIL transport's iceRole assert_true: Is iceRole present expected true got false
-FAIL transport's iceLocalUsernameFragment assert_true: Is iceLocalUsernameFragment present expected true got false
-PASS transport's dtlsState
-FAIL transport's iceState assert_true: Is iceState present expected true got false
-FAIL transport's selectedCandidatePairId assert_true: Is selectedCandidatePairId present expected true got false
-PASS transport's localCertificateId
-FAIL transport's remoteCertificateId assert_true: Is remoteCertificateId present expected true got false
-FAIL transport's tlsVersion assert_true: Is tlsVersion present expected true got false
-FAIL transport's dtlsCipher assert_true: Is dtlsCipher present expected true got false
-FAIL transport's srtpCipher assert_true: Is srtpCipher present expected true got false
-FAIL transport's tlsGroup assert_true: Is tlsGroup present expected true got false
-PASS transport's selectedCandidatePairChanges
-PASS transport's timestamp
-PASS transport's type
-PASS transport's id
-FAIL candidate-pair's transportId assert_true: Is transportId present expected true got false
-FAIL candidate-pair's localCandidateId assert_true: Is localCandidateId present expected true got false
-FAIL candidate-pair's remoteCandidateId assert_true: Is remoteCandidateId present expected true got false
-FAIL candidate-pair's state assert_true: Is state present expected true got false
-FAIL candidate-pair's nominated assert_true: Is nominated present expected true got false
-FAIL candidate-pair's packetsSent assert_true: Is packetsSent present expected true got false
-FAIL candidate-pair's packetsReceived assert_true: Is packetsReceived present expected true got false
-FAIL candidate-pair's bytesSent assert_true: Is bytesSent present expected true got false
-FAIL candidate-pair's bytesReceived assert_true: Is bytesReceived present expected true got false
-FAIL candidate-pair's lastPacketSentTimestamp assert_true: Is lastPacketSentTimestamp present expected true got false
-FAIL candidate-pair's lastPacketReceivedTimestamp assert_true: Is lastPacketReceivedTimestamp present expected true got false
-FAIL candidate-pair's firstRequestTimestamp assert_true: Is firstRequestTimestamp present expected true got false
-FAIL candidate-pair's lastRequestTimestamp assert_true: Is lastRequestTimestamp present expected true got false
-FAIL candidate-pair's lastResponseTimestamp assert_true: Is lastResponseTimestamp present expected true got false
-FAIL candidate-pair's totalRoundTripTime assert_true: Is totalRoundTripTime present expected true got false
-FAIL candidate-pair's currentRoundTripTime assert_true: Is currentRoundTripTime present expected true got false
-FAIL candidate-pair's availableOutgoingBitrate assert_true: Is availableOutgoingBitrate present expected true got false
-FAIL candidate-pair's availableIncomingBitrate assert_true: Is availableIncomingBitrate present expected true got false
-FAIL candidate-pair's circuitBreakerTriggerCount assert_true: Is circuitBreakerTriggerCount present expected true got false
-FAIL candidate-pair's requestsReceived assert_true: Is requestsReceived present expected true got false
-FAIL candidate-pair's requestsSent assert_true: Is requestsSent present expected true got false
-FAIL candidate-pair's responsesReceived assert_true: Is responsesReceived present expected true got false
-FAIL candidate-pair's responsesSent assert_true: Is responsesSent present expected true got false
-FAIL candidate-pair's retransmissionsReceived assert_true: Is retransmissionsReceived present expected true got false
-FAIL candidate-pair's retransmissionsSent assert_true: Is retransmissionsSent present expected true got false
-FAIL candidate-pair's consentRequestsSent assert_true: Is consentRequestsSent present expected true got false
-FAIL candidate-pair's consentExpiredTimestamp assert_true: Is consentExpiredTimestamp present expected true got false
-FAIL candidate-pair's packetsDiscardedOnSend assert_true: Is packetsDiscardedOnSend present expected true got false
-FAIL candidate-pair's bytesDiscardedOnSend assert_true: Is bytesDiscardedOnSend present expected true got false
-FAIL candidate-pair's requestBytesSent assert_true: Is requestBytesSent present expected true got false
-FAIL candidate-pair's consentRequestBytesSent assert_true: Is consentRequestBytesSent present expected true got false
-FAIL candidate-pair's responseBytesSent assert_true: Is responseBytesSent present expected true got false
-FAIL candidate-pair's timestamp assert_true: Is timestamp present expected true got false
-FAIL candidate-pair's type assert_true: Is type present expected true got false
-FAIL candidate-pair's id assert_true: Is id present expected true got false
-FAIL local-candidate's transportId assert_true: Is transportId present expected true got false
-FAIL local-candidate's address assert_true: Is address present expected true got false
-FAIL local-candidate's port assert_true: Is port present expected true got false
-FAIL local-candidate's protocol assert_true: Is protocol present expected true got false
-FAIL local-candidate's candidateType assert_true: Is candidateType present expected true got false
-FAIL local-candidate's priority assert_true: Is priority present expected true got false
-FAIL local-candidate's url assert_true: Is url present expected true got false
-FAIL local-candidate's relayProtocol assert_true: Is relayProtocol present expected true got false
-FAIL local-candidate's timestamp assert_true: Is timestamp present expected true got false
-FAIL local-candidate's type assert_true: Is type present expected true got false
-FAIL local-candidate's id assert_true: Is id present expected true got false
-FAIL remote-candidate's transportId assert_true: Is transportId present expected true got false
-FAIL remote-candidate's address assert_true: Is address present expected true got false
-FAIL remote-candidate's port assert_true: Is port present expected true got false
-FAIL remote-candidate's protocol assert_true: Is protocol present expected true got false
-FAIL remote-candidate's candidateType assert_true: Is candidateType present expected true got false
-FAIL remote-candidate's priority assert_true: Is priority present expected true got false
-FAIL remote-candidate's url assert_true: Is url present expected true got false
-FAIL remote-candidate's relayProtocol assert_true: Is relayProtocol present expected true got false
-FAIL remote-candidate's timestamp assert_true: Is timestamp present expected true got false
-FAIL remote-candidate's type assert_true: Is type present expected true got false
-FAIL remote-candidate's id assert_true: Is id present expected true got false
-PASS certificate's fingerprint
-PASS certificate's fingerprintAlgorithm
-PASS certificate's base64Certificate
-FAIL certificate's issuerCertificateId assert_true: Is issuerCertificateId present expected true got false
-PASS certificate's timestamp
-PASS certificate's type
-PASS certificate's id
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https-expected.txt b/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https-expected.txt
deleted file mode 100644
index cf15e858..0000000
--- a/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/cache-storage-reporting-service-worker.https-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-FAIL COEP support on ServiceWorker. assert_equals: expected 1 but got 0
-FAIL COEP-Report-Only support on ServiceWorker. assert_equals: expected 1 but got 0
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/credentialless/shared-worker.tentative.https-expected.txt b/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/credentialless/shared-worker.tentative.https-expected.txt
deleted file mode 100644
index 19699d9..0000000
--- a/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/credentialless/shared-worker.tentative.https-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS shared-worker
-PASS fetch same-origin
-PASS fetch same-origin + credentialless worker
-PASS fetch cross-origin
-FAIL fetch cross-origin + credentialless worker assert_equals: coep:none =>  expected (undefined) undefined but got (string) "cross_origin"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt b/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt
deleted file mode 100644
index 19f2b45..0000000
--- a/third_party/blink/web_tests/virtual/plz-service-worker/external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https-expected.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-This is a testharness.js-based test.
-PASS [document] same-origin
-PASS [document] blocked by CORP: same-origin
-PASS [document] blocked due to COEP
-PASS [document] blocked during redirect
-PASS [dedicated worker] same-origin
-PASS [dedicated worker] blocked by CORP: same-origin
-FAIL [dedicated worker] blocked due to COEP assert_equals: expected 2 but got 0
-FAIL [dedicated worker] blocked during redirect assert_equals: expected 2 but got 0
-PASS [shared worker] same-origin
-PASS [shared worker] blocked by CORP: same-origin
-FAIL [shared worker] blocked due to COEP assert_equals: expected 2 but got 0
-FAIL [shared worker] blocked during redirect assert_equals: expected 2 but got 0
-PASS [service worker] same-origin
-PASS [service worker] blocked by CORP: same-origin
-FAIL [service worker] blocked due to COEP assert_equals: expected 2 but got 0
-FAIL [service worker] blocked during redirect assert_equals: expected 2 but got 0
-PASS [between service worker and page] same-origin
-PASS [between service worker and page] blocked by CORP: same-origin
-PASS [between service worker and page] blocked due to COEP
-PASS [between service worker and page] blocked during redirect
-PASS destination: script
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/activation-start.html b/third_party/blink/web_tests/wpt_internal/prerender/activation-start.html
new file mode 100644
index 0000000..01fe837
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/prerender/activation-start.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+This file cannot be upstreamed to WPT until:
+* startPrerendering() usage is replaced with a WebDriver API.
+-->
+<title>PerformanceNavigationTiming.activationStart in prerendered page</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/utils.js"></script>
+<body>
+<script>
+promise_test(async t => {
+  const testChannel = new BroadcastChannel('test-channel');
+  t.add_cleanup(() => {
+    testChannel.close();
+  });
+  const gotMessage = new Promise(resolve => {
+    testChannel.addEventListener('message', e => resolve(e.data), {once: true});
+  });
+  window.open('resources/activation-start.html', '_blank', 'noopener');
+  assert_equals(await gotMessage, 'Done');
+}, 'PerformanceNavigationTiming.activationStart in prernedered page');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/resources/activation-start.html b/third_party/blink/web_tests/wpt_internal/prerender/resources/activation-start.html
new file mode 100644
index 0000000..262a1ae
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/prerender/resources/activation-start.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<body>
+<script>
+function getNextMessage(channel) {
+  return new Promise(resolve => {
+    channel.addEventListener('message', e => resolve(e.data), {once: true});
+  });
+}
+
+function getActivationStart() {
+  const entry = performance.getEntriesByType('navigation')[0];
+  assert_equals(
+      entry.activationStart,
+      entry.toJSON()['activationStart'],
+      'activationStart value must be available in the result of toJSON().');
+  return entry.activationStart;
+}
+
+(async () => {
+  const testChannel = new BroadcastChannel('test-channel');
+  const params = new URLSearchParams(location.search);
+  const isPrerenderingMainFrame = params.has('prerendering') &&
+                                  !params.has('iframe');
+  const isIframe = params.has('iframe');
+  const isInitiator = !isPrerenderingMainFrame && !isIframe;
+
+  const ACTIVATION_DELAY = 10;
+
+  // 1. The initiator document (isInitiator) is opened using window.open() by
+  //    activation-start.html in the parent directory.
+  // 2. The initiator document starts prerendering the prerendering document
+  //    (isPrerenderingMainFrame).
+  // 3. The prerendering document opens the iframe document (isIframe).
+  try {
+    if (isInitiator) {
+      // We use a BroadcastChannel to receive a message from the prerendering
+      // iframe.
+      const prerenderChannel = new BroadcastChannel('prerender-channel');
+      const prerendering_url = new URL(document.URL);
+      prerendering_url.searchParams.set('prerendering', '');
+      startPrerendering(prerendering_url);
+      assert_equals(await getNextMessage(prerenderChannel), 'iframe ready');
+
+      // Wait ACTIVATION_DELAY ms before activation.
+      await new Promise(resolve => setTimeout(resolve, ACTIVATION_DELAY));
+      // Activate the prerendered page.
+      location.href = prerendering_url;
+    } else if (isPrerenderingMainFrame) {
+      const initial_value = getActivationStart();
+      const activation_start_promise = new Promise(resolve => {
+        document.addEventListener('prerenderingchange', () => {
+          resolve(getActivationStart());
+        });
+      });
+      // We use the window's message event handler to receive a message from the
+      // iframe.
+      const msg_from_iframe_promise = getNextMessage(window);
+
+      // Add an iframe.
+      const iframe_url = new URL(document.URL);
+      iframe_url.searchParams.set('iframe', '');
+      const iframe = document.createElement('iframe');
+      iframe.src = iframe_url;
+      document.body.appendChild(iframe);
+
+      assert_equals(
+          initial_value,
+          0,
+          'activationStart must be 0 while prerendering');
+      assert_greater_than_equal(
+          await activation_start_promise,
+          ACTIVATION_DELAY,
+          'activationStart after activation must be greater than or equal to ' +
+          'ACTIVATION_DELAY.');
+      assert_equals(await msg_from_iframe_promise, 'iframe activated');
+
+      // Finishes the test.
+      testChannel.postMessage('Done');
+    } else if (isIframe) {
+      const prerenderChannel = new BroadcastChannel('prerender-channel');
+      const initial_value = getActivationStart();
+      const activation_start_promise = new Promise(resolve => {
+        document.addEventListener('prerenderingchange', () => {
+          resolve(getActivationStart());
+        });
+      });
+      prerenderChannel.postMessage('iframe ready');
+      assert_equals(
+          initial_value,
+          0,
+          'activationStart must be 0 while prerendering in iframe.');
+      assert_greater_than_equal(
+          await activation_start_promise,
+          ACTIVATION_DELAY,
+          'activationStart after activation must be greater than or equal to ' +
+          'ACTIVATION_DELAY in iframe.');
+      window.parent.postMessage('iframe activated');
+    }
+  } catch (e) {
+    testChannel.postMessage(e.toString());
+  }
+})();
+</script>
+</body>
\ No newline at end of file
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index a67a4b93..699091d 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -376,8 +376,9 @@
   "chromeos/components/diagnostics_ui/resources/diagnostics_app_resources.grd": {
     "includes": [2517],
   },
-  "ash/content/file_manager/resources/file_manager_resources.grd": {
-    "includes": [2518],
+  "<(SHARED_INTERMEDIATE_DIR)/ash/content/file_manager/resources/file_manager_swa_resources.grd": {
+    "META": {"sizes": {"includes": [100]}},
+    "includes": [2519],
   },
   "chromeos/components/help_app_ui/resources/help_app_resources.grd": {
     "includes": [2520],
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 9aa0d04d..516ad32 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -23793,6 +23793,15 @@
   <description>Recorded when user sign in was successful.</description>
 </action>
 
+<action name="Signin_Signin_WipeDataOnChildAccountSignin">
+  <owner>triploblastic@chromium.org</owner>
+  <owner>aliceywang@chromium.org</owner>
+  <description>
+    Recorded when wiping data during child account sign-in process. Only
+    recorded on Android.
+  </description>
+</action>
+
 <action name="Signin_Signin_WithAdvancedSyncSettings">
   <owner>gogerald@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e8f0bc8..683c7a76 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -24744,6 +24744,7 @@
   <int value="859" label="CloudUserPolicyMerge"/>
   <int value="860" label="ManagedAccountRestriction"/>
   <int value="861" label="LockIconInAddressBarEnabled"/>
+  <int value="862" label="DeviceScheduledReboot"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
@@ -32802,6 +32803,7 @@
   <int value="3926" label="FontFaceSizeAdjust"/>
   <int value="3927" label="HiddenBackfaceWith3D"/>
   <int value="3928" label="MainFrameNonSecurePrivateAddressSpace"/>
+  <int value="3929" label="CSSSelectorPseudoHas"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/ui/chromeos/translations/ui_chromeos_strings_am.xtb b/ui/chromeos/translations/ui_chromeos_strings_am.xtb
index 3999b12f..7ca5246 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_am.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_am.xtb
@@ -540,7 +540,7 @@
 <translation id="6629841649550503054">ሁሉም ወደ <ph name="BEGIN_LINK" />Google Drive<ph name="END_LINK" /> በምትኬ ተቀምጠዋል!</translation>
 <translation id="6643016212128521049">አጽዳ</translation>
 <translation id="6650726141019353908">ሮዝ ቢራቢሮ</translation>
-<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
+<translation id="6657585470893396449">የይለፍ ቃል</translation>
 <translation id="6673674183150363784">ፈረንሳይኛ (ፈረንሳይ) በBépo ቁልፍ ሰሌዳ</translation>
 <translation id="6710022688720561421">ሮቦት</translation>
 <translation id="6710213216561001401">ቀዳሚ</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_bn.xtb b/ui/chromeos/translations/ui_chromeos_strings_bn.xtb
index dfbe2c94..5493189 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_bn.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_bn.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">রোমানিয়ান</translation>
 <translation id="4477219268485577442">বুলগেরিয়ান ফনেটিক</translation>
 <translation id="4509667233588080747">ইংরেজি (মার্কিন যুক্তরাষ্ট্র) ভাষায় ওয়ার্কম্যান ইন্টারন্যাশনাল কীবোর্ড</translation>
-<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4522570452068850558">বিবরণগুলি</translation>
 <translation id="4527800702232535228">এই ফোল্ডার Parallels Desktop-এর সাথে শেয়ার করা হয়েছে</translation>
 <translation id="4552678318981539154">আরও সঞ্চয়স্থান কিনুন</translation>
 <translation id="4559318885353833501"><ph name="FILE_NAME" /> মুছে ফেলা হয়েছে</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_el.xtb b/ui/chromeos/translations/ui_chromeos_strings_el.xtb
index 07a8741..e0c34dc 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_el.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_el.xtb
@@ -553,7 +553,7 @@
 <translation id="6629841649550503054">Δημιουργήθηκαν αντίγραφα ασφαλείας για όλα τα αρχεία στο <ph name="BEGIN_LINK" />Google Drive!<ph name="END_LINK" /></translation>
 <translation id="6643016212128521049">Διαγραφή</translation>
 <translation id="6650726141019353908">Ροζ πεταλούδα</translation>
-<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός Πρόσβασης</translation>
 <translation id="6673674183150363784">Γαλλικά (Γαλλίας) με πληκτρολόγιο BÉPO</translation>
 <translation id="6710022688720561421">Ρομπότ</translation>
 <translation id="6710213216561001401">Προηγούμενο</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_hr.xtb b/ui/chromeos/translations/ui_chromeos_strings_hr.xtb
index b4c59a2d..743d7a9 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_hr.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_hr.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">rumunjski</translation>
 <translation id="4477219268485577442">bugarska (fonetska)</translation>
 <translation id="4509667233588080747">engleski (SAD) s međunarodnom Workman tipkovnicom</translation>
-<translation id="4522570452068850558">Detalji</translation>
+<translation id="4522570452068850558">Pojedinosti</translation>
 <translation id="4527800702232535228">Ova se mapa dijeli s Parallels Desktopom</translation>
 <translation id="4552678318981539154">Kupite još prostora za pohranu</translation>
 <translation id="4559318885353833501">Izbrisana je datoteka <ph name="FILE_NAME" /></translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_lv.xtb b/ui/chromeos/translations/ui_chromeos_strings_lv.xtb
index 60e3132..e27c777a 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_lv.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_lv.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">Rumāņu</translation>
 <translation id="4477219268485577442">Bulgāru fonētiskā</translation>
 <translation id="4509667233588080747">Angļu (ASV), ar Workman starptautisko tastatūru</translation>
-<translation id="4522570452068850558">Informācija</translation>
+<translation id="4522570452068850558">Dati</translation>
 <translation id="4527800702232535228">Šī mape ir kopīgota ar Parallels Desktop</translation>
 <translation id="4552678318981539154">Iegādāties papildu vietu krātuvē</translation>
 <translation id="4559318885353833501">Fails <ph name="FILE_NAME" /> ir izdzēsts</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ru.xtb b/ui/chromeos/translations/ui_chromeos_strings_ru.xtb
index 0886948..dba0930 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ru.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ru.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">Румынский</translation>
 <translation id="4477219268485577442">Болгарская (фонетическая)</translation>
 <translation id="4509667233588080747">Английский (США), международная раскладка Workman</translation>
-<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4522570452068850558">Детали</translation>
 <translation id="4527800702232535228">Доступ к этой папке предоставлен Parallels Desktop.</translation>
 <translation id="4552678318981539154">Приобретите дополнительное пространство</translation>
 <translation id="4559318885353833501">Файл "<ph name="FILE_NAME" />" удален.</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
index f979737..d05078d 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_sv.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">rumänska</translation>
 <translation id="4477219268485577442">Bulgariska (fonetiskt)</translation>
 <translation id="4509667233588080747">engelska (USA) med Workman International-tangentbord</translation>
-<translation id="4522570452068850558">Info</translation>
+<translation id="4522570452068850558">Detaljer</translation>
 <translation id="4527800702232535228">Den här mappen delas med Parallels Desktop</translation>
 <translation id="4552678318981539154">Köp mer lagringsutrymme</translation>
 <translation id="4559318885353833501"><ph name="FILE_NAME" /> har raderats</translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
index 4efea8fb..0945d08a8 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-CN.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">罗马尼亚语</translation>
 <translation id="4477219268485577442">保加利亚语(注音)</translation>
 <translation id="4509667233588080747">英语(美国)Workman 国际键盘</translation>
-<translation id="4522570452068850558">详细信息</translation>
+<translation id="4522570452068850558">详情</translation>
 <translation id="4527800702232535228">已与 Parallels Desktop 共享此文件夹</translation>
 <translation id="4552678318981539154">购买更多存储空间</translation>
 <translation id="4559318885353833501">已删除 <ph name="FILE_NAME" /></translation>
diff --git a/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb b/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
index b0074c3..ea7193ec 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_zh-TW.xtb
@@ -317,7 +317,7 @@
 <translation id="4477002475007461989">羅馬尼亞文</translation>
 <translation id="4477219268485577442">保加利亞文 (拼音)</translation>
 <translation id="4509667233588080747">英文 (美國) 搭配 Workman 國際鍵盤</translation>
-<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4522570452068850558">詳細資料</translation>
 <translation id="4527800702232535228">已與 Parallls Desktop 共用這個資料夾</translation>
 <translation id="4552678318981539154">購買更多儲存空間</translation>
 <translation id="4559318885353833501">已刪除「<ph name="FILE_NAME" />」</translation>
diff --git a/ui/file_manager/audio_player/js/BUILD.gn b/ui/file_manager/audio_player/js/BUILD.gn
index 098cce8..ff508f2 100644
--- a/ui/file_manager/audio_player/js/BUILD.gn
+++ b/ui/file_manager/audio_player/js/BUILD.gn
@@ -51,16 +51,6 @@
   ]
 }
 
-js_library("closure_compile_externs") {
-  sources = []
-  externs_list = [
-    "$externs_path/chrome_extensions.js",
-    "$externs_path/mediasession.js",
-    "//ui/file_manager/file_manager/externs/audio_player_foreground.js",
-    "//ui/file_manager/file_manager/externs/platform.js",
-  ]
-}
-
 js_library("audio_player") {
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn
index 26d4d7d..8d2b8ef 100644
--- a/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -98,29 +98,6 @@
       ]
 }
 
-js_library("closure_compile_externs") {
-  sources = []
-  externs_list = [
-    "$externs_path/metrics_private.js",
-    "//ui/file_manager/file_manager/externs/background/crostini.js",
-    "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js",
-    "//ui/file_manager/file_manager/externs/background/background_base.js",
-    "//ui/file_manager/file_manager/externs/background/file_browser_background_full.js",
-    "//ui/file_manager/file_manager/externs/background/file_operation_manager.js",
-    "//ui/file_manager/file_manager/externs/background/import_history.js",
-    "//ui/file_manager/file_manager/externs/background/media_import_handler.js",
-    "//ui/file_manager/file_manager/externs/background/media_scanner.js",
-    "//ui/file_manager/file_manager/externs/background/progress_center.js",
-    "//ui/file_manager/file_manager/externs/background_window.js",
-    "//ui/file_manager/file_manager/externs/css_rule.js",
-    "//ui/file_manager/file_manager/externs/drive_dialog_controller.js",
-    "//ui/file_manager/file_manager/externs/platform.js",
-    "//ui/file_manager/file_manager/externs/progress_center_panel.js",
-    "//ui/file_manager/file_manager/externs/background/task_queue.js",
-    "//ui/file_manager/file_manager/externs/background/duplicate_finder.js",
-  ]
-}
-
 js_library("app_window_wrapper") {
   visibility += related_apps
   deps = [
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 6bbbd7c..442d34365 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -939,10 +939,16 @@
       this.launchParams_ = new LaunchParam(params);
     } else {
       // Used by the select dialog only.
-      const json = location.search ?
-          JSON.parse(decodeURIComponent(location.search.substr(1))) :
-          {};
-      this.launchParams_ = new LaunchParam(json instanceof Object ? json : {});
+      let json = {};
+      if (location.search) {
+        const query = location.search.substr(1);
+        try {
+          json = /** @type {!Object} */ (JSON.parse(decodeURIComponent(query)));
+        } catch (e) {
+          console.debug(`Error parsing location.search "${query}" due to ${e}`);
+        }
+      }
+      this.launchParams_ = new LaunchParam(json);
     }
 
     // Initialize the member variables that depend this.launchParams_.
diff --git a/ui/ozone/demo/software_renderer.cc b/ui/ozone/demo/software_renderer.cc
index 657925a..d3c0c323 100644
--- a/ui/ozone/demo/software_renderer.cc
+++ b/ui/ozone/demo/software_renderer.cc
@@ -45,7 +45,7 @@
     return false;
   }
 
-  software_surface_->ResizeCanvas(size_);
+  software_surface_->ResizeCanvas(size_, 1.f /*scale_factor*/);
   vsync_provider_ = software_surface_->CreateVSyncProvider();
   RenderFrame();
   return true;
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc
index e5520f8..893df4b 100644
--- a/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -28,7 +28,7 @@
   // SurfaceOzoneCanvas implementation:
   SkCanvas* GetCanvas() override { return surface_->getCanvas(); }
 
-  void ResizeCanvas(const gfx::Size& viewport_size) override {
+  void ResizeCanvas(const gfx::Size& viewport_size, float scale) override {
     surface_ =
         SkSurface::MakeNull(viewport_size.width(), viewport_size.height());
   }
diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc
index afcfed9..981e76a 100644
--- a/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -73,7 +73,7 @@
   ~FileSurface() override {}
 
   // SurfaceOzoneCanvas overrides:
-  void ResizeCanvas(const gfx::Size& viewport_size) override {
+  void ResizeCanvas(const gfx::Size& viewport_size, float scale) override {
     SkSurfaceProps props = skia::LegacyDisplayGlobals::GetSkSurfaceProps();
     surface_ = SkSurface::MakeRaster(
         SkImageInfo::MakeN32Premul(viewport_size.width(),
diff --git a/ui/ozone/platform/scenic/scenic_window_canvas.cc b/ui/ozone/platform/scenic/scenic_window_canvas.cc
index 01dedec6..7f5f9edd 100644
--- a/ui/ozone/platform/scenic/scenic_window_canvas.cc
+++ b/ui/ozone/platform/scenic/scenic_window_canvas.cc
@@ -75,7 +75,8 @@
 
 ScenicWindowCanvas::~ScenicWindowCanvas() = default;
 
-void ScenicWindowCanvas::ResizeCanvas(const gfx::Size& viewport_size) {
+void ScenicWindowCanvas::ResizeCanvas(const gfx::Size& viewport_size,
+                                      float scale) {
   viewport_size_ = viewport_size;
   viewport_size_.SetToMax(gfx::Size(1, 1));
 
diff --git a/ui/ozone/platform/scenic/scenic_window_canvas.h b/ui/ozone/platform/scenic/scenic_window_canvas.h
index 85871172..a7f3939 100644
--- a/ui/ozone/platform/scenic/scenic_window_canvas.h
+++ b/ui/ozone/platform/scenic/scenic_window_canvas.h
@@ -37,7 +37,7 @@
   ~ScenicWindowCanvas() override;
 
   // SurfaceOzoneCanvas implementation.
-  void ResizeCanvas(const gfx::Size& viewport_size) override;
+  void ResizeCanvas(const gfx::Size& viewport_size, float scale) override;
   SkCanvas* GetCanvas() override;
   void PresentCanvas(const gfx::Rect& damage) override;
   std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 0368a75..98c74c3e 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -172,6 +172,8 @@
     configs += [ "//ui/events/ozone/layout:xkbcommon" ]
   }
 
+  defines = [ "OZONE_IMPLEMENTATION" ]
+
   deps = [
     "//base",
     "//build:chromeos_buildflags",
@@ -226,6 +228,15 @@
     "//ui/platform_window/wm",
   ]
 
+  if (use_dbus) {
+    sources += [
+      "host/org_gnome_mutter_idle_monitor.cc",
+      "host/org_gnome_mutter_idle_monitor.h",
+    ]
+    deps += [ "//dbus" ]
+    defines += [ "USE_DBUS" ]
+  }
+
   if (use_gtk) {
     sources += [
       "host/linux_ui_delegate_wayland.cc",
@@ -248,8 +259,6 @@
     ]
   }
 
-  defines = [ "OZONE_IMPLEMENTATION" ]
-
   if (use_system_libwayland) {
     defines += [ "USE_LIBWAYLAND_STUBS" ]
     deps += [ "//third_party/wayland:wayland_stubs" ]
diff --git a/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc b/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
index 182ded3..a03ed59 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
@@ -207,7 +207,8 @@
   return pending_buffer_->sk_surface()->getCanvas();
 }
 
-void WaylandCanvasSurface::ResizeCanvas(const gfx::Size& viewport_size) {
+void WaylandCanvasSurface::ResizeCanvas(const gfx::Size& viewport_size,
+                                        float scale) {
   if (size_ == viewport_size)
     return;
   // TODO(https://crbug.com/930667): We could implement more efficient resizes
@@ -220,6 +221,7 @@
   pending_buffer_ = nullptr;
   unsubmitted_buffers_.clear();
   size_ = viewport_size;
+  viewport_scale_ = std::ceil(scale);
 }
 
 void WaylandCanvasSurface::PresentCanvas(const gfx::Rect& damage) {
diff --git a/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h b/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
index 6da6c52..34b28c4 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
@@ -50,7 +50,7 @@
   // GetCanvas() returns an SkCanvas whose shared memory region is not being
   // used by Wayland. If no such SkCanvas is available, a new one is created.
   SkCanvas* GetCanvas() override;
-  void ResizeCanvas(const gfx::Size& viewport_size) override;
+  void ResizeCanvas(const gfx::Size& viewport_size, float scale) override;
   void PresentCanvas(const gfx::Rect& damage) override;
   std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
 
@@ -76,6 +76,7 @@
   const gfx::AcceleratedWidget widget_;
 
   gfx::Size size_;
+  int32_t viewport_scale_ = 1;
   std::vector<std::unique_ptr<SharedMemoryBuffer>> buffers_;
 
   // Contains pending to be submitted buffers. The vector is processed as FIFO.
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index 0567e79..fcd475e7 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -706,30 +706,40 @@
 }
 
 TEST_P(WaylandSurfaceFactoryTest, Canvas) {
-  auto canvas = CreateCanvas(widget_);
-  ASSERT_TRUE(canvas);
+  const std::vector<float> scale_factors = {1, 1.2, 1.3, 1.5, 1.7, 2, 2.3, 2.8};
+  for (auto scale_factor : scale_factors) {
+    auto canvas = CreateCanvas(widget_);
+    ASSERT_TRUE(canvas);
 
-  canvas->ResizeCanvas(window_->GetBounds().size());
-  auto* sk_canvas = canvas->GetCanvas();
-  DCHECK(sk_canvas);
-  canvas->PresentCanvas(gfx::Rect(5, 10, 20, 15));
+    auto bounds_px = window_->GetBounds();
+    bounds_px = gfx::ScaleToRoundedRect(bounds_px, scale_factor);
 
-  // Wait until the mojo calls are done.
-  base::RunLoop().RunUntilIdle();
+    canvas->ResizeCanvas(bounds_px.size(), scale_factor);
+    auto* sk_canvas = canvas->GetCanvas();
+    DCHECK(sk_canvas);
+    canvas->PresentCanvas(gfx::Rect(5, 10, 20, 15));
 
-  Expectation damage = EXPECT_CALL(*surface_, DamageBuffer(5, 10, 20, 15));
-  wl_resource* buffer_resource = nullptr;
-  Expectation attach = EXPECT_CALL(*surface_, Attach(_, 0, 0))
-                           .WillOnce(SaveArg<0>(&buffer_resource));
-  EXPECT_CALL(*surface_, Commit()).After(damage, attach);
+    // Wait until the mojo calls are done.
+    base::RunLoop().RunUntilIdle();
 
-  Sync();
+    Expectation damage = EXPECT_CALL(*surface_, DamageBuffer(5, 10, 20, 15));
+    wl_resource* buffer_resource = nullptr;
+    Expectation attach = EXPECT_CALL(*surface_, Attach(_, 0, 0))
+                             .WillOnce(SaveArg<0>(&buffer_resource));
+    EXPECT_CALL(*surface_, Commit()).After(damage, attach);
 
-  ASSERT_TRUE(buffer_resource);
-  wl_shm_buffer* buffer = wl_shm_buffer_get(buffer_resource);
-  ASSERT_TRUE(buffer);
-  EXPECT_EQ(wl_shm_buffer_get_width(buffer), 800);
-  EXPECT_EQ(wl_shm_buffer_get_height(buffer), 600);
+    Sync();
+
+    ASSERT_TRUE(buffer_resource);
+    wl_shm_buffer* buffer = wl_shm_buffer_get(buffer_resource);
+    ASSERT_TRUE(buffer);
+    EXPECT_EQ(wl_shm_buffer_get_width(buffer), bounds_px.width());
+    EXPECT_EQ(wl_shm_buffer_get_height(buffer), bounds_px.height());
+
+    surface_->SendFrameCallback();
+
+    Sync();
+  }
 
   // TODO(forney): We could check that the contents match something drawn to the
   // SkSurface above.
@@ -739,10 +749,10 @@
   auto canvas = CreateCanvas(widget_);
   ASSERT_TRUE(canvas);
 
-  canvas->ResizeCanvas(window_->GetBounds().size());
+  canvas->ResizeCanvas(window_->GetBounds().size(), 1);
   auto* sk_canvas = canvas->GetCanvas();
   DCHECK(sk_canvas);
-  canvas->ResizeCanvas(gfx::Size(100, 50));
+  canvas->ResizeCanvas(gfx::Size(100, 50), 1);
   sk_canvas = canvas->GetCanvas();
   DCHECK(sk_canvas);
   canvas->PresentCanvas(gfx::Rect(0, 0, 100, 50));
diff --git a/ui/ozone/platform/wayland/host/DEPS b/ui/ozone/platform/wayland/host/DEPS
index 8f2915a..9a051c04 100644
--- a/ui/ozone/platform/wayland/host/DEPS
+++ b/ui/ozone/platform/wayland/host/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+dbus",
   # For Lacros.
   "+chromeos/crosapi/mojom",
   "+chromeos/crosapi/cpp/crosapi_constants.h",
diff --git a/ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.cc b/ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.cc
new file mode 100644
index 0000000..75dda521
--- /dev/null
+++ b/ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.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 "ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.h"
+
+#include "base/logging.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/task_runner.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_path.h"
+#include "dbus/object_proxy.h"
+
+namespace ui {
+
+namespace {
+
+// After the system has gone idle, the D-Bus service will wait for this time
+// before notifying us.  This reduces "jitter" of the idle/active state, but
+// also adds some lag in responsiveness: when we are finally notified that the
+// idle state has come, it is already there for kIdleThresholdMs milliseconds.
+constexpr uint64_t kIdleThresholdMs = 5000;
+
+constexpr char kInterface[] = "org.gnome.Mutter.IdleMonitor";
+constexpr char kObjectPath[] = "/org/gnome/Mutter/IdleMonitor/Core";
+
+constexpr char kMethodAddIdleWatch[] = "AddIdleWatch";
+constexpr char kMethodAddUserActiveWatch[] = "AddUserActiveWatch";
+constexpr char kMethodGetIdletime[] = "GetIdletime";
+constexpr char kSignalWatchFired[] = "WatchFired";
+
+}  // namespace
+
+OrgGnomeMutterIdleMonitor::OrgGnomeMutterIdleMonitor()
+    : task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+          base::TaskTraits(base::MayBlock(),
+                           base::TaskPriority::USER_VISIBLE,
+                           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN))) {
+  dbus::Bus::Options options;
+  options.bus_type = dbus::Bus::SESSION;
+  options.connection_type = dbus::Bus::PRIVATE;
+  options.dbus_task_runner = task_runner_;
+  bus_ = base::MakeRefCounted<dbus::Bus>(options);
+}
+
+OrgGnomeMutterIdleMonitor::~OrgGnomeMutterIdleMonitor() = default;
+
+absl::optional<base::TimeDelta> OrgGnomeMutterIdleMonitor::GetIdleTime() const {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  switch (service_state_) {
+    case ServiceState::kUnknown:
+      service_state_ = ServiceState::kInitializing;
+      {
+        dbus::ObjectProxy* dbus_proxy = bus_->GetObjectProxy(
+            DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS));
+        dbus::MethodCall name_has_owner_call(DBUS_INTERFACE_DBUS,
+                                             "NameHasOwner");
+        dbus::MessageWriter writer(&name_has_owner_call);
+        writer.AppendString(kInterface);
+        dbus_proxy->CallMethod(
+            &name_has_owner_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+            base::BindOnce(&OrgGnomeMutterIdleMonitor::OnServiceHasOwner,
+                           weak_factory_.GetWeakPtr()));
+      }
+      return base::TimeDelta::FromSeconds(0);
+
+    case ServiceState::kInitializing:
+      return base::TimeDelta::FromSeconds(0);
+
+    case ServiceState::kWorking:
+      if (idle_timestamp_.is_null())
+        return base::TimeDelta::FromSeconds(0);
+      return base::Time::Now() - idle_timestamp_;
+
+    case ServiceState::kNotAvailable:
+      return absl::nullopt;
+
+    default:
+      NOTREACHED();
+      return absl::nullopt;
+  }
+}
+
+void OrgGnomeMutterIdleMonitor::OnServiceHasOwner(dbus::Response* response) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  dbus::MessageReader reader(response);
+  bool owned = false;
+  if (!response || !reader.PopBool(&owned) || !owned) {
+    // Calling methods on a non-existent service will lead to a timeout rather
+    // than an immediate error, so check for service existence first.
+    LOG(WARNING) << kInterface << " D-Bus service does not exist";
+    return Shutdown();
+  }
+
+  proxy_ = bus_->GetObjectProxy(kInterface, dbus::ObjectPath(kObjectPath));
+
+  // Connect the WatchFired signal.
+  proxy_->ConnectToSignal(
+      kInterface, kSignalWatchFired,
+      base::BindRepeating(&OrgGnomeMutterIdleMonitor::OnWatchFired,
+                          weak_factory_.GetWeakPtr()),
+      base::BindOnce(&OrgGnomeMutterIdleMonitor::OnWatchFiredSignalConnected,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void OrgGnomeMutterIdleMonitor::OnWatchFiredSignalConnected(
+    const std::string& interface,
+    const std::string& signal,
+    bool succeeded) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  DCHECK_EQ(interface, kInterface);
+  DCHECK_EQ(signal, kSignalWatchFired);
+
+  if (!succeeded) {
+    LOG(WARNING) << "Cannot connect to " << kSignalWatchFired << " signal of "
+                 << kInterface << " D-Bus service";
+    return Shutdown();
+  }
+
+  // Add the Idle watch.
+  dbus::MethodCall call(kInterface, kMethodAddIdleWatch);
+  dbus::MessageWriter writer(&call);
+  writer.AppendUint64(kIdleThresholdMs);
+  proxy_->CallMethod(&call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                     base::BindOnce(&OrgGnomeMutterIdleMonitor::OnAddIdleWatch,
+                                    weak_factory_.GetWeakPtr()));
+}
+
+void OrgGnomeMutterIdleMonitor::OnAddIdleWatch(dbus::Response* response) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  if (!response || !ReadWatchId(response, &idle_watch_id_)) {
+    LOG(WARNING) << "Call to " << kMethodAddIdleWatch << " method of "
+                 << kInterface << " D-Bus service failed";
+    return Shutdown();
+  }
+
+  // Add the User Active watch.
+  dbus::MethodCall call(kInterface, kMethodAddUserActiveWatch);
+  proxy_->CallMethod(
+      &call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+      base::BindOnce(&OrgGnomeMutterIdleMonitor::OnAddUserActiveWatch,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void OrgGnomeMutterIdleMonitor::OnAddUserActiveWatch(dbus::Response* response) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  if (!response || !ReadWatchId(response, &active_watch_id_)) {
+    LOG(WARNING) << "Call to " << kMethodAddUserActiveWatch << " method of "
+                 << kInterface << " D-Bus service failed";
+    return Shutdown();
+  }
+
+  if (service_state_ == ServiceState::kInitializing) {
+    // If we are still initialising, request the current idle time to have the
+    // correct initial idle time.
+    dbus::MethodCall call(kInterface, kMethodGetIdletime);
+    proxy_->CallMethod(&call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                       base::BindOnce(&OrgGnomeMutterIdleMonitor::OnGetIdletime,
+                                      weak_factory_.GetWeakPtr()));
+  }
+}
+
+void OrgGnomeMutterIdleMonitor::OnGetIdletime(dbus::Response* response) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  if (!response || !UpdateIdleTime(response)) {
+    LOG(WARNING) << "Call to " << kMethodGetIdletime << " method of "
+                 << kInterface << " D-Bus service failed";
+    return Shutdown();
+  }
+
+  // Successfully initialised.
+  service_state_ = ServiceState::kWorking;
+}
+
+void OrgGnomeMutterIdleMonitor::OnWatchFired(dbus::Signal* signal) {
+  DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
+
+  DCHECK(signal);
+
+  dbus::MessageReader reader(signal);
+  uint32_t id;
+  if (!reader.PopUint32(&id) || reader.HasMoreData()) {
+    LOG(WARNING) << "Invalid signal received (unexpected payload)";
+    return Shutdown();
+  }
+
+  if (id == idle_watch_id_) {
+    idle_timestamp_ =
+        base::Time::Now() - base::TimeDelta::FromMilliseconds(kIdleThresholdMs);
+    dbus::MethodCall call(kInterface, kMethodAddUserActiveWatch);
+    proxy_->CallMethod(
+        &call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&OrgGnomeMutterIdleMonitor::OnAddUserActiveWatch,
+                       weak_factory_.GetWeakPtr()));
+  } else if (id == active_watch_id_) {
+    idle_timestamp_ = base::Time{};
+  }
+}
+
+bool OrgGnomeMutterIdleMonitor::UpdateIdleTime(dbus::Message* message) {
+  if (!message)
+    return false;
+
+  dbus::MessageReader reader(message);
+  uint64_t idletime;
+  if (!reader.PopUint64(&idletime) || reader.HasMoreData())
+    return false;
+  idle_timestamp_ =
+      base::Time::Now() - base::TimeDelta::FromMilliseconds(idletime);
+  return true;
+}
+
+bool OrgGnomeMutterIdleMonitor::ReadWatchId(dbus::Message* message,
+                                            uint32_t* watch_id) {
+  if (!message)
+    return false;
+
+  DCHECK(watch_id);
+
+  dbus::MessageReader reader(message);
+  return (reader.PopUint32(watch_id) && !reader.HasMoreData());
+}
+
+void OrgGnomeMutterIdleMonitor::Shutdown() {
+  idle_timestamp_ = base::Time{};
+  service_state_ = ServiceState::kNotAvailable;
+}
+
+}  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.h b/ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.h
new file mode 100644
index 0000000..087efe4f
--- /dev/null
+++ b/ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.h
@@ -0,0 +1,86 @@
+// 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 UI_OZONE_PLATFORM_WAYLAND_HOST_ORG_GNOME_MUTTER_IDLE_MONITOR_H_
+#define UI_OZONE_PLATFORM_WAYLAND_HOST_ORG_GNOME_MUTTER_IDLE_MONITOR_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace dbus {
+class Bus;
+class Message;
+class ObjectProxy;
+class Response;
+class Signal;
+}  // namespace dbus
+
+namespace ui {
+
+// Wraps org.gnome.Mutter.IdleMonitor D-Bus system service.
+class OrgGnomeMutterIdleMonitor {
+ public:
+  OrgGnomeMutterIdleMonitor();
+  ~OrgGnomeMutterIdleMonitor();
+
+  // Returns the idle time.
+  //
+  // If called on the instance that is off, will return 0.
+  absl::optional<base::TimeDelta> GetIdleTime() const;
+
+ private:
+  enum class ServiceState {
+    kUnknown,
+    kInitializing,
+    kWorking,
+    kNotAvailable,
+  };
+
+  // Five On... methods below are called in chain, one after another, in the
+  // initialisation sequence.  Error at any step stops the initialisation and
+  // puts the instance into disabled state.
+  void OnServiceHasOwner(dbus::Response* response);
+  void OnWatchFiredSignalConnected(const std::string& interface,
+                                   const std::string& signal,
+                                   bool succeeded);
+  void OnAddIdleWatch(dbus::Response* response);
+  void OnAddUserActiveWatch(dbus::Response* response);
+  void OnGetIdletime(dbus::Response* response);
+
+  // Called back by the D-Bus service in two cases:
+  // 1) Some time after the system entered the idle state.
+  // 2) After the system exited the idle state.
+  void OnWatchFired(dbus::Signal* signal);
+
+  // Readers that unpack data from incoming messages.
+  bool UpdateIdleTime(dbus::Message* message);
+  bool ReadWatchId(dbus::Message* message, uint32_t* watch_id);
+
+  // Puts the instance into state of terminal unavailability so it no longer
+  // interacts with the D-Bus service and returns default zero idle time.
+  void Shutdown();
+
+  // Current state of the instance.
+  mutable ServiceState service_state_{ServiceState::kUnknown};
+  // Time when the system went into idle state.
+  base::Time idle_timestamp_;
+
+  uint32_t idle_watch_id_ = 0;
+  uint32_t active_watch_id_ = 0;
+
+  scoped_refptr<dbus::Bus> bus_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  dbus::ObjectProxy* proxy_ = nullptr;
+
+  THREAD_CHECKER(main_thread_checker_);
+
+  base::WeakPtrFactory<OrgGnomeMutterIdleMonitor> weak_factory_{this};
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_PLATFORM_WAYLAND_HOST_ORG_GNOME_MUTTER_IDLE_MONITOR_H_
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc
index 73dc463..238ed43 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen.cc
+++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -24,6 +24,10 @@
 #include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
 #include "ui/ozone/platform/wayland/host/wayland_window.h"
 
+#if defined(USE_DBUS)
+#include "ui/ozone/platform/wayland/host/org_gnome_mutter_idle_monitor.h"
+#endif
+
 namespace ui {
 
 WaylandScreen::WaylandScreen(WaylandConnection* connection)
@@ -241,6 +245,24 @@
   return display_matching ? *display_matching : GetPrimaryDisplay();
 }
 
+base::TimeDelta WaylandScreen::CalculateIdleTime() const {
+#if defined(USE_DBUS)
+  // Try the org.gnome.Mutter.IdleMonitor D-Bus service (Mutter).
+  if (!org_gnome_mutter_idle_monitor_)
+    org_gnome_mutter_idle_monitor_ =
+        std::make_unique<OrgGnomeMutterIdleMonitor>();
+  const auto idle_time = org_gnome_mutter_idle_monitor_->GetIdleTime();
+  if (idle_time)
+    return *idle_time;
+#endif  // defined(USE_DBUS)
+
+  // Try the org_kde_kwin_idle Wayland protocol extension (KWin).
+  NOTIMPLEMENTED_LOG_ONCE();
+
+  // No providers.  Return 0 which means the system never gets idle.
+  return base::TimeDelta::FromSeconds(0);
+}
+
 void WaylandScreen::AddObserver(display::DisplayObserver* observer) {
   display_list_.AddObserver(observer);
 }
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.h b/ui/ozone/platform/wayland/host/wayland_screen.h
index fb9a8765..ccd5254c 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen.h
+++ b/ui/ozone/platform/wayland/host/wayland_screen.h
@@ -26,6 +26,10 @@
 
 class WaylandConnection;
 
+#if defined(USE_DBUS)
+class OrgGnomeMutterIdleMonitor;
+#endif
+
 // A PlatformScreen implementation for Wayland.
 class WaylandScreen : public PlatformScreen {
  public:
@@ -58,6 +62,7 @@
       const gfx::Point& point) const override;
   display::Display GetDisplayMatching(
       const gfx::Rect& match_rect) const override;
+  base::TimeDelta CalculateIdleTime() const override;
   void AddObserver(display::DisplayObserver* observer) override;
   void RemoveObserver(display::DisplayObserver* observer) override;
   base::Value GetGpuExtraInfoAsListValue(
@@ -77,6 +82,11 @@
   absl::optional<gfx::BufferFormat> image_format_alpha_;
   absl::optional<gfx::BufferFormat> image_format_no_alpha_;
 
+#if defined(USE_DBUS)
+  mutable std::unique_ptr<OrgGnomeMutterIdleMonitor>
+      org_gnome_mutter_idle_monitor_;
+#endif
+
   base::WeakPtrFactory<WaylandScreen> weak_factory_;
 };
 
diff --git a/ui/ozone/platform/x11/x11_canvas_surface.cc b/ui/ozone/platform/x11/x11_canvas_surface.cc
index d449135..8292952 100644
--- a/ui/ozone/platform/x11/x11_canvas_surface.cc
+++ b/ui/ozone/platform/x11/x11_canvas_surface.cc
@@ -23,7 +23,8 @@
   return x11_software_bitmap_presenter_.GetSkCanvas();
 }
 
-void X11CanvasSurface::ResizeCanvas(const gfx::Size& viewport_size) {
+void X11CanvasSurface::ResizeCanvas(const gfx::Size& viewport_size,
+                                    float scale) {
   x11_software_bitmap_presenter_.Resize(viewport_size);
 }
 
diff --git a/ui/ozone/platform/x11/x11_canvas_surface.h b/ui/ozone/platform/x11/x11_canvas_surface.h
index 72a4181..5310f1b 100644
--- a/ui/ozone/platform/x11/x11_canvas_surface.h
+++ b/ui/ozone/platform/x11/x11_canvas_surface.h
@@ -33,7 +33,7 @@
 
   // SurfaceOzoneCanvas overrides:
   SkCanvas* GetCanvas() override;
-  void ResizeCanvas(const gfx::Size& viewport_size) override;
+  void ResizeCanvas(const gfx::Size& viewport_size, float scale) override;
   void PresentCanvas(const gfx::Rect& damage) override;
   std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
   bool SupportsAsyncBufferSwap() const override;
diff --git a/ui/ozone/public/surface_ozone_canvas.h b/ui/ozone/public/surface_ozone_canvas.h
index 7e4143b1..0adced8b 100644
--- a/ui/ozone/public/surface_ozone_canvas.h
+++ b/ui/ozone/public/surface_ozone_canvas.h
@@ -38,7 +38,9 @@
   // Attempts to resize the canvas to match the viewport size. After
   // resizing, the compositor must call GetSurface() to get the next
   // surface - this invalidates any previous surface from GetSurface().
-  virtual void ResizeCanvas(const gfx::Size& viewport_size) = 0;
+  // |viewport_size| is the size of viewport in pixels that is the multiple
+  // of a size in screen dips * |scale|.
+  virtual void ResizeCanvas(const gfx::Size& viewport_size, float scale) = 0;
 
   // Present the current surface. After presenting, the compositor must
   // call GetSurface() to get the next surface - this invalidates any
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd
index 89e1df17..6920f14 100644
--- a/ui/strings/ui_strings.grd
+++ b/ui/strings/ui_strings.grd
@@ -536,6 +536,9 @@
       <message name="IDS_APP_ACCNAME_BACK" desc="The accessible name for the back button on the window frame.">
         Back button
       </message>
+      <message name="IDS_APP_ACCNAME_CENTER" desc="The accessible name for the center button on the window frame.">
+        Center button
+      </message>
       <message name="IDS_APP_ACCNAME_CLOSE" desc="The accessible name for the Close button.">
         Close
       </message>
diff --git a/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_CENTER.png.sha1 b/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_CENTER.png.sha1
new file mode 100644
index 0000000..c006112
--- /dev/null
+++ b/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_CENTER.png.sha1
@@ -0,0 +1 @@
+971bdb8b28a84becadb3367d9aec1a18c98e5619
\ No newline at end of file
diff --git a/ui/views/window/caption_button_types.h b/ui/views/window/caption_button_types.h
index 12b41c0..dba416a 100644
--- a/ui/views/window/caption_button_types.h
+++ b/ui/views/window/caption_button_types.h
@@ -19,6 +19,7 @@
   CAPTION_BUTTON_ICON_LOCATION,
   CAPTION_BUTTON_ICON_MENU,
   CAPTION_BUTTON_ICON_ZOOM,
+  CAPTION_BUTTON_ICON_CENTER,
   CAPTION_BUTTON_ICON_COUNT
 };
 
diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc
index 9f05cd1..6c10aa98 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -206,6 +206,8 @@
   if (icon_definition_)
     SetImage(icon_, Animate::kNo, *icon_definition_);
   UpdateInkDropBaseColor();
+
+  OnPropertyChanged(&background_color_, kPropertyEffectsPaint);
 }
 
 SkColor FrameCaptionButton::GetBackgroundColor() const {
@@ -223,6 +225,12 @@
   return ink_drop_corner_radius_;
 }
 
+base::CallbackListSubscription
+FrameCaptionButton::AddBackgroundColorChangedCallback(
+    PropertyChangedCallback callback) {
+  return AddPropertyChangedCallback(&background_color_, callback);
+}
+
 void FrameCaptionButton::SetPaintAsActive(bool paint_as_active) {
   if (paint_as_active == paint_as_active_)
     return;
@@ -234,6 +242,24 @@
   return paint_as_active_;
 }
 
+void FrameCaptionButton::DrawHighlight(gfx::Canvas* canvas,
+                                       cc::PaintFlags flags) {
+  const gfx::Point center(GetMirroredRect(GetContentsBounds()).CenterPoint());
+  canvas->DrawCircle(center, ink_drop_corner_radius_, flags);
+}
+
+void FrameCaptionButton::DrawIconContents(gfx::Canvas* canvas,
+                                          gfx::ImageSkia image,
+                                          int x,
+                                          int y,
+                                          cc::PaintFlags flags) {
+  canvas->DrawImageInt(image, x, y, flags);
+}
+
+gfx::Size FrameCaptionButton::GetInkDropSize() const {
+  return gfx::Size(2 * GetInkDropCornerRadius(), 2 * GetInkDropCornerRadius());
+}
+
 void FrameCaptionButton::PaintButtonContents(gfx::Canvas* canvas) {
   constexpr SkAlpha kHighlightVisibleOpacity = 0x14;
   SkAlpha highlight_alpha = SK_AlphaTRANSPARENT;
@@ -255,8 +281,7 @@
     cc::PaintFlags flags;
     flags.setColor(ink_drop()->GetBaseColor());
     flags.setAlpha(highlight_alpha);
-    const gfx::Point center(GetMirroredRect(GetContentsBounds()).CenterPoint());
-    canvas->DrawCircle(center, ink_drop_corner_radius_, flags);
+    DrawHighlight(canvas, flags);
   }
 
   int icon_alpha = swap_images_animation_->CurrentValueBetween(0, 255);
@@ -271,21 +296,21 @@
     canvas->SaveLayerAlpha(GetAlphaForIcon(alpha_));
     cc::PaintFlags flags;
     flags.setAlpha(icon_alpha);
-    canvas->DrawImageInt(icon_image_, centered_origin_x, centered_origin_y,
-                         flags);
+    DrawIconContents(canvas, icon_image_, centered_origin_x, centered_origin_y,
+                     flags);
 
     flags.setAlpha(crossfade_icon_alpha);
     flags.setBlendMode(SkBlendMode::kPlus);
-    canvas->DrawImageInt(crossfade_icon_image_, centered_origin_x,
-                         centered_origin_y, flags);
+    DrawIconContents(canvas, crossfade_icon_image_, centered_origin_x,
+                     centered_origin_y, flags);
     canvas->Restore();
   } else {
     if (!swap_images_animation_->is_animating())
       icon_alpha = alpha_;
     cc::PaintFlags flags;
     flags.setAlpha(GetAlphaForIcon(icon_alpha));
-    canvas->DrawImageInt(icon_image_, centered_origin_x, centered_origin_y,
-                         flags);
+    DrawIconContents(canvas, icon_image_, centered_origin_x, centered_origin_y,
+                     flags);
   }
 }
 
@@ -310,11 +335,8 @@
 
 gfx::Insets FrameCaptionButton::GetInkdropInsets(
     const gfx::Size& button_size) const {
-  const gfx::Size kInkDropHighlightSize{2 * ink_drop_corner_radius_,
-                                        2 * ink_drop_corner_radius_};
-  return gfx::Insets(
-      (button_size.height() - kInkDropHighlightSize.height()) / 2,
-      (button_size.width() - kInkDropHighlightSize.width()) / 2);
+  return gfx::Insets((button_size.height() - GetInkDropSize().height()) / 2,
+                     (button_size.width() - GetInkDropSize().width()) / 2);
 }
 
 void FrameCaptionButton::UpdateInkDropBaseColor() {
@@ -360,6 +382,7 @@
      u"CAPTION_BUTTON_ICON_MENU"},
     {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_ZOOM,
      u"CAPTION_BUTTON_ICON_ZOOM"},
+    {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_CENTER,
+     u"CAPTION_BUTTON_ICON_CENTER"},
     {views::CaptionButtonIcon::CAPTION_BUTTON_ICON_COUNT,
      u"CAPTION_BUTTON_ICON_COUNT"})
-
diff --git a/ui/views/window/frame_caption_button.h b/ui/views/window/frame_caption_button.h
index 2c9d7b5..0311a02 100644
--- a/ui/views/window/frame_caption_button.h
+++ b/ui/views/window/frame_caption_button.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/callback_list.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image_skia.h"
@@ -70,6 +71,9 @@
   void SetInkDropCornerRadius(int ink_drop_corner_radius);
   int GetInkDropCornerRadius() const;
 
+  base::CallbackListSubscription AddBackgroundColorChangedCallback(
+      PropertyChangedCallback callback);
+
   CaptionButtonIcon GetIcon() const { return icon_; }
 
   const gfx::ImageSkia& icon_image() const { return icon_image_; }
@@ -82,6 +86,15 @@
   // views::Button override:
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
+  virtual void DrawHighlight(gfx::Canvas* canvas, cc::PaintFlags flags);
+  virtual void DrawIconContents(gfx::Canvas* canvas,
+                                gfx::ImageSkia image,
+                                int x,
+                                int y,
+                                cc::PaintFlags flags);
+  // Returns the size of the inkdrop ripple.
+  virtual gfx::Size GetInkDropSize() const;
+
  private:
   class HighlightPathGenerator;
 
@@ -90,8 +103,8 @@
   int GetAlphaForIcon(int base_alpha) const;
 
   // Returns the amount by which the inkdrop ripple and mask should be insetted
-  // from the button size in order to achieve a circular inkdrop with a size
-  // equals to kInkDropHighlightSize.
+  // from the button size in order to draw the inkdrop with a size returned by
+  // GetInkDropSize().
   gfx::Insets GetInkdropInsets(const gfx::Size& button_size) const;
 
   void UpdateInkDropBaseColor();
diff --git a/weblayer/shell/android/shell_apk/AndroidManifest.xml b/weblayer/shell/android/shell_apk/AndroidManifest.xml
index 8b47b41..a7734e0 100644
--- a/weblayer/shell/android/shell_apk/AndroidManifest.xml
+++ b/weblayer/shell/android/shell_apk/AndroidManifest.xml
@@ -7,7 +7,6 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
     package="org.chromium.weblayer.shell">
 
     <application android:label="WebLayer shell"
@@ -64,14 +63,6 @@
       <meta-data
           android:name="org.chromium.weblayer.ENABLE_LOGGING_OF_JS_CONSOLE_MESSAGES" android:value="true"/>
 
-      <!-- Disables at startup init of Emoji2. See http://crbug.com/1205141 -->
-      <provider
-          android:authorities="org.chromium.weblayer.shell.androidx-startup"
-          android:name="androidx.startup.InitializationProvider"
-          android:exported="false"
-          tools:node="remove">
-      </provider>
-
       {% if weblayer_package is defined %}
             <meta-data android:name="org.chromium.weblayer.WebLayerPackage"
                        android:value="{{ weblayer_package }}"/>