diff --git a/DEPS b/DEPS
index 0a86db3..273600e 100644
--- a/DEPS
+++ b/DEPS
@@ -181,11 +181,11 @@
   # 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': 'edae1b3e044e5755a7b05a9776525fc6a00f0f7b',
+  'skia_revision': '12b2c270383875438a06c0a51140ee3dd0e9bac9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '3d04bd15b02d40f716b49dbb1cb97bb13c40741a',
+  'v8_revision': 'bffadc06da505a4107e53211321f677893ab8a21',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -193,11 +193,11 @@
   # 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': '54d0d539593317eee954eaec1b4aca003032a360',
+  'angle_revision': '683dd1d6a8631e6969918bfca777af7c8f0d74c4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '488d35ac0b1c66c79a6a8511111ad5b6296a2ffb',
+  'swiftshader_revision': '9f1e03b61de8e67e1bce5b0dd25c5a7f54fb1e3e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -244,7 +244,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '25614ff33a6262865cd487ca40ddab809bf9b681',
+  'catapult_revision': '13d8a54a705c1571819c1064380443048a0b79f0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -316,7 +316,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.
-  'quiche_revision': '1378a942692b9e6ff35b29198e0b18c6269f5b17',
+  'quiche_revision': '1f4fe2d7c33b70394c99e540d00d1e309147e982',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -879,7 +879,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '57766ec208686ea167d4930d7accffa49da6dde5',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '872b953d195526ed6bad0fe37bb67bcead9b8a4d',
       'condition': 'checkout_linux',
   },
 
@@ -1297,7 +1297,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'eac62c294ee1c23bc76059efaf8e16859ed58866',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f2839ae905e755f34be2de89f7c20ffb586c9b67',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
diff --git a/android_webview/browser/aw_contents_io_thread_client.cc b/android_webview/browser/aw_contents_io_thread_client.cc
index 65a5a00..c14ed8c 100644
--- a/android_webview/browser/aw_contents_io_thread_client.cc
+++ b/android_webview/browser/aw_contents_io_thread_client.cc
@@ -344,7 +344,7 @@
 // Used to specify what kind of url was intercepted by the embedded
 // using shouldIntercepterRequest callback.
 // Note: these values are persisted in UMA logs, so they should never be
-// renumbered nor reused.
+// renumbered or reused.
 enum class InterceptionType {
   kNoIntercept,
   kOther,
diff --git a/android_webview/browser/gfx/browser_view_renderer_unittest.cc b/android_webview/browser/gfx/browser_view_renderer_unittest.cc
index a3242fd..fa79552 100644
--- a/android_webview/browser/gfx/browser_view_renderer_unittest.cc
+++ b/android_webview/browser/gfx/browser_view_renderer_unittest.cc
@@ -679,7 +679,7 @@
     gfx::Vector2dF total_scroll_offset = kTotalScrollOffset;
     gfx::Vector2dF total_max_scroll_offset = kTotalMaxScrollOffset;
     gfx::SizeF scrollable_size = kScrollableSize;
-    // When --use-zoom-for-dsf is enabled, these value are in physical pixel.
+    // When --use-zoom-for-dsf is enabled, these values are in physical pixels.
     if (content::IsUseZoomForDSFEnabled()) {
       total_scroll_offset.Scale(kDipScale);
       total_max_scroll_offset.Scale(kDipScale);
diff --git a/android_webview/browser/safe_browsing/aw_safe_browsing_blocking_page.h b/android_webview/browser/safe_browsing/aw_safe_browsing_blocking_page.h
index 8b85543..a6caa15 100644
--- a/android_webview/browser/safe_browsing/aw_safe_browsing_blocking_page.h
+++ b/android_webview/browser/safe_browsing/aw_safe_browsing_blocking_page.h
@@ -39,7 +39,7 @@
   // Used to specify which BaseSafeBrowsingErrorUI to instantiate, and
   // parameters they require.
   // Note: these values are persisted in UMA logs, so they should never be
-  // renumbered nor reused.
+  // renumbered or reused.
   // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.android_webview
   enum class ErrorUiType { LOUD, QUIET_SMALL, QUIET_GIANT, COUNT };
 
diff --git a/android_webview/common/BUILD.gn b/android_webview/common/BUILD.gn
index c4f4c5af2..01deaa9 100644
--- a/android_webview/common/BUILD.gn
+++ b/android_webview/common/BUILD.gn
@@ -6,9 +6,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("common_mojom") {
-  sources = [
-    "js_java_interaction/interfaces.mojom",
-  ]
+  sources = [ "js_java_interaction/interfaces.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
index f159b8d..8fe2100 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -129,8 +129,8 @@
         sRecordWholeDocumentEnabledByApi = true;
     }
 
-    // Used to record the UMA histogram WebView.WebViewApiCall. Since these value are persisted to
-    // logs, they should never be renumbered nor reused.
+    // Used to record the UMA histogram WebView.WebViewApiCall. Since these values are persisted to
+    // logs, they should never be renumbered or reused.
     @IntDef({ApiCall.ADD_JAVASCRIPT_INTERFACE, ApiCall.AUTOFILL, ApiCall.CAN_GO_BACK,
             ApiCall.CAN_GO_BACK_OR_FORWARD, ApiCall.CAN_GO_FORWARD, ApiCall.CAN_ZOOM_IN,
             ApiCall.CAN_ZOOM_OUT, ApiCall.CAPTURE_PICTURE, ApiCall.CLEAR_CACHE,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 860c59d..fae9ef9 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -179,7 +179,7 @@
     }
 
     // Used to record the UMA histogram Android.WebView.LoadDataWithBaseUrl.HistoryUrl. Since these
-    // values are persisted to logs, they should never be renumbered nor reused.
+    // values are persisted to logs, they should never be renumbered or reused.
     @IntDef({HistoryUrl.EMPTY, HistoryUrl.BASEURL, HistoryUrl.DIFFERENT, HistoryUrl.COUNT})
     @interface HistoryUrl {
         int EMPTY = 0;
@@ -189,7 +189,7 @@
     }
 
     // Used to record the UMA histogram Android.WebView.LoadDataWithBaseUrl.UrlScheme. Since these
-    // values are persisted to logs, they should never be renumbered nor reused.
+    // values are persisted to logs, they should never be renumbered or reused.
     @VisibleForTesting
     @IntDef({UrlScheme.EMPTY, UrlScheme.UNKNOWN_SCHEME, UrlScheme.HTTP_SCHEME,
             UrlScheme.HTTPS_SCHEME, UrlScheme.FILE_SCHEME, UrlScheme.FTP_SCHEME,
diff --git a/android_webview/java/src/org/chromium/android_webview/safe_browsing/AwSafeBrowsingConfigHelper.java b/android_webview/java/src/org/chromium/android_webview/safe_browsing/AwSafeBrowsingConfigHelper.java
index 87ae3bb..1b9cb320 100644
--- a/android_webview/java/src/org/chromium/android_webview/safe_browsing/AwSafeBrowsingConfigHelper.java
+++ b/android_webview/java/src/org/chromium/android_webview/safe_browsing/AwSafeBrowsingConfigHelper.java
@@ -35,7 +35,7 @@
     private static volatile boolean sEnabledByManifest;
 
     // Used to record the UMA histogram SafeBrowsing.WebView.AppOptIn. Since these values are
-    // persisted to logs, they should never be renumbered nor reused.
+    // persisted to logs, they should never be renumbered or reused.
     @IntDef({AppOptIn.NO_PREFERENCE, AppOptIn.OPT_IN, AppOptIn.OPT_OUT})
     @interface AppOptIn {
         int NO_PREFERENCE = 0;
@@ -46,7 +46,7 @@
     }
 
     // Used to record the UMA histogram SafeBrowsing.WebView.UserOptIn. Since these values are
-    // persisted to logs, they should never be renumbered nor reused.
+    // persisted to logs, they should never be renumbered or reused.
     @IntDef({UserOptIn.UNABLE_TO_DETERMINE, UserOptIn.OPT_IN, UserOptIn.OPT_OUT})
     @interface UserOptIn {
         int OPT_OUT = 0;
diff --git a/android_webview/renderer/BUILD.gn b/android_webview/renderer/BUILD.gn
index 6ceb223..88b25c6 100644
--- a/android_webview/renderer/BUILD.gn
+++ b/android_webview/renderer/BUILD.gn
@@ -40,6 +40,7 @@
     "//android_webview/common",
     "//android_webview/common:common_mojom",
     "//base",
+    "//components/android_system_error_page",
     "//components/autofill/content/renderer",
     "//components/cdm/renderer",
     "//components/content_capture/common",
diff --git a/android_webview/renderer/DEPS b/android_webview/renderer/DEPS
index 4694021f..b30bfc3 100644
--- a/android_webview/renderer/DEPS
+++ b/android_webview/renderer/DEPS
@@ -4,6 +4,7 @@
   "+android_webview/renderer",
   "+android_webview/grit",
 
+  "+components/android_system_error_page",
   "+components/autofill/content/renderer",
   "+components/cdm/renderer",
   "+components/page_load_metrics/renderer",
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index c4981454..bc23390 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -25,11 +25,9 @@
 #include "base/i18n/rtl.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/grit/components_resources.h"
+#include "components/android_system_error_page/error_page_populator.h"
 #include "components/page_load_metrics/renderer/metrics_render_frame_observer.h"
 #include "components/printing/renderer/print_render_frame_helper.h"
-#include "components/strings/grit/components_strings.h"
 #include "components/visitedlink/renderer/visitedlink_reader.h"
 #include "content/public/child/child_thread.h"
 #include "content/public/common/url_constants.h"
@@ -38,18 +36,13 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "mojo/public/cpp/bindings/binder_map.h"
-#include "net/base/escape.h"
-#include "net/base/net_errors.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/public/web/web_frame.h"
 #include "third_party/blink/public/web/web_navigation_type.h"
 #include "third_party/blink/public/web/web_security_policy.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
@@ -62,12 +55,6 @@
 
 namespace android_webview {
 
-namespace {
-constexpr char kThrottledErrorDescription[] =
-    "Request throttled. Visit http://dev.chromium.org/throttling for more "
-    "information.";
-}  // namespace
-
 AwContentRendererClient::AwContentRendererClient() = default;
 
 AwContentRendererClient::~AwContentRendererClient() = default;
@@ -217,45 +204,7 @@
   AwSafeBrowsingErrorPageControllerDelegateImpl::Get(render_frame)
       ->PrepareForErrorPage();
 
-  std::string err;
-  if (error.reason() == net::ERR_TEMPORARILY_THROTTLED)
-    err = kThrottledErrorDescription;
-  else
-    err = net::ErrorToString(error.reason());
-
-  if (!error_html)
-    return;
-
-  // Create the error page based on the error reason.
-  GURL gurl(error.url());
-  std::string url_string = gurl.possibly_invalid_spec();
-  int reason_id = IDS_ANDROID_ERROR_PAGE_WEBPAGE_CAN_NOT_BE_LOADED;
-
-  if (err.empty())
-    reason_id = IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN;
-
-  std::string escaped_url = net::EscapeForHTML(url_string);
-  std::vector<std::string> replacements;
-  replacements.push_back(
-      l10n_util::GetStringUTF8(IDS_ANDROID_ERROR_PAGE_WEBPAGE_NOT_AVAILABLE));
-  replacements.push_back(
-      l10n_util::GetStringFUTF8(reason_id, base::UTF8ToUTF16(escaped_url)));
-
-  // Having chosen the base reason, chose what extra information to add.
-  if (reason_id == IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN) {
-    replacements.push_back(l10n_util::GetStringUTF8(
-        IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN_SUGGESTIONS));
-  } else {
-    replacements.push_back(err);
-  }
-  if (base::i18n::IsRTL())
-    replacements.push_back("direction: rtl;");
-  else
-    replacements.push_back("");
-  *error_html = base::ReplaceStringPlaceholders(
-      ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
-          IDR_ANDROID_ERROR_PAGE_LOAD_ERROR_HTML),
-      replacements, nullptr);
+  android_system_error_page::PopulateErrorPageHtml(error, error_html);
 }
 
 uint64_t AwContentRendererClient::VisitedLinkHash(const char* canonical_url,
diff --git a/android_webview/support_library/boundary_interfaces/BUILD.gn b/android_webview/support_library/boundary_interfaces/BUILD.gn
index 0180db39..e3ed180 100644
--- a/android_webview/support_library/boundary_interfaces/BUILD.gn
+++ b/android_webview/support_library/boundary_interfaces/BUILD.gn
@@ -41,9 +41,7 @@
   # build when we mirror this into AndroidX. We are only permitted to depend on
   # core Android classes and other AndroidX classes (must be in the androidx.*
   # package name).
-  deps = [
-    "//third_party/android_deps:androidx_annotation_annotation_java",
-  ]
+  deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ]
 
   # This is to verify the boundary interfaces compile and lint correctly against
   # the minSdkVersion of the webkit support library module. As the minSdkVersion
diff --git a/android_webview/test/embedded_test_server/BUILD.gn b/android_webview/test/embedded_test_server/BUILD.gn
index fa8c6b4..e9807d7 100644
--- a/android_webview/test/embedded_test_server/BUILD.gn
+++ b/android_webview/test/embedded_test_server/BUILD.gn
@@ -37,9 +37,7 @@
     "aw_embedded_test_server.cc",
     "aw_test_entry_point.cc",
   ]
-  deps = [
-    "//net:test_support",
-  ]
+  deps = [ "//net:test_support" ]
   public_deps = [
     ":aw_net_jni_headers",
     "//net:net_test_jni_headers",
diff --git a/android_webview/tools/system_webview_shell/BUILD.gn b/android_webview/tools/system_webview_shell/BUILD.gn
index dc7d6d13..183b87a 100644
--- a/android_webview/tools/system_webview_shell/BUILD.gn
+++ b/android_webview/tools/system_webview_shell/BUILD.gn
@@ -47,18 +47,14 @@
 android_resources("system_webview_shell_apk_resources") {
   resource_dirs = [ "apk/res" ]
   custom_package = "org.chromium.webview_shell"
-  deps = [
-    "//third_party/android_deps:android_support_v7_appcompat_java",
-  ]
+  deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ]
 }
 
 instrumentation_test_apk("system_webview_shell_page_cycler_apk") {
   apk_name = "SystemWebViewShellPageCycler"
   apk_under_test = ":system_webview_shell_apk"
   android_manifest = "page_cycler/AndroidManifest.xml"
-  sources = [
-    "page_cycler/src/org/chromium/webview_shell/page_cycler/PageCyclerTest.java",
-  ]
+  sources = [ "page_cycler/src/org/chromium/webview_shell/page_cycler/PageCyclerTest.java" ]
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
diff --git a/android_webview/tools/webview_log_verbosifier/BUILD.gn b/android_webview/tools/webview_log_verbosifier/BUILD.gn
index aca6466..a6d9dfd 100644
--- a/android_webview/tools/webview_log_verbosifier/BUILD.gn
+++ b/android_webview/tools/webview_log_verbosifier/BUILD.gn
@@ -7,9 +7,7 @@
 android_apk("webview_log_verbosifier_apk") {
   apk_name = "WebViewLogVerbosifier"
   android_manifest = "AndroidManifest.xml"
-  deps = [
-    ":webview_log_verbosifier_resources",
-  ]
+  deps = [ ":webview_log_verbosifier_resources" ]
   min_sdk_version = 21
   target_sdk_version = 28
 }
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index 6a5b38e..1b0c73f 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -33,6 +33,7 @@
 #include "ash/metrics/user_metrics_recorder.h"
 #include "ash/multi_profile_uma.h"
 #include "ash/public/cpp/ash_features.h"
+#include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/new_window_delegate.h"
 #include "ash/public/cpp/notification_utils.h"
@@ -1150,37 +1151,61 @@
                                                            false /* by_user */);
 }
 
-void SetDockedMagnifierEnabled(bool enabled) {
-  Shell::Get()->docked_magnifier_controller()->SetEnabled(enabled);
+// Return false if the accessibility shortcuts have been disabled, or if
+// the accessibility feature itself associated with |accessibility_pref_name|
+// is being enforced by the administrator.
+bool IsAccessibilityShortcutEnabled(
+    const std::string& accessibility_pref_name) {
+  Shell* shell = Shell::Get();
+  return shell->accessibility_controller()->accessibility_shortcuts_enabled() &&
+         !shell->session_controller()
+              ->GetActivePrefService()
+              ->IsManagedPreference(accessibility_pref_name);
+}
 
-  // We need to show the notification only if the state actually changed.
-  const bool actual_enabled =
-      Shell::Get()->docked_magnifier_controller()->GetEnabled();
+void SetDockedMagnifierEnabled(bool enabled) {
+  Shell* shell = Shell::Get();
+  // Check that the attempt to change the value of the accessibility feature
+  // will be done only when the accessibility shortcuts are enabled, and
+  // the feature isn't being enforced by the administrator.
+  DCHECK(IsAccessibilityShortcutEnabled(prefs::kDockedMagnifierEnabled));
+
+  shell->docked_magnifier_controller()->SetEnabled(enabled);
+
   RemoveStickyNotitification(kDockedMagnifierToggleAccelNotificationId);
-  if (enabled && actual_enabled) {
+  if (shell->docked_magnifier_controller()->GetEnabled()) {
     CreateAndShowStickyNotification(IDS_DOCKED_MAGNIFIER_ACCEL_TITLE,
                                     IDS_DOCKED_MAGNIFIER_ACCEL_MSG,
                                     kDockedMagnifierToggleAccelNotificationId);
-  } else if (enabled != actual_enabled) {
-    NotifyAccessibilityFeatureDisabledByAdmin(
-        IDS_ASH_DOCKED_MAGNIFIER_SHORTCUT_DISABLED, actual_enabled,
-        kDockedMagnifierToggleAccelNotificationId);
   }
 }
 
 void HandleToggleDockedMagnifier() {
   base::RecordAction(UserMetricsAction("Accel_Toggle_Docked_Magnifier"));
 
+  Shell* shell = Shell::Get();
+
+  RemoveStickyNotitification(kDockedMagnifierToggleAccelNotificationId);
+  if (!IsAccessibilityShortcutEnabled(prefs::kDockedMagnifierEnabled)) {
+    NotifyAccessibilityFeatureDisabledByAdmin(
+        IDS_ASH_DOCKED_MAGNIFIER_SHORTCUT_DISABLED,
+        shell->docked_magnifier_controller()->GetEnabled(),
+        kDockedMagnifierToggleAccelNotificationId);
+    return;
+  }
+
   DockedMagnifierControllerImpl* docked_magnifier_controller =
-      Shell::Get()->docked_magnifier_controller();
+      shell->docked_magnifier_controller();
+  AccessibilityControllerImpl* accessibility_controller =
+      shell->accessibility_controller();
+
   const bool current_enabled = docked_magnifier_controller->GetEnabled();
   const bool dialog_ever_accepted =
-      Shell::Get()
-          ->accessibility_controller()
+      accessibility_controller
           ->HasDockedMagnifierAcceleratorDialogBeenAccepted();
 
   if (!current_enabled && !dialog_ever_accepted) {
-    Shell::Get()->accelerator_controller()->MaybeShowConfirmationDialog(
+    shell->accelerator_controller()->MaybeShowConfirmationDialog(
         IDS_ASH_DOCKED_MAGNIFIER_TITLE, IDS_ASH_DOCKED_MAGNIFIER_BODY,
         base::BindOnce([]() {
           Shell::Get()
@@ -1199,54 +1224,63 @@
   // Necessary to make magnification controller in ash observe changes to the
   // prefs iteself.
   Shell* shell = Shell::Get();
+  // Check that the attempt to change the value of the accessibility feature
+  // will be done only when the accessibility shortcuts are enabled, and
+  // the feature isn't being enforced by the administrator.
+  DCHECK(IsAccessibilityShortcutEnabled(
+      prefs::kAccessibilityScreenMagnifierEnabled));
+
   shell->accessibility_controller()->SetFullscreenMagnifierEnabled(enabled);
 
-  // We need to show the notification only if the state actually changed.
-  const bool actual_enabled =
-      Shell::Get()->magnification_controller()->IsEnabled();
   RemoveStickyNotitification(kFullscreenMagnifierToggleAccelNotificationId);
-  if (enabled && actual_enabled) {
+  if (shell->magnification_controller()->IsEnabled()) {
     CreateAndShowStickyNotification(
         IDS_FULLSCREEN_MAGNIFIER_ACCEL_TITLE,
         IDS_FULLSCREEN_MAGNIFIER_ACCEL_MSG,
         kFullscreenMagnifierToggleAccelNotificationId);
-  } else if (enabled != actual_enabled) {
-    NotifyAccessibilityFeatureDisabledByAdmin(
-        IDS_ASH_FULLSCREEN_MAGNIFIER_SHORTCUT_DISABLED, actual_enabled,
-        kFullscreenMagnifierToggleAccelNotificationId);
   }
 }
 
 void SetHighContrastEnabled(bool enabled) {
-  AccessibilityControllerImpl* accessibility_controller =
-      Shell::Get()->accessibility_controller();
-  accessibility_controller->SetHighContrastEnabled(enabled);
-  // Value could differ from one that were set because of higher-priority pref
-  // source, eg. policy. See crbug.com/953245.
-  const bool actual_enabled = accessibility_controller->high_contrast_enabled();
+  Shell* shell = Shell::Get();
+  // Check that the attempt to change the value of the accessibility feature
+  // will be done only when the accessibility shortcuts are enabled, and
+  // the feature isn't being enforced by the administrator.
+  DCHECK(
+      IsAccessibilityShortcutEnabled(prefs::kAccessibilityHighContrastEnabled));
+
+  shell->accessibility_controller()->SetHighContrastEnabled(enabled);
+
   RemoveStickyNotitification(kHighContrastToggleAccelNotificationId);
-  if (enabled && actual_enabled) {
+  if (shell->accessibility_controller()->high_contrast_enabled()) {
     CreateAndShowStickyNotification(IDS_HIGH_CONTRAST_ACCEL_TITLE,
                                     IDS_HIGH_CONTRAST_ACCEL_MSG,
                                     kHighContrastToggleAccelNotificationId);
-  } else if (enabled != actual_enabled) {
-    NotifyAccessibilityFeatureDisabledByAdmin(
-        IDS_ASH_HIGH_CONTRAST_SHORTCUT_DISABLED, actual_enabled,
-        kHighContrastToggleAccelNotificationId);
   }
 }
 
 void HandleToggleHighContrast() {
   base::RecordAction(UserMetricsAction("Accel_Toggle_High_Contrast"));
 
-  AccessibilityControllerImpl* controller =
-      Shell::Get()->accessibility_controller();
+  Shell* shell = Shell::Get();
+
+  RemoveStickyNotitification(kHighContrastToggleAccelNotificationId);
+  if (!IsAccessibilityShortcutEnabled(
+          prefs::kAccessibilityHighContrastEnabled)) {
+    NotifyAccessibilityFeatureDisabledByAdmin(
+        IDS_ASH_HIGH_CONTRAST_SHORTCUT_DISABLED,
+        shell->accessibility_controller()->high_contrast_enabled(),
+        kHighContrastToggleAccelNotificationId);
+    return;
+  }
+
+  AccessibilityControllerImpl* controller = shell->accessibility_controller();
   const bool current_enabled = controller->high_contrast_enabled();
   const bool dialog_ever_accepted =
       controller->HasHighContrastAcceleratorDialogBeenAccepted();
 
   if (!current_enabled && !dialog_ever_accepted) {
-    Shell::Get()->accelerator_controller()->MaybeShowConfirmationDialog(
+    shell->accelerator_controller()->MaybeShowConfirmationDialog(
         IDS_ASH_HIGH_CONTRAST_TITLE, IDS_ASH_HIGH_CONTRAST_BODY,
         base::BindOnce([]() {
           Shell::Get()
@@ -1263,15 +1297,30 @@
 void HandleToggleFullscreenMagnifier() {
   base::RecordAction(UserMetricsAction("Accel_Toggle_Fullscreen_Magnifier"));
 
-  MagnificationController* controller =
-      Shell::Get()->magnification_controller();
-  const bool current_enabled = controller->IsEnabled();
+  Shell* shell = Shell::Get();
+
+  RemoveStickyNotitification(kFullscreenMagnifierToggleAccelNotificationId);
+  if (!IsAccessibilityShortcutEnabled(
+          prefs::kAccessibilityScreenMagnifierEnabled)) {
+    NotifyAccessibilityFeatureDisabledByAdmin(
+        IDS_ASH_FULLSCREEN_MAGNIFIER_SHORTCUT_DISABLED,
+        shell->magnification_controller()->IsEnabled(),
+        kFullscreenMagnifierToggleAccelNotificationId);
+    return;
+  }
+
+  MagnificationController* magnification_controller =
+      shell->magnification_controller();
+  AccessibilityControllerImpl* accessibility_controller =
+      shell->accessibility_controller();
+
+  const bool current_enabled = magnification_controller->IsEnabled();
   const bool dialog_ever_accepted =
-      Shell::Get()
-          ->accessibility_controller()
+      accessibility_controller
           ->HasScreenMagnifierAcceleratorDialogBeenAccepted();
+
   if (!current_enabled && !dialog_ever_accepted) {
-    Shell::Get()->accelerator_controller()->MaybeShowConfirmationDialog(
+    shell->accelerator_controller()->MaybeShowConfirmationDialog(
         IDS_ASH_SCREEN_MAGNIFIER_TITLE, IDS_ASH_SCREEN_MAGNIFIER_BODY,
         base::BindOnce([]() {
           Shell::Get()
@@ -1288,20 +1337,21 @@
 void HandleToggleSpokenFeedback() {
   base::RecordAction(UserMetricsAction("Accel_Toggle_Spoken_Feedback"));
 
-  AccessibilityControllerImpl* controller =
-      Shell::Get()->accessibility_controller();
-  bool old_value = controller->spoken_feedback_enabled();
-  controller->SetSpokenFeedbackEnabled(!controller->spoken_feedback_enabled(),
-                                       A11Y_NOTIFICATION_SHOW);
-  // If we tried to enable it and didn't succeed — show disabled by policy
-  // toast.
+  Shell* shell = Shell::Get();
+  const bool old_value =
+      shell->accessibility_controller()->spoken_feedback_enabled();
+
   RemoveStickyNotitification(kSpokenFeedbackToggleAccelNotificationId);
-  if (!controller->spoken_feedback_enabled() && !old_value) {
+  if (!IsAccessibilityShortcutEnabled(
+          prefs::kAccessibilitySpokenFeedbackEnabled)) {
     NotifyAccessibilityFeatureDisabledByAdmin(
-        IDS_ASH_SPOKEN_FEEDBACK_SHORTCUT_DISABLED,
-        controller->spoken_feedback_enabled(),
+        IDS_ASH_SPOKEN_FEEDBACK_SHORTCUT_DISABLED, old_value,
         kSpokenFeedbackToggleAccelNotificationId);
+    return;
   }
+
+  shell->accessibility_controller()->SetSpokenFeedbackEnabled(
+      !old_value, A11Y_NOTIFICATION_SHOW);
 }
 
 // Percent by which the volume should be changed when a volume key is pressed.
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 41e58832..65a61a5 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -2108,6 +2108,108 @@
   RemoveAllNotifications();
 }
 
+class AccessibilityAcceleratorTester : public MagnifiersAcceleratorsTester {
+ public:
+  AccessibilityAcceleratorTester() = default;
+  ~AccessibilityAcceleratorTester() override = default;
+
+  AccessibilityAcceleratorTester(const AccessibilityAcceleratorTester&) =
+      delete;
+  AccessibilityAcceleratorTester& operator=(
+      const AccessibilityAcceleratorTester&) = delete;
+
+  bool ContainsAccessibilityNotification(
+      const std::string& notification_id) const {
+    return nullptr !=
+           message_center()->FindVisibleNotificationById(notification_id);
+  }
+
+  void TestAccessibilityAcceleratorControlledByPref(
+      const std::string& pref_name,
+      const char* notification_id,
+      const ui::Accelerator& accelerator) {
+    // Verify that the initial state for the accessibility feature will be
+    // disabled, and for accessibility accelerators controller pref
+    // |kAccessibilityShortcutsEnabled| is enabled. And neither of that
+    // accessibility feature notification id, nor its confirmation dialog have
+    // appeared.
+    EXPECT_FALSE(user_pref_service()->GetBoolean(pref_name));
+    EXPECT_TRUE(
+        user_pref_service()->GetBoolean(prefs::kAccessibilityShortcutsEnabled));
+    EXPECT_FALSE(IsConfirmationDialogOpen());
+    if (notification_id)
+      EXPECT_FALSE(ContainsAccessibilityNotification(notification_id));
+
+    // Verify that after disabling the accessibility accelerators, the
+    // confirmation dialog won't appear for that accessibility feature. And its
+    // corresponding pref won't be enabled. But a notification should appear,
+    // which shows that the shortcut for that feature has been disabled.
+    user_pref_service()->SetBoolean(prefs::kAccessibilityShortcutsEnabled,
+                                    false);
+    EXPECT_TRUE(ProcessInController(accelerator));
+    EXPECT_FALSE(IsConfirmationDialogOpen());
+    if (notification_id)
+      EXPECT_TRUE(ContainsAccessibilityNotification(notification_id));
+    EXPECT_FALSE(user_pref_service()->GetBoolean(pref_name));
+
+    // Verify that if the accessibility accelerators are enabled, then
+    // it will show the confirmation dialog for the first time only when
+    // toggling its value. And the coressponding pref will be chanaged
+    // accordingly.
+    user_pref_service()->SetBoolean(prefs::kAccessibilityShortcutsEnabled,
+                                    true);
+    EXPECT_TRUE(ProcessInController(accelerator));
+    if (notification_id)
+      AcceptConfirmationDialog();
+    base::RunLoop().RunUntilIdle();
+    message_center::NotificationList::Notifications notifications =
+        message_center()->GetVisibleNotifications();
+    ASSERT_EQ(1u, notifications.size());
+    EXPECT_TRUE(user_pref_service()->GetBoolean(pref_name));
+    if (notification_id)
+      EXPECT_TRUE(ContainsAccessibilityNotification(notification_id));
+
+    // Verify that the notification id, won't be shown if the accessibility
+    // feature is going to be disabled.
+    EXPECT_TRUE(ProcessInController(accelerator));
+    if (notification_id)
+      EXPECT_FALSE(ContainsAccessibilityNotification(notification_id));
+    EXPECT_FALSE(user_pref_service()->GetBoolean(pref_name));
+
+    // Remove all the current notifications, to get the initial state again.
+    RemoveAllNotifications();
+  }
+};
+
+TEST_F(AccessibilityAcceleratorTester, DisableAccessibilityAccelerators) {
+  struct PrefToAcceleratorEntry {
+    const char* pref_name;
+    // If |notification_id| has been set to nullptr, then no notification is
+    // expected.
+    const char* notification_id;
+    const ui::Accelerator accelerator;
+  };
+  const PrefToAcceleratorEntry kAccessibilityAcceleratorMap[] = {
+      {prefs::kAccessibilityHighContrastEnabled,
+       kHighContrastToggleAccelNotificationId,
+       ui::Accelerator(ui::VKEY_H, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN)},
+      {prefs::kDockedMagnifierEnabled,
+       kDockedMagnifierToggleAccelNotificationId,
+       ui::Accelerator(ui::VKEY_D, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN)},
+      {prefs::kAccessibilitySpokenFeedbackEnabled, nullptr,
+       ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)},
+      {prefs::kAccessibilityScreenMagnifierEnabled,
+       kFullscreenMagnifierToggleAccelNotificationId,
+       ui::Accelerator(ui::VKEY_M, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN)},
+  };
+  FakeMagnificationManager manager;
+  manager.SetPrefs(user_pref_service());
+  for (const auto& test_data : kAccessibilityAcceleratorMap) {
+    TestAccessibilityAcceleratorControlledByPref(
+        test_data.pref_name, test_data.notification_id, test_data.accelerator);
+  }
+}
+
 namespace {
 
 struct MediaSessionAcceleratorTestConfig {
diff --git a/ash/accessibility/accessibility_controller_impl.cc b/ash/accessibility/accessibility_controller_impl.cc
index 695a5d7..ff9e097b 100644
--- a/ash/accessibility/accessibility_controller_impl.cc
+++ b/ash/accessibility/accessibility_controller_impl.cc
@@ -88,6 +88,7 @@
     prefs::kAccessibilitySelectToSpeakEnabled,
     prefs::kAccessibilitySpokenFeedbackEnabled,
     prefs::kAccessibilityStickyKeysEnabled,
+    prefs::kAccessibilityShortcutsEnabled,
     prefs::kAccessibilitySwitchAccessEnabled,
     prefs::kAccessibilityVirtualKeyboardEnabled,
     prefs::kDockedMagnifierEnabled,
@@ -369,6 +370,9 @@
       prefs::kAccessibilityStickyKeysEnabled, false,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
   registry->RegisterBooleanPref(
+      prefs::kAccessibilityShortcutsEnabled, true,
+      user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
+  registry->RegisterBooleanPref(
       prefs::kAccessibilitySwitchAccessEnabled, false,
       user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
   registry->RegisterListPref(
@@ -1175,6 +1179,11 @@
           &AccessibilityControllerImpl::UpdateSelectToSpeakFromPref,
           base::Unretained(this)));
   pref_change_registrar_->Add(
+      prefs::kAccessibilityShortcutsEnabled,
+      base::BindRepeating(
+          &AccessibilityControllerImpl::UpdateShortcutsEnabledFromPref,
+          base::Unretained(this)));
+  pref_change_registrar_->Add(
       prefs::kAccessibilityStickyKeysEnabled,
       base::BindRepeating(
           &AccessibilityControllerImpl::UpdateStickyKeysFromPref,
@@ -1240,6 +1249,7 @@
   UpdateStickyKeysFromPref();
   UpdateSwitchAccessFromPref();
   UpdateVirtualKeyboardFromPref();
+  UpdateShortcutsEnabledFromPref();
 }
 
 void AccessibilityControllerImpl::UpdateAutoclickFromPref() {
@@ -1654,6 +1664,19 @@
   UpdateSwitchAccessKeyCodesFromPref(SwitchAccessCommand::kPrevious);
 }
 
+void AccessibilityControllerImpl::UpdateShortcutsEnabledFromPref() {
+  DCHECK(active_user_prefs_);
+  const bool enabled =
+      active_user_prefs_->GetBoolean(prefs::kAccessibilityShortcutsEnabled);
+
+  if (shortcuts_enabled_ == enabled)
+    return;
+
+  shortcuts_enabled_ = enabled;
+
+  NotifyAccessibilityStatusChanged();
+}
+
 void AccessibilityControllerImpl::UpdateVirtualKeyboardFromPref() {
   DCHECK(active_user_prefs_);
   const bool enabled = active_user_prefs_->GetBoolean(
diff --git a/ash/accessibility/accessibility_controller_impl.h b/ash/accessibility/accessibility_controller_impl.h
index d46403a6..9fb8630 100644
--- a/ash/accessibility/accessibility_controller_impl.h
+++ b/ash/accessibility/accessibility_controller_impl.h
@@ -167,6 +167,9 @@
 
   bool dictation_active() const { return dictation_active_; }
 
+  // Returns true if accessibility shortcuts have been disabled.
+  bool accessibility_shortcuts_enabled() const { return shortcuts_enabled_; }
+
   // Triggers an accessibility alert to give the user feedback.
   void TriggerAccessibilityAlert(AccessibilityAlert alert);
 
@@ -292,6 +295,7 @@
   void UpdateSwitchAccessAutoScanKeyboardSpeedFromPref();
   void UpdateVirtualKeyboardFromPref();
   void UpdateAccessibilityHighlightingFromPrefs();
+  void UpdateShortcutsEnabledFromPref();
 
   void MaybeCreateSelectToSpeakEventHandler();
   void MaybeCreateSwitchAccessEventHandler();
@@ -321,6 +325,7 @@
   bool switch_access_enabled_ = false;
   bool virtual_keyboard_enabled_ = false;
   bool dictation_active_ = false;
+  bool shortcuts_enabled_ = true;
 
   SelectToSpeakState select_to_speak_state_ =
       SelectToSpeakState::kSelectToSpeakStateInactive;
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc
index fcab59d..7dd0e4a 100644
--- a/ash/accessibility/accessibility_controller_unittest.cc
+++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -68,6 +68,7 @@
   EXPECT_TRUE(
       prefs->FindPreference(prefs::kAccessibilitySpokenFeedbackEnabled));
   EXPECT_TRUE(prefs->FindPreference(prefs::kAccessibilityStickyKeysEnabled));
+  EXPECT_TRUE(prefs->FindPreference(prefs::kAccessibilityShortcutsEnabled));
   EXPECT_TRUE(
       prefs->FindPreference(prefs::kAccessibilityVirtualKeyboardEnabled));
 }
diff --git a/ash/home_screen/drag_window_from_shelf_controller_unittest.cc b/ash/home_screen/drag_window_from_shelf_controller_unittest.cc
index fe7531f..a7b3989 100644
--- a/ash/home_screen/drag_window_from_shelf_controller_unittest.cc
+++ b/ash/home_screen/drag_window_from_shelf_controller_unittest.cc
@@ -182,8 +182,8 @@
   EXPECT_FALSE(window2->IsVisible());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
-  DragWindowFromShelfControllerTestApi test_api;
-  test_api.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   EndDrag(gfx::Point(200, 200), base::nullopt);
   EXPECT_TRUE(overview_controller->InOverviewSession());
   EXPECT_TRUE(overview_controller->overview_session()->IsWindowInOverview(
@@ -219,8 +219,8 @@
   StartDrag(window1.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
   // Drag it far enough so overview should be open behind the dragged window.
   Drag(gfx::Point(200, 200), 0.f, 1.f);
-  DragWindowFromShelfControllerTestApi test_api;
-  test_api.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
   EXPECT_TRUE(window1->IsVisible());
@@ -286,8 +286,8 @@
   Drag(gfx::Point(200, 200), 0.f, 1.f);
   EXPECT_FALSE(window->layer()->GetTargetTransform().IsIdentity());
   EXPECT_TRUE(overview_controller->InOverviewSession());
-  DragWindowFromShelfControllerTestApi test_api;
-  test_api.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   EndDrag(
       gfx::Point(
           200,
@@ -316,8 +316,7 @@
 
 // Test if overview is active and splitview is not active, fling in overview may
 // or may not head to the home screen.
-// TODO(https://crbug.com/1019080) This test is flaky.
-TEST_F(DragWindowFromShelfControllerTest, DISABLED_FlingInOverview) {
+TEST_F(DragWindowFromShelfControllerTest, FlingInOverview) {
   UpdateDisplay("400x400");
   const gfx::Rect shelf_bounds =
       Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
@@ -327,6 +326,8 @@
   // where the window should go based on the release position.
   StartDrag(window.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
   Drag(gfx::Point(200, 200), 0.f, 1.f);
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
   EndDrag(
@@ -456,8 +457,8 @@
 
   StartDrag(window1.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
   Drag(gfx::Point(200, 200), 0.5f, 0.5f);
-  DragWindowFromShelfControllerTestApi test_api;
-  test_api.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
   // We test the visibility of overview by testing the drop target widget's
@@ -476,8 +477,8 @@
   EXPECT_EQ(drop_target_item->GetWindow()->layer()->GetTargetOpacity(), 0.f);
 
   Drag(gfx::Point(200, 200), 0.5f, 0.5f);
-  DragWindowFromShelfControllerTestApi test_api2;
-  test_api2.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   EndDrag(gfx::Point(200, 200),
           /*velocity_y=*/base::nullopt);
   EXPECT_TRUE(overview_controller->InOverviewSession());
@@ -488,9 +489,8 @@
 }
 
 // Check the split view drag indicators window dragging states.
-// Flaky on ChromeOS. https://crbug.com/1022320
 TEST_F(DragWindowFromShelfControllerTest,
-       DISABLED_SplitViewDragIndicatorsWindowDraggingStates) {
+       SplitViewDragIndicatorsWindowDraggingStates) {
   UpdateDisplay("400x400");
   const gfx::Rect shelf_bounds =
       Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
@@ -498,6 +498,8 @@
 
   StartDrag(window.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
   Drag(gfx::Point(200, 200), 0.5f, 0.5f);
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
   OverviewSession* overview_session = overview_controller->overview_session();
@@ -550,8 +552,7 @@
 
 // Test that if drag is cancelled, overview should be dismissed and other
 // hidden windows should restore to its previous visibility state.
-// TODO(crbug.com/1022319): flaky.
-TEST_F(DragWindowFromShelfControllerTest, DISABLED_CancelDragDismissOverview) {
+TEST_F(DragWindowFromShelfControllerTest, CancelDragDismissOverview) {
   const gfx::Rect shelf_bounds =
       Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
   auto window3 = CreateTestWindow();
@@ -563,6 +564,8 @@
 
   StartDrag(window1.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
   Drag(gfx::Point(200, 200), 0.5f, 0.5f);
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
   EXPECT_TRUE(window1->IsVisible());
@@ -576,14 +579,14 @@
   EXPECT_TRUE(window3->IsVisible());
 }
 
-// TODO(https://crbug.com/1018498) This test is flaky.
-TEST_F(DragWindowFromShelfControllerTest,
-       DISABLED_CancelDragIfWindowDestroyed) {
+TEST_F(DragWindowFromShelfControllerTest, CancelDragIfWindowDestroyed) {
   const gfx::Rect shelf_bounds =
       Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
   auto window = CreateTestWindow();
   StartDrag(window.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
   Drag(gfx::Point(200, 200), 0.5f, 0.5f);
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   EXPECT_EQ(window_drag_controller()->dragged_window(), window.get());
   EXPECT_TRUE(window_drag_controller()->drag_started());
   window.reset();
@@ -698,8 +701,8 @@
 
   StartDrag(window.get(), shelf_bounds.left_center(), HotseatState::kExtended);
   Drag(gfx::Point(200, 200), 0.f, 10.f);
-  DragWindowFromShelfControllerTestApi test_api;
-  test_api.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   // End drag without any fling, the window should be added to overview.
   EndDrag(gfx::Point(200, 200), base::nullopt);
   OverviewController* overview_controller = Shell::Get()->overview_controller();
@@ -732,8 +735,8 @@
   EXPECT_EQ(window->GetProperty(kBackdropWindowMode),
             BackdropWindowMode::kDisabled);
   Drag(gfx::Point(200, 200), 0.f, 1.f);
-  DragWindowFromShelfControllerTestApi test_api;
-  test_api.WaitUntilOverviewIsShown(window_drag_controller());
+  DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown(
+      window_drag_controller());
   EndDrag(gfx::Point(200, 200), base::nullopt);
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   EXPECT_TRUE(overview_controller->InOverviewSession());
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index d90ba15c..5dd8de30 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -85,7 +85,7 @@
 // Date time format containing only the day of the week, for example: "Tuesday".
 constexpr char kDayOfWeekOnlyTimeFormat[] = "EEEE";
 
-constexpr int kFingerprintIconSizeDp = 32;
+constexpr int kFingerprintIconSizeDp = 28;
 constexpr int kResetToDefaultIconDelayMs = 1300;
 constexpr int kFingerprintIconTopSpacingDp = 20;
 constexpr int kSpacingBetweenFingerprintIconAndLabelDp = 15;
@@ -466,7 +466,7 @@
     if (success) {
       icon_->SetImage(gfx::CreateVectorIcon(kLockScreenFingerprintSuccessIcon,
                                             kFingerprintIconSizeDp,
-                                            gfx::kGoogleGreenDark500));
+                                            gfx::kGoogleGreen300));
     } else {
       SetIcon(FingerprintState::DISABLED_FROM_ATTEMPTS);
       // base::Unretained is safe because reset_state_ is owned by |this|.
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc
index 2bf1b22..afb2b71dd 100644
--- a/ash/public/cpp/ash_pref_names.cc
+++ b/ash/public/cpp/ash_pref_names.cc
@@ -45,6 +45,9 @@
 const char kAccessibilityMonoAudioEnabled[] = "settings.a11y.mono_audio";
 // A boolean pref which determines whether autoclick is enabled.
 const char kAccessibilityAutoclickEnabled[] = "settings.a11y.autoclick";
+// A boolean pref which determines whether the accessibility shortcuts are
+// enabled or not.
+const char kAccessibilityShortcutsEnabled[] = "settings.a11y.shortcuts_enabled";
 // An integer pref which determines time in ms between when the mouse cursor
 // stops and when an autoclick event is triggered.
 const char kAccessibilityAutoclickDelayMs[] =
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h
index cf69b422..994d927 100644
--- a/ash/public/cpp/ash_pref_names.h
+++ b/ash/public/cpp/ash_pref_names.h
@@ -22,6 +22,7 @@
 ASH_PUBLIC_EXPORT extern const char kAccessibilityVirtualKeyboardEnabled[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityMonoAudioEnabled[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickEnabled[];
+ASH_PUBLIC_EXPORT extern const char kAccessibilityShortcutsEnabled[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickDelayMs[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickEventType[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickRevertToLeftClick[];
diff --git a/ash/public/cpp/shelf_model.cc b/ash/public/cpp/shelf_model.cc
index 9d7daad..8054144 100644
--- a/ash/public/cpp/shelf_model.cc
+++ b/ash/public/cpp/shelf_model.cc
@@ -144,15 +144,28 @@
   return item;
 }
 
-bool ShelfModel::Swap(int index, bool with_next) {
+bool ShelfModel::CanSwap(int index, bool with_next) const {
   const int target_index = with_next ? index + 1 : index - 1;
 
+  // Out of bounds issues, or trying to swap the first item with the previous
+  // one, or the last item with the next one.
   if (index < 0 || target_index >= item_count() || target_index < 0)
     return false;
 
-  // Only allow swapping two pinned apps or two unpinned apps.
-  if (!SamePinState(items()[index].type, items()[target_index].type))
+  const ShelfItem source_item = items()[index];
+  const ShelfItem target_item = items()[target_index];
+  // Trying to swap two items of different pin states.
+  if (!SamePinState(source_item.type, target_item.type))
     return false;
+
+  return true;
+}
+
+bool ShelfModel::Swap(int index, bool with_next) {
+  if (!CanSwap(index, with_next))
+    return false;
+
+  const int target_index = with_next ? index + 1 : index - 1;
   Move(index, target_index);
   return true;
 }
diff --git a/ash/public/cpp/shelf_model.h b/ash/public/cpp/shelf_model.h
index a7201db..6111671 100644
--- a/ash/public/cpp/shelf_model.h
+++ b/ash/public/cpp/shelf_model.h
@@ -84,6 +84,13 @@
   std::unique_ptr<ShelfItemDelegate> RemoveItemAndTakeShelfItemDelegate(
       const ShelfID& shelf_id);
 
+  // Returns whether the item with the given index can be swapped with the
+  // next (or previous) item. Example cases when a swap cannot happen are:
+  // trying to swap the first item with the previous one, trying to swap
+  // the last item with the next one, trying to swap a pinned item with an
+  // unpinned item.
+  bool CanSwap(int index, bool with_next) const;
+
   // Swaps the item at the given index with the next one if |with_next| is
   // true, or with the previous one if |with_next| is false. Returns true
   // if the requested swap has happened, and false otherwise.
diff --git a/ash/resources/vector_icons/lock_screen_caps_lock.icon b/ash/resources/vector_icons/lock_screen_caps_lock.icon
index 01342b0f..895db6d 100644
--- a/ash/resources/vector_icons/lock_screen_caps_lock.icon
+++ b/ash/resources/vector_icons/lock_screen_caps_lock.icon
@@ -2,56 +2,31 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-CANVAS_DIMENSIONS, 40,
-MOVE_TO, 9, 5,
-LINE_TO, 31, 5,
-CUBIC_TO, 33.21f, 5, 35, 6.79f, 35, 9,
-LINE_TO, 35, 31,
-CUBIC_TO, 35, 33.21f, 33.21f, 35, 31, 35,
-LINE_TO, 9, 35,
-CUBIC_TO, 6.79f, 35, 5, 33.21f, 5, 31,
-LINE_TO, 5, 9,
-LINE_TO, 5, 9,
-CUBIC_TO, 5, 6.79f, 6.79f, 5, 9, 5,
-LINE_TO, 9, 5,
-CLOSE,
-MOVE_TO, 20, 14.95f,
-LINE_TO, 27.65f, 23,
-LINE_TO, 30, 20.53f,
-LINE_TO, 20, 10,
-LINE_TO, 10, 20.53f,
-LINE_TO, 12.35f, 23,
-LINE_TO, 20, 14.95f,
-CLOSE,
-MOVE_TO, 10, 30,
-LINE_TO, 30, 30,
-LINE_TO, 30, 27,
-LINE_TO, 10, 27,
-LINE_TO, 10, 30,
-CLOSE
 
 CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2.5f, 4.49f,
-CUBIC_TO, 2.5f, 3.39f, 3.39f, 2.5f, 4.49f, 2.5f,
-LINE_TO, 15.51f, 2.5f,
-CUBIC_TO, 16.61f, 2.5f, 17.5f, 3.39f, 17.5f, 4.49f,
-LINE_TO, 17.5f, 15.51f,
-CUBIC_TO, 17.5f, 16.61f, 16.61f, 17.5f, 15.51f, 17.5f,
-LINE_TO, 4.49f, 17.5f,
-CUBIC_TO, 3.39f, 17.5f, 2.5f, 16.61f, 2.5f, 15.51f,
-LINE_TO, 2.5f, 4.49f,
+MOVE_TO, 16, 2,
+R_CUBIC_TO, 1.1f, 0, 2, 0.9f, 2, 2,
+R_V_LINE_TO, 12,
+R_CUBIC_TO, 0, 1.1f, -0.9f, 2, -2, 2,
+H_LINE_TO, 4,
+R_CUBIC_TO, -1.1f, 0, -2, -0.9f, -2, -2,
+V_LINE_TO, 4,
+R_CUBIC_TO, 0, -1.1f, 0.9f, -2, 2, -2,
 CLOSE,
-MOVE_TO, 10, 7.47f,
-LINE_TO, 13.83f, 11.5f,
-LINE_TO, 15, 10.26f,
-LINE_TO, 10, 5,
-LINE_TO, 5, 10.26f,
-LINE_TO, 6.18f, 11.5f,
-LINE_TO, 10, 7.47f,
+R_MOVE_TO, 0, 2,
+H_LINE_TO, 4,
+R_V_LINE_TO, 12,
+R_H_LINE_TO, 12,
 CLOSE,
-MOVE_TO, 5, 15,
-LINE_TO, 15, 15,
-LINE_TO, 15, 13.5f,
-LINE_TO, 5, 13.5f,
-LINE_TO, 5, 15,
+R_MOVE_TO, -2, 8,
+R_V_LINE_TO, 2,
+H_LINE_TO, 6,
+R_V_LINE_TO, -2,
+CLOSE,
+R_MOVE_TO, -4, -6.91f,
+R_LINE_TO, 4.21f, 4.21f,
+R_LINE_TO, -1.41f, 1.41f,
+LINE_TO, 10, 7.91f,
+LINE_TO, 7.21f, 10.71f,
+LINE_TO, 5.79f, 9.29f,
 CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_fingerprint_success.icon b/ash/resources/vector_icons/lock_screen_fingerprint_success.icon
index f7e74d8..b1bdaee 100644
--- a/ash/resources/vector_icons/lock_screen_fingerprint_success.icon
+++ b/ash/resources/vector_icons/lock_screen_fingerprint_success.icon
@@ -2,44 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-CANVAS_DIMENSIONS, 56,
-MOVE_TO, 28, 4,
-CUBIC_TO, 14.8f, 4, 4, 14.8f, 4, 28,
-R_CUBIC_TO, 0, 13.2f, 10.8f, 24, 24, 24,
-R_CUBIC_TO, 13.2f, 0, 24, -10.8f, 24, -24,
-CUBIC_TO_SHORTHAND, 41.2f, 4, 28, 4,
-CLOSE,
-R_MOVE_TO, 0, 43.2f,
-CUBIC_TO, 17.4f, 47.2f, 8.8f, 38.6f, 8.8f, 28,
-CUBIC_TO_SHORTHAND, 17.4f, 8.8f, 28, 8.8f,
-CUBIC_TO_SHORTHAND, 47.2f, 17.4f, 47.2f, 28,
-CUBIC_TO_SHORTHAND, 38.6f, 47.2f, 28, 47.2f,
-CLOSE,
-MOVE_TO, 37.4f, 19,
-LINE_TO, 24.6f, 31.6f,
-R_LINE_TO, -5, -5,
-R_LINE_TO, -2.6f, 2.8f,
-R_LINE_TO, 7.6f, 7.6f,
-LINE_TO, 40, 21.6f,
-CLOSE
-
 CANVAS_DIMENSIONS, 28,
-MOVE_TO, 14, 2,
-CUBIC_TO, 7.4f, 2, 2, 7.4f, 2, 14,
-R_CUBIC_TO, 0, 6.6f, 5.4f, 12, 12, 12,
-R_CUBIC_TO, 6.6f, 0, 12, -5.4f, 12, -12,
-CUBIC_TO_SHORTHAND, 20.6f, 2, 14, 2,
+MOVE_TO, 14, 4,
+CUBIC_TO, 8.48f, 4, 4, 8.48f, 4, 14,
+R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
+R_CUBIC_TO, 5.52f, 0, 10, -4.48f, 10, -10,
+CUBIC_TO_SHORTHAND, 19.52f, 4, 14, 4,
 CLOSE,
-R_MOVE_TO, 0, 21.6f,
-R_CUBIC_TO, -5.3f, 0, -9.6f, -4.3f, -9.6f, -9.6f,
-CUBIC_TO_SHORTHAND, 8.7f, 4.4f, 14, 4.4f,
-R_CUBIC_TO, 5.3f, 0, 9.6f, 4.3f, 9.6f, 9.6f,
-R_CUBIC_TO, 0, 5.3f, -4.3f, 9.6f, -9.6f, 9.6f,
+R_MOVE_TO, 0, 18,
+R_CUBIC_TO, -4.41f, 0, -8, -3.59f, -8, -8,
+R_CUBIC_TO, 0, -4.41f, 3.59f, -8, 8, -8,
+R_CUBIC_TO, 4.41f, 0, 8, 3.59f, 8, 8,
+R_CUBIC_TO, 0, 4.41f, -3.59f, 8, -8, 8,
 CLOSE,
-MOVE_TO, 18.7f, 9.5f,
-R_LINE_TO, -6.4f, 6.3f,
-R_LINE_TO, -2.5f, -2.5f,
-R_LINE_TO, -1.3f, 1.4f,
-R_LINE_TO, 3.8f, 3.8f,
-R_LINE_TO, 7.7f, -7.7f,
-CLOSE
\ No newline at end of file
+R_MOVE_TO, -2, -5.8f,
+R_LINE_TO, -2.6f, -2.6f,
+LINE_TO, 8, 15,
+R_LINE_TO, 4, 4,
+R_LINE_TO, 8, -8,
+R_LINE_TO, -1.4f, -1.4f,
+CLOSE
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 90b62f44..a54d240 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2158,7 +2158,7 @@
 
   flags = [
     "CLANG_COVERAGE=$use_clang_coverage",
-    "CLANG_COVERAGE_INSIDE_SANDBOX=$use_clang_coverage_inside_sandbox"
+    "CLANG_COVERAGE_INSIDE_SANDBOX=$use_clang_coverage_inside_sandbox",
   ]
 }
 
@@ -2184,9 +2184,7 @@
       "win/static_constants.h",
     ]
 
-    public_deps = [
-      "//base/win:pe_image",
-    ]
+    public_deps = [ "//base/win:pe_image" ]
 
     # Disable sanitizer coverage in win/pe_image.cc. It is called by the sandbox
     # before sanitizer coverage can initialize. http://crbug.com/484711
@@ -2311,9 +2309,7 @@
 }
 
 test("base_i18n_perftests") {
-  sources = [
-    "i18n/streaming_utf8_validator_perftest.cc",
-  ]
+  sources = [ "i18n/streaming_utf8_validator_perftest.cc" ]
   deps = [
     ":base",
     ":i18n",
@@ -2325,9 +2321,7 @@
 
 if (!is_ios) {
   executable("build_utf8_validator_tables") {
-    sources = [
-      "i18n/build_utf8_validator_tables.cc",
-    ]
+    sources = [ "i18n/build_utf8_validator_tables.cc" ]
     deps = [
       ":base",
       "//build/win:default_exe_manifest",
@@ -2336,9 +2330,7 @@
   }
 
   executable("check_example") {
-    sources = [
-      "check_example.cc",
-    ]
+    sources = [ "check_example.cc" ]
     deps = [
       ":base",
       "//build/win:default_exe_manifest",
@@ -2350,9 +2342,7 @@
   # Target to manually rebuild pe_image_test.dll which is checked into
   # base/test/data/pe_image.
   shared_library("pe_image_test") {
-    sources = [
-      "win/pe_image_test.cc",
-    ]
+    sources = [ "win/pe_image_test.cc" ]
     ldflags = [
       "/DELAYLOAD:cfgmgr32.dll",
       "/DELAYLOAD:shell32.dll",
@@ -2365,9 +2355,7 @@
   }
 
   loadable_module("scoped_handle_test_dll") {
-    sources = [
-      "win/scoped_handle_test_dll.cc",
-    ]
+    sources = [ "win/scoped_handle_test_dll.cc" ]
     deps = [
       ":base",
       "//base/win:base_win_buildflags",
@@ -2379,9 +2367,7 @@
   if (current_cpu == "x64" || (current_cpu == "arm64" && is_win)) {
     # Must be a shared library so that it can be unloaded during testing.
     shared_library("base_profiler_test_support_library") {
-      sources = [
-        "profiler/test_support_library.cc",
-      ]
+      sources = [ "profiler/test_support_library.cc" ]
     }
   }
 }
@@ -2425,10 +2411,8 @@
     "test/data/serializer_test.json",
     "test/data/serializer_test_nowhitespace.json",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 if (is_ios || is_mac) {
@@ -2450,9 +2434,7 @@
   fidl_library("testfidl") {
     namespace = "base.fuchsia"
 
-    sources = [
-      "fuchsia/test.fidl",
-    ]
+    sources = [ "fuchsia/test.fidl" ]
   }
 
   source_set("test_interface_impl") {
@@ -2474,9 +2456,7 @@
     "task/test_task_traits_extension.cc",
     "task/test_task_traits_extension.h",
   ]
-  deps = [
-    ":base",
-  ]
+  deps = [ ":base" ]
 }
 
 test("base_unittests") {
@@ -2804,9 +2784,7 @@
     deps += [ ":base_unittests_arc" ]
   }
 
-  public_deps = [
-    ":base_unittests_bundle_data",
-  ]
+  public_deps = [ ":base_unittests_bundle_data" ]
 
   data = [
     "test/data/",
@@ -3128,9 +3106,7 @@
 action("build_date") {
   script = "//build/write_build_date_header.py"
 
-  outputs = [
-    "$target_gen_dir/generated_build_date.h",
-  ]
+  outputs = [ "$target_gen_dir/generated_build_date.h" ]
 
   args = [
     rebase_path("$target_gen_dir/generated_build_date.h", root_build_dir),
@@ -3153,6 +3129,7 @@
       "metrics/histogram_unittest.nc",
       "observer_list_unittest.nc",
       "optional_unittest.nc",
+      "sequence_checker_unittest.nc",
       "strings/string16_unittest.nc",
       "task/task_traits_extension_unittest.nc",
       "task/task_traits_unittest.nc",
@@ -3212,9 +3189,7 @@
       "android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
     ]
 
-    public_deps = [
-      ":android_runtime_jni_headers",
-    ]
+    public_deps = [ ":android_runtime_jni_headers" ]
   }
 
   generate_jar_jni("android_runtime_jni_headers") {
@@ -3450,16 +3425,12 @@
       ":base",
       ":base_javatests_jni_headers",
     ]
-    sources = [
-      "test/library_loader/early_native_test_helper.cc",
-    ]
+    sources = [ "test/library_loader/early_native_test_helper.cc" ]
   }
 
   generate_jni("base_javatests_jni_headers") {
     testonly = true
-    sources = [
-      "android/javatests/src/org/chromium/base/library_loader/EarlyNativeTest.java",
-    ]
+    sources = [ "android/javatests/src/org/chromium/base/library_loader/EarlyNativeTest.java" ]
   }
 
   android_library("base_java_test_support") {
@@ -3556,9 +3527,7 @@
       ":base_java",
       ":base_java_test_support",
     ]
-    sources = [
-      "test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java",
-    ]
+    sources = [ "test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java" ]
   }
 
   android_library("base_junit_test_support") {
@@ -3650,9 +3619,7 @@
 
   android_library("base_java_unittest_support") {
     testonly = true
-    deps = [
-      ":base_java",
-    ]
+    deps = [ ":base_java" ]
     sources = [
       "test/android/java/src/org/chromium/base/ContentUriTestUtils.java",
       "test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java",
@@ -3662,50 +3629,30 @@
 
 # Keep the list of fuzzer_tests in alphabetical order.
 fuzzer_test("base64_decode_fuzzer") {
-  sources = [
-    "base64_decode_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "base64_decode_fuzzer.cc" ]
+  deps = [ "//base" ]
 }
 
 fuzzer_test("base64_encode_fuzzer") {
-  sources = [
-    "base64_encode_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "base64_encode_fuzzer.cc" ]
+  deps = [ "//base" ]
 }
 
 fuzzer_test("base_json_correctness_fuzzer") {
-  sources = [
-    "json/json_correctness_fuzzer.cc",
-  ]
-  deps = [
-    ":base",
-  ]
+  sources = [ "json/json_correctness_fuzzer.cc" ]
+  deps = [ ":base" ]
   dict = "//testing/libfuzzer/fuzzers/dicts/json.dict"
 }
 
 fuzzer_test("base_json_reader_fuzzer") {
-  sources = [
-    "json/json_reader_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "json/json_reader_fuzzer.cc" ]
+  deps = [ "//base" ]
   dict = "//testing/libfuzzer/fuzzers/dicts/json.dict"
 }
 
 fuzzer_test("base_json_string_escape_fuzzer") {
-  sources = [
-    "json/string_escape_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "json/string_escape_fuzzer.cc" ]
+  deps = [ "//base" ]
 }
 
 if (is_mac) {
@@ -3714,9 +3661,7 @@
       "test/data/mach_port_rendezvous_fuzz/dead_name.textproto",
       "test/data/mach_port_rendezvous_fuzz/send.textproto",
     ]
-    inputs = [
-      "//testing/libfuzzer/fuzzers/mach/mach_message.proto",
-    ]
+    inputs = [ "//testing/libfuzzer/fuzzers/mach/mach_message.proto" ]
     output_pattern = "$target_gen_dir/base_mach_port_rendezvous_corpus/{{source_name_part}}.binarypb"
     args = [
       "--encode=mach_fuzzer.MachMessage",
@@ -3726,9 +3671,7 @@
     ]
   }
   fuzzer_test("base_mach_port_rendezvous_fuzzer") {
-    sources = [
-      "mac/mach_port_rendezvous_fuzzer.cc",
-    ]
+    sources = [ "mac/mach_port_rendezvous_fuzzer.cc" ]
     deps = [
       "//base",
       "//testing/libfuzzer/fuzzers/mach:converter",
@@ -3740,36 +3683,22 @@
 }
 
 fuzzer_test("string_number_conversions_fuzzer") {
-  sources = [
-    "strings/string_number_conversions_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "strings/string_number_conversions_fuzzer.cc" ]
+  deps = [ "//base" ]
 }
 
 fuzzer_test("string_tokenizer_fuzzer") {
-  sources = [
-    "strings/string_tokenizer_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "strings/string_tokenizer_fuzzer.cc" ]
+  deps = [ "//base" ]
 }
 
 fuzzer_test("utf_string_conversions_fuzzer") {
-  sources = [
-    "strings/utf_string_conversions_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "strings/utf_string_conversions_fuzzer.cc" ]
+  deps = [ "//base" ]
 }
 
 fuzzer_test("pickle_fuzzer") {
-  sources = [
-    "pickle_fuzzer.cc",
-  ]
+  sources = [ "pickle_fuzzer.cc" ]
   deps = [
     "//base",
     "//base/test:test_support",
diff --git a/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java b/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java
index 990b717..f763acaf 100644
--- a/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java
+++ b/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java
@@ -432,15 +432,25 @@
         // JniStaticTestMocker<ClassNameJni> TEST_HOOKS = new JniStaticTestMocker<>() {
         //      @Override
         //      public static setInstanceForTesting(ClassNameJni instance) {
+        //          if (!GEN_JNI.TESTING_ENABLED) {
+        //              throw new RuntimeException($mocksNotEnabledExceptionString);
+        //          }
         //          testInstance = instance;
         //      }
         // }
-        MethodSpec testHookMockerMethod = MethodSpec.methodBuilder("setInstanceForTesting")
-                                                  .addModifiers(Modifier.PUBLIC)
-                                                  .addAnnotation(Override.class)
-                                                  .addParameter(nativeInterfaceType, "instance")
-                                                  .addStatement("$N = instance", testTarget)
-                                                  .build();
+        String mocksNotEnabledExceptionString =
+                "Tried to set a JNI mock when mocks aren't enabled!";
+        MethodSpec testHookMockerMethod =
+                MethodSpec.methodBuilder("setInstanceForTesting")
+                        .addModifiers(Modifier.PUBLIC)
+                        .addAnnotation(Override.class)
+                        .addParameter(nativeInterfaceType, "instance")
+                        .beginControlFlow("if (!$T.$N)", mNativeClassName, NATIVE_TEST_FIELD_NAME)
+                        .addStatement(
+                                "throw new RuntimeException($S)", mocksNotEnabledExceptionString)
+                        .endControlFlow()
+                        .addStatement("$N = instance", testTarget)
+                        .build();
 
         // Make the anonymous TEST_HOOK class.
         ParameterizedTypeName genericMockerInterface = ParameterizedTypeName.get(
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc
index 357e6cb7..e0098471 100644
--- a/base/json/json_parser.cc
+++ b/base/json/json_parser.cc
@@ -248,11 +248,12 @@
 }
 
 bool JSONParser::EatComment() {
-  Optional<StringPiece> comment_start = ConsumeChars(2);
+  Optional<StringPiece> comment_start = PeekChars(2);
   if (!comment_start)
     return false;
 
   if (comment_start == "//") {
+    ConsumeChars(2);
     // Single line comment, read to newline.
     while (Optional<char> c = PeekChar()) {
       if (c == '\n' || c == '\r')
@@ -260,6 +261,7 @@
       ConsumeChar();
     }
   } else if (comment_start == "/*") {
+    ConsumeChars(2);
     char previous_char = '\0';
     // Block comment, read until end marker.
     while (Optional<char> c = PeekChar()) {
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc
index c41b8a8..fe0b9d0 100644
--- a/base/json/json_reader_unittest.cc
+++ b/base/json/json_reader_unittest.cc
@@ -76,6 +76,9 @@
   ASSERT_TRUE(root);
   EXPECT_TRUE(root->is_int());
   EXPECT_EQ(44, root->GetInt());
+
+  // At one point, this parsed successfully as the value three.
+  EXPECT_FALSE(JSONReader::Read("/33"));
 }
 
 TEST(JSONReaderTest, Ints) {
diff --git a/base/memory/weak_ptr.cc b/base/memory/weak_ptr.cc
index 0efcc44..da57943 100644
--- a/base/memory/weak_ptr.cc
+++ b/base/memory/weak_ptr.cc
@@ -25,8 +25,8 @@
 }
 
 bool WeakReference::Flag::IsValid() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_)
-      << "WeakPtrs must be checked on the same sequenced thread.";
+  // WeakPtrs must be checked on the same sequenced thread.
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return !invalidated_.IsSet();
 }
 
diff --git a/base/sequence_checker.h b/base/sequence_checker.h
index 8477dde..60ffd75 100644
--- a/base/sequence_checker.h
+++ b/base/sequence_checker.h
@@ -8,10 +8,12 @@
 #include "base/compiler_specific.h"
 #include "base/logging.h"
 #include "base/sequence_checker_impl.h"
+#include "base/strings/string_piece.h"
 #include "build/build_config.h"
 
 // SequenceChecker is a helper class used to help verify that some methods of a
-// class are called sequentially (for thread-safety).
+// class are called sequentially (for thread-safety). It supports thread safety
+// annotations (see base/thread_annotations.h).
 //
 // Use the macros below instead of the SequenceChecker directly so that the
 // unused member doesn't result in an extra byte (four when padded) per
@@ -43,16 +45,36 @@
 //     void MyMethod() {
 //       DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
 //       ... (do stuff) ...
+//       MyOtherMethod();
+//     }
+//
+//     void MyOtherMethod()
+//         VALID_CONTEXT_REQUIRED(my_sequence_checker_) {
+//       foo_ = 42;
 //     }
 //
 //    private:
+//      // GUARDED_BY_CONTEXT() enforces that this member is only
+//      // accessed from a scope that invokes DCHECK_CALLED_ON_VALID_SEQUENCE()
+//      // or from a function annotated with VALID_CONTEXT_REQUIRED(). A
+//      // DCHECK build will not compile if the member is accessed and these
+//      // conditions are not met.
+//     int foo_ GUARDED_BY_CONTEXT(my_sequence_checker_);
+//
 //     SEQUENCE_CHECKER(my_sequence_checker_);
 //   }
 
+#define SEQUENCE_CHECKER_INTERNAL_CONCAT2(a, b) a##b
+#define SEQUENCE_CHECKER_INTERNAL_CONCAT(a, b) \
+  SEQUENCE_CHECKER_INTERNAL_CONCAT2(a, b)
+#define SEQUENCE_CHECKER_INTERNAL_UID(prefix) \
+  SEQUENCE_CHECKER_INTERNAL_CONCAT(prefix, __LINE__)
+
 #if DCHECK_IS_ON()
 #define SEQUENCE_CHECKER(name) base::SequenceChecker name
-#define DCHECK_CALLED_ON_VALID_SEQUENCE(name) \
-  DCHECK((name).CalledOnValidSequence())
+#define DCHECK_CALLED_ON_VALID_SEQUENCE(name, ...)                   \
+  base::ScopedValidateSequenceChecker SEQUENCE_CHECKER_INTERNAL_UID( \
+      scoped_validate_sequence_checker_)(name, ##__VA_ARGS__);
 #define DETACH_FROM_SEQUENCE(name) (name).DetachFromSequence()
 #else  // DCHECK_IS_ON()
 #if __OBJC__ && defined(OS_IOS) && !HAS_FEATURE(objc_cxx_static_assert)
@@ -61,7 +83,7 @@
 #else
 #define SEQUENCE_CHECKER(name) static_assert(true, "")
 #endif
-#define DCHECK_CALLED_ON_VALID_SEQUENCE(name) EAT_STREAM_PARAMETERS
+#define DCHECK_CALLED_ON_VALID_SEQUENCE(name, ...) EAT_STREAM_PARAMETERS
 #define DETACH_FROM_SEQUENCE(name)
 #endif  // DCHECK_IS_ON()
 
@@ -71,7 +93,9 @@
 //
 // Note: You should almost always use the SequenceChecker class (through the
 // above macros) to get the right version for your build configuration.
-class SequenceCheckerDoNothing {
+// Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
+// order to support thread_annotations.h.
+class LOCKABLE SequenceCheckerDoNothing {
  public:
   SequenceCheckerDoNothing() = default;
 
@@ -96,6 +120,24 @@
 };
 #endif  // DCHECK_IS_ON()
 
+class SCOPED_LOCKABLE ScopedValidateSequenceChecker {
+ public:
+  explicit ScopedValidateSequenceChecker(const SequenceChecker& checker)
+      EXCLUSIVE_LOCK_FUNCTION(checker) {
+    DCHECK(checker.CalledOnValidSequence());
+  }
+
+  explicit ScopedValidateSequenceChecker(const SequenceChecker& checker,
+                                         const StringPiece& msg)
+      EXCLUSIVE_LOCK_FUNCTION(checker) {
+    DCHECK(checker.CalledOnValidSequence()) << msg;
+  }
+
+  ~ScopedValidateSequenceChecker() UNLOCK_FUNCTION() {}
+
+ private:
+};
+
 }  // namespace base
 
 #endif  // BASE_SEQUENCE_CHECKER_H_
diff --git a/base/sequence_checker_impl.h b/base/sequence_checker_impl.h
index 3599fb8..ea0fbb5 100644
--- a/base/sequence_checker_impl.h
+++ b/base/sequence_checker_impl.h
@@ -21,7 +21,9 @@
 //
 // Note: You should almost always use the SequenceChecker class to get the right
 // version for your build configuration.
-class BASE_EXPORT SequenceCheckerImpl {
+// Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
+// order to support thread_annotations.h.
+class LOCKABLE BASE_EXPORT SequenceCheckerImpl {
  public:
   SequenceCheckerImpl();
   ~SequenceCheckerImpl();
diff --git a/base/sequence_checker_unittest.cc b/base/sequence_checker_unittest.cc
index 537facc..58c668d 100644
--- a/base/sequence_checker_unittest.cc
+++ b/base/sequence_checker_unittest.cc
@@ -230,27 +230,27 @@
       SequenceToken::Create());
   SEQUENCE_CHECKER(my_sequence_checker);
 
-  // Don't expect a DCHECK death when a SequenceChecker is used on the right
-  // sequence.
-  DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
-
+  {
+    // Don't expect a DCHECK death when a SequenceChecker is used on the right
+    // sequence.
+    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
+  }
   scope.reset();
 
 #if DCHECK_IS_ON()
   // Expect DCHECK death when used on a different sequence.
-  EXPECT_DCHECK_DEATH({
-    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
-  });
+  EXPECT_DCHECK_DEATH(
+      { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker); });
 #else
     // Happily no-ops on non-dcheck builds.
-    DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
+  DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
 #endif
 
   DETACH_FROM_SEQUENCE(my_sequence_checker);
 
   // Don't expect a DCHECK death when a SequenceChecker is used for the first
   // time after having been detached.
-  DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
+  DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
 }
 
 // Owns a SequenceCheckerImpl, and asserts that CalledOnValidSequence() is valid
diff --git a/base/sequence_checker_unittest.nc b/base/sequence_checker_unittest.nc
new file mode 100644
index 0000000..61b6bf00
--- /dev/null
+++ b/base/sequence_checker_unittest.nc
@@ -0,0 +1,43 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a "No Compile Test" suite.
+// https://dev.chromium.org/developers/testing/no-compile-tests
+
+#include "base/sequence_checker.h"
+
+namespace {
+
+class SequenceAffine {
+ public:
+  void BuggyIncrement();
+
+  void Increment() VALID_CONTEXT_REQUIRED(sequence_checker_) {
+    ++counter_;
+  }
+
+ private:
+  int counter_ GUARDED_BY_CONTEXT(sequence_checker_);
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+#if defined(NCTEST_ACCESS_WITHOUT_CHECK)  // [r"fatal error: writing variable 'counter_' requires holding mutex 'sequence_checker_' exclusively"]
+
+void SequenceAffine::BuggyIncrement() {
+  // Member access without sequence_checker_ assertion.
+  ++counter_;
+}
+
+#elif defined(NCTEST_CALL_WITHOUT_CHECK)  // [r"fatal error: calling function 'Increment' requires holding mutex 'sequence_checker_' exclusively"]
+
+void SequenceAffine::BuggyIncrement() {
+  // Function call without sequence_checker_ assertion.
+  Increment();
+}
+
+
+#endif
+
+}  // namespace
\ No newline at end of file
diff --git a/base/third_party/dynamic_annotations/BUILD.gn b/base/third_party/dynamic_annotations/BUILD.gn
index 0fc4bf7..251a1f00 100644
--- a/base/third_party/dynamic_annotations/BUILD.gn
+++ b/base/third_party/dynamic_annotations/BUILD.gn
@@ -7,9 +7,7 @@
   # dummy target in order for clients to not have to special-case the
   # dependency.
   source_set("dynamic_annotations") {
-    sources = [
-      "dynamic_annotations.h",
-    ]
+    sources = [ "dynamic_annotations.h" ]
   }
 } else {
   # Should be static library, see documentation on //base:base for discussion.
diff --git a/base/thread_annotations.h b/base/thread_annotations.h
index bba3ed7..fdd32f8 100644
--- a/base/thread_annotations.h
+++ b/base/thread_annotations.h
@@ -32,6 +32,7 @@
 #ifndef BASE_THREAD_ANNOTATIONS_H_
 #define BASE_THREAD_ANNOTATIONS_H_
 
+#include "base/logging.h"
 #include "build/build_config.h"
 
 #if defined(__clang__)
@@ -237,4 +238,27 @@
 
 }  // namespace thread_safety_analysis
 
+// The above is imported as-is from abseil-cpp. The following Chromium-specific
+// synonyms are added for Chromium concepts (SequenceChecker/ThreadChecker).
+#if DCHECK_IS_ON()
+
+// Equivalent to GUARDED_BY for SequenceChecker/ThreadChecker. Currently,
+// clang's error message "requires holding mutex" is misleading. Usage of this
+// macro is discouraged until the message is updated.
+// TODO(etiennep): Update comment above once clang's error message is updated.
+#define GUARDED_BY_CONTEXT(name) GUARDED_BY(name)
+
+// Equivalent to EXCLUSIVE_LOCKS_REQUIRED for SequenceChecker/ThreadChecker.
+// Currently, clang's error message "requires holding mutex" is misleading.
+// Usage of this macro is discouraged until the message is updated.
+// TODO(etiennep): Update comment above once clang's error message is updated.
+#define VALID_CONTEXT_REQUIRED(name) EXCLUSIVE_LOCKS_REQUIRED(name)
+
+#else  // DCHECK_IS_ON()
+
+#define GUARDED_BY_CONTEXT(name)
+#define VALID_CONTEXT_REQUIRED(name)
+
+#endif  // DCHECK_IS_ON()
+
 #endif  // BASE_THREAD_ANNOTATIONS_H_
diff --git a/base/threading/thread_checker.h b/base/threading/thread_checker.h
index 5e3cb85..e149534 100644
--- a/base/threading/thread_checker.h
+++ b/base/threading/thread_checker.h
@@ -7,10 +7,13 @@
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/thread_annotations.h"
 #include "base/threading/thread_checker_impl.h"
 
 // ThreadChecker is a helper class used to help verify that some methods of a
-// class are called from the same thread (for thread-affinity).
+// class are called from the same thread (for thread-affinity).  It supports
+// thread safety annotations (see base/thread_annotations.h).
 //
 // Use the macros below instead of the ThreadChecker directly so that the unused
 // member doesn't result in an extra byte (four when padded) per instance in
@@ -56,17 +59,32 @@
 //       ... (do stuff) ...
 //     }
 //
+//     void MyOtherMethod()
+//         VALID_CONTEXT_REQUIRED(thread_checker_) {
+//       foo_ = 42;
+//     }
+//
 //    private:
+//     int foo_ GUARDED_BY_CONTEXT(thread_checker_);
+//
 //     THREAD_CHECKER(thread_checker_);
 //   }
 
+#define THREAD_CHECKER_INTERNAL_CONCAT2(a, b) a##b
+#define THREAD_CHECKER_INTERNAL_CONCAT(a, b) \
+  THREAD_CHECKER_INTERNAL_CONCAT2(a, b)
+#define THREAD_CHECKER_INTERNAL_UID(prefix) \
+  THREAD_CHECKER_INTERNAL_CONCAT(prefix, __LINE__)
+
 #if DCHECK_IS_ON()
 #define THREAD_CHECKER(name) base::ThreadChecker name
-#define DCHECK_CALLED_ON_VALID_THREAD(name) DCHECK((name).CalledOnValidThread())
+#define DCHECK_CALLED_ON_VALID_THREAD(name, ...)                 \
+  base::ScopedValidateThreadChecker THREAD_CHECKER_INTERNAL_UID( \
+      scoped_validate_thread_checker_)(name, ##__VA_ARGS__);
 #define DETACH_FROM_THREAD(name) (name).DetachFromThread()
 #else  // DCHECK_IS_ON()
 #define THREAD_CHECKER(name) static_assert(true, "")
-#define DCHECK_CALLED_ON_VALID_THREAD(name) EAT_STREAM_PARAMETERS
+#define DCHECK_CALLED_ON_VALID_THREAD(name, ...) EAT_STREAM_PARAMETERS
 #define DETACH_FROM_THREAD(name)
 #endif  // DCHECK_IS_ON()
 
@@ -76,7 +94,9 @@
 //
 // Note: You should almost always use the ThreadChecker class (through the above
 // macros) to get the right version for your build configuration.
-class ThreadCheckerDoNothing {
+// Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
+// order to support thread_annotations.h.
+class LOCKABLE ThreadCheckerDoNothing {
  public:
   ThreadCheckerDoNothing() = default;
 
@@ -104,6 +124,25 @@
 };
 #endif  // DCHECK_IS_ON()
 
+class SCOPED_LOCKABLE ScopedValidateThreadChecker {
+ public:
+  explicit ScopedValidateThreadChecker(const ThreadChecker& checker)
+      EXCLUSIVE_LOCK_FUNCTION(checker) {
+    DCHECK(checker.CalledOnValidThread());
+  }
+
+  explicit ScopedValidateThreadChecker(const ThreadChecker& checker,
+                                       const StringPiece& msg)
+      EXCLUSIVE_LOCK_FUNCTION(checker) {
+    DCHECK(checker.CalledOnValidThread()) << msg;
+  }
+
+  ~ScopedValidateThreadChecker() UNLOCK_FUNCTION() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedValidateThreadChecker);
+};
+
 }  // namespace base
 
 #endif  // BASE_THREADING_THREAD_CHECKER_H_
diff --git a/base/threading/thread_checker_impl.h b/base/threading/thread_checker_impl.h
index e911cec..b325db6a 100644
--- a/base/threading/thread_checker_impl.h
+++ b/base/threading/thread_checker_impl.h
@@ -20,7 +20,9 @@
 //
 // Note: You should almost always use the ThreadChecker class to get the right
 // version for your build configuration.
-class BASE_EXPORT ThreadCheckerImpl {
+// Note: This is only a check, not a "lock". It is marked "LOCKABLE" only in
+// order to support thread_annotations.h.
+class LOCKABLE BASE_EXPORT ThreadCheckerImpl {
  public:
   ThreadCheckerImpl();
   ~ThreadCheckerImpl();
diff --git a/base/threading/thread_checker_unittest.cc b/base/threading/thread_checker_unittest.cc
index 5041bafd..d195889 100644
--- a/base/threading/thread_checker_unittest.cc
+++ b/base/threading/thread_checker_unittest.cc
@@ -321,8 +321,6 @@
 
   void ExpectNoDeathOnOtherThreadAfterDetach() {
     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_)
-        << "Make sure it compiles when DCHECK is off";
   }
 
  protected:
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 09d00dd..4e416e64 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -581,9 +581,7 @@
     deps += [ "//gpu/vulkan/init" ]
   }
   if (!is_android) {
-    data_deps = [
-      "//third_party/mesa_headers",
-    ]
+    data_deps = [ "//third_party/mesa_headers" ]
   }
 }
 
@@ -743,9 +741,7 @@
   ]
 
   if (!is_android) {
-    data = [
-      "//components/viz/test/data/",
-    ]
+    data = [ "//components/viz/test/data/" ]
   }
 
   if (is_win) {
@@ -786,9 +782,7 @@
     "//ui/gl",
     "//ui/gl:test_support",
   ]
-  data_deps = [
-    "//third_party/mesa_headers",
-  ]
+  data_deps = [ "//third_party/mesa_headers" ]
 
   if (enable_vulkan) {
     deps += [
@@ -857,9 +851,7 @@
   # This target should not require the Chrome executable to run.
   assert_no_deps = [ "//chrome" ]
 
-  data = [
-    "//components/viz/test/data/",
-  ]
+  data = [ "//components/viz/test/data/" ]
 
   data_deps = [
     # Needed for isolate script to execute.
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc
index 30cc0b3..361f205 100644
--- a/cc/metrics/compositor_frame_reporter.cc
+++ b/cc/metrics/compositor_frame_reporter.cc
@@ -145,9 +145,11 @@
 
 CompositorFrameReporter::CompositorFrameReporter(
     const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+    const viz::BeginFrameId& id,
     LatencyUkmReporter* latency_ukm_reporter,
     bool is_single_threaded)
-    : is_single_threaded_(is_single_threaded),
+    : frame_id_(id),
+      is_single_threaded_(is_single_threaded),
       active_trackers_(active_trackers),
       latency_ukm_reporter_(latency_ukm_reporter) {
   TRACE_EVENT_ASYNC_BEGIN1("cc,benchmark", "PipelineReporter", this,
diff --git a/cc/metrics/compositor_frame_reporter.h b/cc/metrics/compositor_frame_reporter.h
index 85c9d43..be72ea5 100644
--- a/cc/metrics/compositor_frame_reporter.h
+++ b/cc/metrics/compositor_frame_reporter.h
@@ -13,6 +13,7 @@
 #include "cc/cc_export.h"
 #include "cc/metrics/begin_main_frame_metrics.h"
 #include "cc/metrics/frame_sequence_tracker.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_timing_details.h"
 
 namespace viz {
@@ -118,6 +119,7 @@
 
   CompositorFrameReporter(
       const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+      const viz::BeginFrameId& id,
       LatencyUkmReporter* latency_ukm_reporter,
       bool is_single_threaded = false);
   ~CompositorFrameReporter();
@@ -126,6 +128,8 @@
   CompositorFrameReporter& operator=(const CompositorFrameReporter& reporter) =
       delete;
 
+  const viz::BeginFrameId frame_id_;
+
   void MissedSubmittedFrame();
 
   // Note that the started stage may be reported to UMA. If the histogram is
diff --git a/cc/metrics/compositor_frame_reporter_unittest.cc b/cc/metrics/compositor_frame_reporter_unittest.cc
index 18a67030..e6f2d137 100644
--- a/cc/metrics/compositor_frame_reporter_unittest.cc
+++ b/cc/metrics/compositor_frame_reporter_unittest.cc
@@ -19,6 +19,7 @@
   CompositorFrameReporterTest()
       : pipeline_reporter_(
             std::make_unique<CompositorFrameReporter>(&active_trackers,
+                                                      viz::BeginFrameId(),
                                                       nullptr)) {
     AdvanceNowByMs(1);
   }
diff --git a/cc/metrics/compositor_frame_reporting_controller.cc b/cc/metrics/compositor_frame_reporting_controller.cc
index 41d13a0b..022006c 100644
--- a/cc/metrics/compositor_frame_reporting_controller.cc
+++ b/cc/metrics/compositor_frame_reporting_controller.cc
@@ -51,7 +51,8 @@
   return base::TimeTicks::Now();
 }
 
-void CompositorFrameReportingController::WillBeginImplFrame() {
+void CompositorFrameReportingController::WillBeginImplFrame(
+    const viz::BeginFrameId& id) {
   base::TimeTicks begin_time = Now();
   if (reporters_[PipelineStage::kBeginImplFrame]) {
     // If the the reporter is replaced in this stage, it means that Impl frame
@@ -61,19 +62,22 @@
         begin_time);
   }
   std::unique_ptr<CompositorFrameReporter> reporter =
-      std::make_unique<CompositorFrameReporter>(
-          &active_trackers_, latency_ukm_reporter_.get(), is_single_threaded_);
+      std::make_unique<CompositorFrameReporter>(&active_trackers_, id,
+                                                latency_ukm_reporter_.get(),
+                                                is_single_threaded_);
   reporter->StartStage(StageType::kBeginImplFrameToSendBeginMainFrame,
                        begin_time);
   reporters_[PipelineStage::kBeginImplFrame] = std::move(reporter);
 }
 
-void CompositorFrameReportingController::WillBeginMainFrame() {
+void CompositorFrameReportingController::WillBeginMainFrame(
+    const viz::BeginFrameId& id) {
   if (reporters_[PipelineStage::kBeginImplFrame]) {
     // We need to use .get() below because operator<< in std::unique_ptr is a
     // C++20 feature.
     DCHECK_NE(reporters_[PipelineStage::kBeginMainFrame].get(),
               reporters_[PipelineStage::kBeginImplFrame].get());
+    DCHECK_EQ(reporters_[PipelineStage::kBeginImplFrame]->frame_id_, id);
     reporters_[PipelineStage::kBeginImplFrame]->StartStage(
         StageType::kSendBeginMainFrameToCommit, Now());
     AdvanceReporterStage(PipelineStage::kBeginImplFrame,
@@ -83,7 +87,7 @@
     // beginMain frame before next BeginImplFrame (Not reached the ImplFrame
     // deadline yet). So will start a new reporter at BeginMainFrame.
     std::unique_ptr<CompositorFrameReporter> reporter =
-        std::make_unique<CompositorFrameReporter>(&active_trackers_,
+        std::make_unique<CompositorFrameReporter>(&active_trackers_, id,
                                                   latency_ukm_reporter_.get(),
                                                   is_single_threaded_);
     reporter->StartStage(StageType::kSendBeginMainFrameToCommit, Now());
@@ -91,9 +95,10 @@
   }
 }
 
-void CompositorFrameReportingController::BeginMainFrameAborted() {
+void CompositorFrameReportingController::BeginMainFrameAborted(
+    const viz::BeginFrameId& id) {
   DCHECK(reporters_[PipelineStage::kBeginMainFrame]);
-
+  DCHECK_EQ(reporters_[PipelineStage::kBeginMainFrame]->frame_id_, id);
   auto& begin_main_reporter = reporters_[PipelineStage::kBeginMainFrame];
   begin_main_reporter->OnAbortBeginMainFrame();
 
@@ -145,7 +150,9 @@
 }
 
 void CompositorFrameReportingController::DidSubmitCompositorFrame(
-    uint32_t frame_token) {
+    uint32_t frame_token,
+    const viz::BeginFrameId& current_frame_id,
+    const viz::BeginFrameId& last_activated_frame_id) {
   // If there is no reporter in active stage and there exists a finished
   // BeginImplFrame reporter (i.e. if impl-frame has finished), then advance it
   // to the activate stage.
@@ -160,7 +167,6 @@
                            PipelineStage::kActivate);
     }
   }
-
   if (!reporters_[PipelineStage::kActivate])
     return;
 
@@ -172,10 +178,13 @@
                                             std::move(submitted_reporter));
 }
 
-void CompositorFrameReportingController::OnFinishImplFrame() {
+void CompositorFrameReportingController::OnFinishImplFrame(
+    const viz::BeginFrameId& id) {
   if (reporters_[PipelineStage::kBeginImplFrame]) {
+    DCHECK_EQ(reporters_[PipelineStage::kBeginImplFrame]->frame_id_, id);
     reporters_[PipelineStage::kBeginImplFrame]->OnFinishImplFrame(Now());
   } else if (reporters_[PipelineStage::kBeginMainFrame]) {
+    DCHECK_EQ(reporters_[PipelineStage::kBeginMainFrame]->frame_id_, id);
     auto& begin_main_reporter = reporters_[PipelineStage::kBeginMainFrame];
     begin_main_reporter->OnFinishImplFrame(Now());
 
diff --git a/cc/metrics/compositor_frame_reporting_controller.h b/cc/metrics/compositor_frame_reporting_controller.h
index 8848f43..3b1f43ca 100644
--- a/cc/metrics/compositor_frame_reporting_controller.h
+++ b/cc/metrics/compositor_frame_reporting_controller.h
@@ -49,16 +49,19 @@
       const CompositorFrameReportingController&) = delete;
 
   // Events to signal Beginning/Ending of phases.
-  virtual void WillBeginImplFrame();
-  virtual void WillBeginMainFrame();
-  virtual void BeginMainFrameAborted();
+  virtual void WillBeginImplFrame(const viz::BeginFrameId& id);
+  virtual void WillBeginMainFrame(const viz::BeginFrameId& id);
+  virtual void BeginMainFrameAborted(const viz::BeginFrameId& id);
   virtual void WillInvalidateOnImplSide();
   virtual void WillCommit();
   virtual void DidCommit();
   virtual void WillActivate();
   virtual void DidActivate();
-  virtual void DidSubmitCompositorFrame(uint32_t frame_token);
-  virtual void OnFinishImplFrame();
+  virtual void DidSubmitCompositorFrame(
+      uint32_t frame_token,
+      const viz::BeginFrameId& current_frame_id,
+      const viz::BeginFrameId& last_activated_frame_id);
+  virtual void OnFinishImplFrame(const viz::BeginFrameId& id);
   virtual void DidPresentCompositorFrame(
       uint32_t frame_token,
       const viz::FrameTimingDetails& details);
@@ -89,6 +92,8 @@
  private:
   void AdvanceReporterStage(PipelineStage start, PipelineStage target);
 
+  viz::BeginFrameId last_submitted_frame_id_;
+
   // Used by the managed reporters to differentiate the histogram names when
   // reporting to UMA.
   const bool is_single_threaded_;
diff --git a/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
index 469550e..e35663d7 100644
--- a/cc/metrics/compositor_frame_reporting_controller_unittest.cc
+++ b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -45,11 +45,15 @@
 
 class CompositorFrameReportingControllerTest : public testing::Test {
  public:
-  CompositorFrameReportingControllerTest() : reporting_controller_(this) {}
+  CompositorFrameReportingControllerTest() : reporting_controller_(this) {
+    current_id_ = viz::BeginFrameId(1, 1);
+  }
 
   // The following functions simulate the actions that would
   // occur for each phase of the reporting controller.
-  void SimulateBeginImplFrame() { reporting_controller_.WillBeginImplFrame(); }
+  void SimulateBeginImplFrame() {
+    reporting_controller_.WillBeginImplFrame(current_id_);
+  }
 
   void SimulateBeginMainFrame() {
     if (!reporting_controller_.reporters()[CompositorFrameReportingController::
@@ -58,7 +62,7 @@
     CHECK(
         reporting_controller_.reporters()[CompositorFrameReportingController::
                                               PipelineStage::kBeginImplFrame]);
-    reporting_controller_.WillBeginMainFrame();
+    reporting_controller_.WillBeginMainFrame(current_id_);
   }
 
   void SimulateCommit(std::unique_ptr<BeginMainFrameMetrics> blink_breakdown) {
@@ -81,6 +85,7 @@
               [CompositorFrameReportingController::PipelineStage::kCommit]);
     reporting_controller_.WillActivate();
     reporting_controller_.DidActivate();
+    last_activated_id_ = viz::BeginFrameId(current_id_);
   }
 
   void SimulateSubmitCompositorFrame(uint32_t frame_token) {
@@ -89,7 +94,8 @@
       SimulateActivate();
     CHECK(reporting_controller_.reporters()
               [CompositorFrameReportingController::PipelineStage::kActivate]);
-    reporting_controller_.DidSubmitCompositorFrame(frame_token);
+    reporting_controller_.DidSubmitCompositorFrame(frame_token, current_id_,
+                                                   last_activated_id_);
   }
 
   void SimulatePresentCompositorFrame() {
@@ -102,6 +108,8 @@
 
  protected:
   TestCompositorFrameReportingController reporting_controller_;
+  viz::BeginFrameId current_id_;
+  viz::BeginFrameId last_activated_id_;
 
  private:
   viz::FrameTokenGenerator next_token_;
@@ -119,18 +127,18 @@
   // - 4 Simultaneous Reporters
 
   // BF
-  reporting_controller_.WillBeginImplFrame();
+  reporting_controller_.WillBeginImplFrame(current_id_);
   EXPECT_EQ(1, reporting_controller_.ActiveReporters());
 
   // BF -> BF
   // Should replace previous reporter.
-  reporting_controller_.WillBeginImplFrame();
+  reporting_controller_.WillBeginImplFrame(current_id_);
   EXPECT_EQ(1, reporting_controller_.ActiveReporters());
 
   // BF -> BMF -> BF
   // Should add new reporter.
-  reporting_controller_.WillBeginMainFrame();
-  reporting_controller_.WillBeginImplFrame();
+  reporting_controller_.WillBeginMainFrame(current_id_);
+  reporting_controller_.WillBeginImplFrame(current_id_);
   EXPECT_EQ(2, reporting_controller_.ActiveReporters());
 
   // BF -> BMF -> BF -> Commit
@@ -141,16 +149,18 @@
 
   // BF -> BMF -> BF -> Commit -> BMF -> Activate -> Commit -> Activation
   // Having two reporters at Activate phase should delete the older one.
-  reporting_controller_.WillBeginMainFrame();
+  reporting_controller_.WillBeginMainFrame(current_id_);
   reporting_controller_.WillActivate();
   reporting_controller_.DidActivate();
+  last_activated_id_ = viz::BeginFrameId(current_id_);
   reporting_controller_.WillCommit();
   reporting_controller_.DidCommit();
   reporting_controller_.WillActivate();
   reporting_controller_.DidActivate();
   EXPECT_EQ(1, reporting_controller_.ActiveReporters());
 
-  reporting_controller_.DidSubmitCompositorFrame(0);
+  reporting_controller_.DidSubmitCompositorFrame(0, current_id_,
+                                                 last_activated_id_);
   EXPECT_EQ(0, reporting_controller_.ActiveReporters());
 
   // 4 simultaneous reporters active.
@@ -242,11 +252,12 @@
 TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted) {
   base::HistogramTester histogram_tester;
 
-  reporting_controller_.WillBeginImplFrame();
-  reporting_controller_.WillBeginMainFrame();
-  reporting_controller_.BeginMainFrameAborted();
-  reporting_controller_.OnFinishImplFrame();
-  reporting_controller_.DidSubmitCompositorFrame(1);
+  reporting_controller_.WillBeginImplFrame(current_id_);
+  reporting_controller_.WillBeginMainFrame(current_id_);
+  reporting_controller_.BeginMainFrameAborted(current_id_);
+  reporting_controller_.OnFinishImplFrame(current_id_);
+  reporting_controller_.DidSubmitCompositorFrame(1, current_id_,
+                                                 last_activated_id_);
 
   viz::FrameTimingDetails details = {};
   reporting_controller_.DidPresentCompositorFrame(1, details);
diff --git a/cc/metrics/compositor_timing_history.cc b/cc/metrics/compositor_timing_history.cc
index d2bf9e2..fdb8a44 100644
--- a/cc/metrics/compositor_timing_history.cc
+++ b/cc/metrics/compositor_timing_history.cc
@@ -710,7 +710,7 @@
   viz::BeginFrameArgs::BeginFrameArgsType frame_type = args.type;
   base::TimeTicks frame_time = args.frame_time;
 
-  compositor_frame_reporting_controller_->WillBeginImplFrame();
+  compositor_frame_reporting_controller_->WillBeginImplFrame(args.frame_id);
 
   // The check for whether a BeginMainFrame was sent anytime between two
   // BeginImplFrames protects us from not detecting a fast main thread that
@@ -729,11 +729,12 @@
   did_send_begin_main_frame_ = false;
 }
 
-void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw) {
+void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw,
+                                                  const viz::BeginFrameId& id) {
   if (!needs_redraw)
     SetCompositorDrawingContinuously(false);
 
-  compositor_frame_reporting_controller_->OnFinishImplFrame();
+  compositor_frame_reporting_controller_->OnFinishImplFrame(id);
 }
 
 void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() {
@@ -743,16 +744,15 @@
 }
 
 void CompositorTimingHistory::WillBeginMainFrame(
-    bool on_critical_path,
-    base::TimeTicks main_frame_time) {
+    const viz::BeginFrameArgs& args) {
   DCHECK_EQ(base::TimeTicks(), begin_main_frame_sent_time_);
   DCHECK_EQ(base::TimeTicks(), begin_main_frame_frame_time_);
 
-  compositor_frame_reporting_controller_->WillBeginMainFrame();
+  compositor_frame_reporting_controller_->WillBeginMainFrame(args.frame_id);
 
-  begin_main_frame_on_critical_path_ = on_critical_path;
+  begin_main_frame_on_critical_path_ = args.on_critical_path;
   begin_main_frame_sent_time_ = Now();
-  begin_main_frame_frame_time_ = main_frame_time;
+  begin_main_frame_frame_time_ = args.frame_time;
 
   did_send_begin_main_frame_ = true;
   SetBeginMainFrameNeededContinuously(true);
@@ -765,8 +765,9 @@
   begin_main_frame_start_time_ = main_thread_start_time;
 }
 
-void CompositorTimingHistory::BeginMainFrameAborted() {
-  compositor_frame_reporting_controller_->BeginMainFrameAborted();
+void CompositorTimingHistory::BeginMainFrameAborted(
+    const viz::BeginFrameId& id) {
+  compositor_frame_reporting_controller_->BeginMainFrameAborted(id);
   SetBeginMainFrameCommittingContinuously(false);
   base::TimeTicks begin_main_frame_end_time = Now();
   DidBeginMainFrame(begin_main_frame_end_time);
@@ -1064,9 +1065,13 @@
   draw_start_time_ = base::TimeTicks();
 }
 
-void CompositorTimingHistory::DidSubmitCompositorFrame(uint32_t frame_token) {
+void CompositorTimingHistory::DidSubmitCompositorFrame(
+    uint32_t frame_token,
+    const viz::BeginFrameId& current_frame_id,
+    const viz::BeginFrameId& last_activated_frame_id) {
   DCHECK_EQ(base::TimeTicks(), submit_start_time_);
-  compositor_frame_reporting_controller_->DidSubmitCompositorFrame(frame_token);
+  compositor_frame_reporting_controller_->DidSubmitCompositorFrame(
+      frame_token, current_frame_id, last_activated_frame_id);
   submit_start_time_ = Now();
 }
 
diff --git a/cc/metrics/compositor_timing_history.h b/cc/metrics/compositor_timing_history.h
index 57b8c11..f6f8179 100644
--- a/cc/metrics/compositor_timing_history.h
+++ b/cc/metrics/compositor_timing_history.h
@@ -73,12 +73,11 @@
   void WillBeginImplFrame(const viz::BeginFrameArgs& args,
                           bool new_active_tree_is_likely,
                           base::TimeTicks now);
-  void WillFinishImplFrame(bool needs_redraw);
+  void WillFinishImplFrame(bool needs_redraw, const viz::BeginFrameId& id);
   void BeginImplFrameNotExpectedSoon();
-  void WillBeginMainFrame(bool on_critical_path,
-                          base::TimeTicks main_frame_time);
+  void WillBeginMainFrame(const viz::BeginFrameArgs& args);
   void BeginMainFrameStarted(base::TimeTicks main_thread_start_time);
-  void BeginMainFrameAborted();
+  void BeginMainFrameAborted(const viz::BeginFrameId& id);
   void NotifyReadyToCommit(std::unique_ptr<BeginMainFrameMetrics> details);
   void WillCommit();
   void DidCommit();
@@ -96,7 +95,10 @@
                bool current_frame_had_raf,
                bool next_frame_has_pending_raf,
                bool has_custom_property_animations);
-  void DidSubmitCompositorFrame(uint32_t frame_token);
+  void DidSubmitCompositorFrame(
+      uint32_t frame_token,
+      const viz::BeginFrameId& current_frame_id,
+      const viz::BeginFrameId& last_activated_frame_id);
   void DidReceiveCompositorFrameAck();
   void DidPresentCompositorFrame(uint32_t frame_token,
                                  const viz::FrameTimingDetails& details);
diff --git a/cc/metrics/compositor_timing_history_unittest.cc b/cc/metrics/compositor_timing_history_unittest.cc
index 695217c6..7734463c 100644
--- a/cc/metrics/compositor_timing_history_unittest.cc
+++ b/cc/metrics/compositor_timing_history_unittest.cc
@@ -59,7 +59,7 @@
                      int main_thread_animations_count,
                      bool current_frame_had_raf = false,
                      bool next_frame_has_pending_raf = false) {
-    timing_history_.WillBeginMainFrame(true, Now());
+    timing_history_.WillBeginMainFrame(getFakeBeginFrameArg());
     timing_history_.BeginMainFrameStarted(Now());
     timing_history_.WillCommit();
     timing_history_.DidCommit();
@@ -77,9 +77,10 @@
                      int composited_animations_count,
                      int main_thread_animations_count,
                      bool has_custom_property_animation) {
-    timing_history_.WillBeginMainFrame(true, Now());
+    viz::BeginFrameArgs args_ = getFakeBeginFrameArg();
+    timing_history_.WillBeginMainFrame(args_);
     timing_history_.BeginMainFrameStarted(Now());
-    timing_history_.BeginMainFrameAborted();
+    timing_history_.BeginMainFrameAborted(args_.frame_id);
     timing_history_.WillActivate();
     timing_history_.DidActivate();
     timing_history_.WillDraw();
@@ -94,6 +95,13 @@
   std::unique_ptr<CompositorFrameReportingController> reporting_controller_;
   TestCompositorTimingHistory timing_history_;
   base::TimeTicks now_;
+
+  viz::BeginFrameArgs getFakeBeginFrameArg(bool on_critical_path = true) {
+    viz::BeginFrameArgs args_ = viz::BeginFrameArgs();
+    args_.frame_time = Now();
+    args_.on_critical_path = on_critical_path;
+    return args_;
+  }
 };
 
 base::TimeTicks TestCompositorTimingHistory::Now() const {
@@ -118,7 +126,7 @@
   base::TimeDelta activate_duration = base::TimeDelta::FromMilliseconds(4);
   base::TimeDelta draw_duration = base::TimeDelta::FromMilliseconds(5);
 
-  timing_history_.WillBeginMainFrame(true, Now());
+  timing_history_.WillBeginMainFrame(getFakeBeginFrameArg());
   AdvanceNowBy(begin_main_frame_queue_duration);
   timing_history_.BeginMainFrameStarted(Now());
   AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
@@ -172,12 +180,13 @@
   base::TimeDelta activate_duration = base::TimeDelta::FromMilliseconds(4);
   base::TimeDelta draw_duration = base::TimeDelta::FromMilliseconds(5);
 
-  timing_history_.WillBeginMainFrame(false, Now());
+  viz::BeginFrameArgs args_ = getFakeBeginFrameArg(false);
+  timing_history_.WillBeginMainFrame(args_);
   AdvanceNowBy(begin_main_frame_queue_duration);
   timing_history_.BeginMainFrameStarted(Now());
   AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
   // BeginMainFrameAborted counts as a commit complete.
-  timing_history_.BeginMainFrameAborted();
+  timing_history_.BeginMainFrameAborted(args_.frame_id);
   timing_history_.WillPrepareTiles();
   AdvanceNowBy(prepare_tiles_duration);
   timing_history_.DidPrepareTiles();
@@ -213,17 +222,19 @@
   base::TimeDelta begin_main_frame_start_to_ready_to_commit_duration =
       base::TimeDelta::FromMilliseconds(1);
 
-  timing_history_.WillBeginMainFrame(true, Now());
+  viz::BeginFrameArgs args_ = getFakeBeginFrameArg();
+  timing_history_.WillBeginMainFrame(args_);
   AdvanceNowBy(begin_main_frame_queue_duration_critical);
   timing_history_.BeginMainFrameStarted(Now());
   AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
-  timing_history_.BeginMainFrameAborted();
+  timing_history_.BeginMainFrameAborted(args_.frame_id);
 
-  timing_history_.WillBeginMainFrame(false, Now());
+  args_ = getFakeBeginFrameArg(false);
+  timing_history_.WillBeginMainFrame(args_);
   AdvanceNowBy(begin_main_frame_queue_duration_not_critical);
   timing_history_.BeginMainFrameStarted(Now());
   AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
-  timing_history_.BeginMainFrameAborted();
+  timing_history_.BeginMainFrameAborted(args_.frame_id);
 
   // Since the critical BeginMainFrames are faster than non critical ones,
   // the expectations are straightforward.
@@ -245,21 +256,23 @@
       base::TimeDelta::FromMilliseconds(1);
 
   // A single critical frame that is slow.
-  timing_history_.WillBeginMainFrame(true, Now());
+  viz::BeginFrameArgs args_ = getFakeBeginFrameArg();
+  timing_history_.WillBeginMainFrame(args_);
   AdvanceNowBy(begin_main_frame_queue_duration_critical);
   timing_history_.BeginMainFrameStarted(Now());
   AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
   // BeginMainFrameAborted counts as a commit complete.
-  timing_history_.BeginMainFrameAborted();
+  timing_history_.BeginMainFrameAborted(args_.frame_id);
 
   // A bunch of faster non critical frames that are newer.
   for (int i = 0; i < 100; i++) {
-    timing_history_.WillBeginMainFrame(false, Now());
+    args_ = getFakeBeginFrameArg(false);
+    timing_history_.WillBeginMainFrame(args_);
     AdvanceNowBy(begin_main_frame_queue_duration_not_critical);
     timing_history_.BeginMainFrameStarted(Now());
     AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
     // BeginMainFrameAborted counts as a commit complete.
-    timing_history_.BeginMainFrameAborted();
+    timing_history_.BeginMainFrameAborted(args_.frame_id);
   }
 
   // Recent fast non critical BeginMainFrames should result in the
@@ -282,19 +295,21 @@
       base::TimeDelta::FromMilliseconds(1);
 
   // A single non critical frame that is fast.
-  timing_history_.WillBeginMainFrame(false, Now());
+  viz::BeginFrameArgs args_ = getFakeBeginFrameArg(false);
+  timing_history_.WillBeginMainFrame(args_);
   AdvanceNowBy(begin_main_frame_queue_duration_not_critical);
   timing_history_.BeginMainFrameStarted(Now());
   AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
-  timing_history_.BeginMainFrameAborted();
+  timing_history_.BeginMainFrameAborted(args_.frame_id);
 
   // A bunch of slower critical frames that are newer.
   for (int i = 0; i < 100; i++) {
-    timing_history_.WillBeginMainFrame(true, Now());
+    args_ = getFakeBeginFrameArg();
+    timing_history_.WillBeginMainFrame(args_);
     AdvanceNowBy(begin_main_frame_queue_duration_critical);
     timing_history_.BeginMainFrameStarted(Now());
     AdvanceNowBy(begin_main_frame_start_to_ready_to_commit_duration);
-    timing_history_.BeginMainFrameAborted();
+    timing_history_.BeginMainFrameAborted(args_.frame_id);
   }
 
   // Recent slow critical BeginMainFrames should result in the
diff --git a/cc/mojom/BUILD.gn b/cc/mojom/BUILD.gn
index 7f648e69..03d1c93 100644
--- a/cc/mojom/BUILD.gn
+++ b/cc/mojom/BUILD.gn
@@ -6,11 +6,7 @@
 
 mojom("mojom") {
   generate_java = true
-  sources = [
-    "touch_action.mojom",
-  ]
+  sources = [ "touch_action.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index a7536ba..7064a90 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -112,9 +112,7 @@
 }
 
 fuzzer_test("paint_op_buffer_fuzzer") {
-  sources = [
-    "paint_op_buffer_fuzzer.cc",
-  ]
+  sources = [ "paint_op_buffer_fuzzer.cc" ]
 
   libfuzzer_options = [ "max_len=4096" ]
 
@@ -128,9 +126,7 @@
 }
 
 fuzzer_test("transfer_cache_fuzzer") {
-  sources = [
-    "transfer_cache_fuzzer.cc",
-  ]
+  sources = [ "transfer_cache_fuzzer.cc" ]
 
   libfuzzer_options = [ "max_len=4096" ]
 
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 632c224..985890e0 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -145,7 +145,9 @@
 }
 
 void Scheduler::DidSubmitCompositorFrame(uint32_t frame_token) {
-  compositor_timing_history_->DidSubmitCompositorFrame(frame_token);
+  compositor_timing_history_->DidSubmitCompositorFrame(
+      frame_token, begin_main_frame_args_.frame_id,
+      last_activate_origin_frame_args_.frame_id);
   state_machine_.DidSubmitCompositorFrame();
 
   // There is no need to call ProcessScheduledActions here because
@@ -186,7 +188,8 @@
 void Scheduler::BeginMainFrameAborted(CommitEarlyOutReason reason) {
   TRACE_EVENT1("cc", "Scheduler::BeginMainFrameAborted", "reason",
                CommitEarlyOutReasonToString(reason));
-  compositor_timing_history_->BeginMainFrameAborted();
+  compositor_timing_history_->BeginMainFrameAborted(
+      last_dispatched_begin_main_frame_args_.frame_id);
   state_machine_.BeginMainFrameAborted(reason);
   ProcessScheduledActions();
 }
@@ -564,8 +567,8 @@
   begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
 
   BeginImplFrame(args, Now());
-  compositor_timing_history_->WillFinishImplFrame(
-      state_machine_.needs_redraw());
+  compositor_timing_history_->WillFinishImplFrame(state_machine_.needs_redraw(),
+                                                  args.frame_id);
   FinishImplFrame();
 }
 
@@ -720,7 +723,7 @@
   // * Creating a new OuputSurface will not occur during the deadline in
   //     order to allow the state machine to "settle" first.
   compositor_timing_history_->WillFinishImplFrame(
-      state_machine_.needs_redraw());
+      state_machine_.needs_redraw(), begin_main_frame_args_.frame_id);
   state_machine_.OnBeginImplFrameDeadline();
   ProcessScheduledActions();
   FinishImplFrame();
@@ -801,9 +804,7 @@
       case SchedulerStateMachine::Action::NONE:
         break;
       case SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME:
-        compositor_timing_history_->WillBeginMainFrame(
-            begin_main_frame_args_.on_critical_path,
-            begin_main_frame_args_.frame_time);
+        compositor_timing_history_->WillBeginMainFrame(begin_main_frame_args_);
         state_machine_.WillSendBeginMainFrame();
         client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_);
         last_dispatched_begin_main_frame_args_ = begin_main_frame_args_;
diff --git a/cc/test/fake_compositor_frame_reporting_controller.cc b/cc/test/fake_compositor_frame_reporting_controller.cc
index 1b8daa2a..04e285f 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.cc
+++ b/cc/test/fake_compositor_frame_reporting_controller.cc
@@ -10,21 +10,23 @@
     bool is_single_threaded)
     : CompositorFrameReportingController(is_single_threaded) {}
 
-void FakeCompositorFrameReportingController::WillBeginMainFrame() {
+void FakeCompositorFrameReportingController::WillBeginMainFrame(
+    const viz::BeginFrameId& id) {
   if (!reporters_[PipelineStage::kBeginImplFrame])
-    CompositorFrameReportingController::WillBeginImplFrame();
-  CompositorFrameReportingController::WillBeginMainFrame();
+    CompositorFrameReportingController::WillBeginImplFrame(id);
+  CompositorFrameReportingController::WillBeginMainFrame(id);
 }
 
-void FakeCompositorFrameReportingController::BeginMainFrameAborted() {
+void FakeCompositorFrameReportingController::BeginMainFrameAborted(
+    const viz::BeginFrameId& id) {
   if (!reporters_[PipelineStage::kBeginMainFrame])
-    WillBeginMainFrame();
-  CompositorFrameReportingController::BeginMainFrameAborted();
+    WillBeginMainFrame(id);
+  CompositorFrameReportingController::BeginMainFrameAborted(id);
 }
 
 void FakeCompositorFrameReportingController::WillCommit() {
   if (!reporters_[PipelineStage::kBeginMainFrame])
-    WillBeginMainFrame();
+    WillBeginMainFrame(viz::BeginFrameId());
   CompositorFrameReportingController::WillCommit();
 }
 
@@ -47,8 +49,11 @@
 }
 
 void FakeCompositorFrameReportingController::DidSubmitCompositorFrame(
-    uint32_t frame_token) {
-  CompositorFrameReportingController::DidSubmitCompositorFrame(frame_token);
+    uint32_t frame_token,
+    const viz::BeginFrameId& current_frame_id,
+    const viz::BeginFrameId& last_activated_frame_id) {
+  CompositorFrameReportingController::DidSubmitCompositorFrame(
+      frame_token, current_frame_id, last_activated_frame_id);
 
   viz::FrameTimingDetails details;
   details.presentation_feedback.timestamp = base::TimeTicks::Now();
diff --git a/cc/test/fake_compositor_frame_reporting_controller.h b/cc/test/fake_compositor_frame_reporting_controller.h
index 1a28bbb15..0536f550f77 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.h
+++ b/cc/test/fake_compositor_frame_reporting_controller.h
@@ -27,13 +27,16 @@
   FakeCompositorFrameReportingController& operator=(
       const FakeCompositorFrameReportingController& controller) = delete;
 
-  void WillBeginMainFrame() override;
-  void BeginMainFrameAborted() override;
+  void WillBeginMainFrame(const viz::BeginFrameId& id) override;
+  void BeginMainFrameAborted(const viz::BeginFrameId& id) override;
   void WillCommit() override;
   void DidCommit() override;
   void WillActivate() override;
   void DidActivate() override;
-  void DidSubmitCompositorFrame(uint32_t frame_token) override;
+  void DidSubmitCompositorFrame(
+      uint32_t frame_token,
+      const viz::BeginFrameId& current_frame_id,
+      const viz::BeginFrameId& last_activated_frame_id) override;
   void DidPresentCompositorFrame(
       uint32_t frame_token,
       const viz::FrameTimingDetails& details) override;
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 8c0a18c8..1cd333e 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1711,6 +1711,7 @@
   "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarAnimationCoordinator.java",
   "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java",
   "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java",
+  "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarVariationManager.java",
   "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java",
   "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarLinearLayout.java",
   "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index edbac41..43ebe700 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -18,10 +18,8 @@
     "//third_party/android_deps:android_support_v7_appcompat_java",
   ]
 
-  sources = [
-    "java/src/org/chromium/chrome/browser/" +
-        "autofill_assistant/header/AnimatedPoodle.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/browser/" +
+              "autofill_assistant/header/AnimatedPoodle.java" ]
 }
 
 android_resources("animated_poodle_resources") {
@@ -200,9 +198,7 @@
 
 generate_jni("test_support_jni_headers") {
   testonly = true
-  sources = [
-    "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTestService.java",
-  ]
+  sources = [ "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTestService.java" ]
 }
 
 android_library("autofill_assistant_java_test_support") {
@@ -280,9 +276,7 @@
     "//ui/android:ui_full_java",
   ]
 
-  data = [
-    "//components/test/data/autofill_assistant/",
-  ]
+  data = [ "//components/test/data/autofill_assistant/" ]
 }
 
 android_resources("java_resources") {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java
index 338dc34..ffb33708 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java
@@ -9,6 +9,7 @@
 import static android.support.test.espresso.action.ViewActions.click;
 import static android.support.test.espresso.action.ViewActions.scrollTo;
 import static android.support.test.espresso.action.ViewActions.typeText;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
@@ -20,6 +21,7 @@
 
 import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.getAbsoluteBoundingRect;
 import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.startAutofillAssistant;
+import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewAssertionTrue;
 import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition;
 import static org.chromium.chrome.browser.autofill_assistant.proto.ConfigureBottomSheetProto.PeekMode.HANDLE;
 import static org.chromium.chrome.browser.autofill_assistant.proto.ConfigureBottomSheetProto.PeekMode.HANDLE_HEADER;
@@ -47,8 +49,10 @@
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
+import org.chromium.chrome.browser.autofill_assistant.proto.ChipIcon;
 import org.chromium.chrome.browser.autofill_assistant.proto.ChipProto;
 import org.chromium.chrome.browser.autofill_assistant.proto.ChipType;
+import org.chromium.chrome.browser.autofill_assistant.proto.ClientSettingsProto;
 import org.chromium.chrome.browser.autofill_assistant.proto.CollectUserDataProto;
 import org.chromium.chrome.browser.autofill_assistant.proto.ConfigureBottomSheetProto;
 import org.chromium.chrome.browser.autofill_assistant.proto.ConfigureBottomSheetProto.PeekMode;
@@ -312,6 +316,71 @@
         onView(withText("Title 0")).perform(scrollTo()).check(matches(isDisplayed()));
     }
 
+    @Test
+    @MediumTest
+    public void testCancelSnackbarUndo() {
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add((ActionProto) ActionProto.newBuilder()
+                         .setPrompt(PromptProto.newBuilder().addChoices(Choice.newBuilder().setChip(
+                                 ChipProto.newBuilder()
+                                         .setType(ChipType.CANCEL_ACTION)
+                                         .setIcon(ChipIcon.ICON_CLEAR)
+                                         .setText("Cancel"))))
+                         .build());
+        AutofillAssistantTestScript script = new AutofillAssistantTestScript(
+                (SupportedScriptProto) SupportedScriptProto.newBuilder()
+                        .setPath("bottomsheet_behaviour_target_website.html")
+                        .setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip(
+                                ChipProto.newBuilder().setText("Autostart")))
+                        .build(),
+                list);
+
+        AutofillAssistantTestService testService =
+                new AutofillAssistantTestService(Collections.singletonList(script));
+        startAutofillAssistant(mTestRule.getActivity(), testService);
+        waitUntilViewMatchesCondition(withText("Cancel"), isCompletelyDisplayed());
+
+        onView(withText("Cancel")).perform(click());
+        waitUntilViewMatchesCondition(withText(R.string.undo), isCompletelyDisplayed());
+        onView(withText("Cancel")).check(doesNotExist());
+        onView(withText(R.string.undo)).perform(click());
+        waitUntilViewMatchesCondition(withText("Cancel"), isDisplayed());
+    }
+
+    @Test
+    @MediumTest
+    public void testCancelSnackbarTimeout() {
+        ClientSettingsProto clientSettings = (ClientSettingsProto) ClientSettingsProto.newBuilder()
+                                                     .setCancelDelayMs(2000)
+                                                     .build();
+        ArrayList<ActionProto> list = new ArrayList<>();
+        list.add((ActionProto) ActionProto.newBuilder()
+                         .setPrompt(PromptProto.newBuilder().addChoices(Choice.newBuilder().setChip(
+                                 ChipProto.newBuilder()
+                                         .setType(ChipType.CANCEL_ACTION)
+                                         .setIcon(ChipIcon.ICON_CLEAR)
+                                         .setText("Cancel"))))
+                         .build());
+        AutofillAssistantTestScript script = new AutofillAssistantTestScript(
+                (SupportedScriptProto) SupportedScriptProto.newBuilder()
+                        .setPath("bottomsheet_behaviour_target_website.html")
+                        .setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip(
+                                ChipProto.newBuilder().setText("Autostart")))
+                        .build(),
+                list);
+
+        AutofillAssistantTestService testService =
+                new AutofillAssistantTestService(Collections.singletonList(script), clientSettings);
+        startAutofillAssistant(mTestRule.getActivity(), testService);
+        waitUntilViewMatchesCondition(withText("Cancel"), isCompletelyDisplayed());
+
+        onView(withText("Cancel")).perform(click());
+        waitUntilViewMatchesCondition(withText(R.string.undo), isCompletelyDisplayed());
+        onView(withText("Cancel")).check(doesNotExist());
+        waitUntilViewAssertionTrue(withText(R.string.undo), doesNotExist(), 3000L);
+        onView(withId(R.id.autofill_assistant)).check(doesNotExist());
+    }
+
     private ViewAction swipeDownToMinimize() {
         return actionWithAssertions(
                 new GeneralSwipeAction(Swipe.FAST, GeneralLocation.CENTER, view -> {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
index 06321c8ff..0cbc39b 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java
@@ -9,6 +9,9 @@
 
 import static org.hamcrest.MatcherAssert.assertThat;
 
+import static org.chromium.content_public.browser.test.util.CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL;
+import static org.chromium.content_public.browser.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
+
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
@@ -19,6 +22,7 @@
 import android.support.test.espresso.NoMatchingViewException;
 import android.support.test.espresso.UiController;
 import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.ViewAssertion;
 import android.support.test.espresso.core.deps.guava.base.Preconditions;
 import android.support.test.espresso.matcher.BoundedMatcher;
 import android.text.SpannableString;
@@ -271,6 +275,12 @@
      */
     public static void waitUntilViewMatchesCondition(
             Matcher<View> matcher, Matcher<View> condition) {
+        waitUntilViewMatchesCondition(matcher, condition, DEFAULT_MAX_TIME_TO_POLL);
+    }
+
+    /** @see {@link #waitUntilViewMatchesCondition(Matcher, Matcher)} */
+    public static void waitUntilViewMatchesCondition(
+            Matcher<View> matcher, Matcher<View> condition, long maxTimeoutMs) {
         CriteriaHelper.pollInstrumentationThread(
                 new Criteria("Timeout while waiting for " + matcher + " to satisfy " + condition) {
                     @Override
@@ -284,7 +294,32 @@
                             return false;
                         }
                     }
-                });
+                },
+                maxTimeoutMs, DEFAULT_POLLING_INTERVAL);
+    }
+
+    /**
+     * Same as {@link #waitUntilViewMatchesCondition(Matcher, Matcher, long)}, but waits for a view
+     * assertion instead.
+     */
+    public static void waitUntilViewAssertionTrue(
+            Matcher<View> matcher, ViewAssertion viewAssertion, long maxTimeoutMs) {
+        CriteriaHelper.pollInstrumentationThread(
+                new Criteria(
+                        "Timeout while waiting for " + matcher + " to satisfy " + viewAssertion) {
+                    @Override
+                    public boolean isSatisfied() {
+                        try {
+                            onView(matcher).check(viewAssertion);
+                            return true;
+                        } catch (NoMatchingViewException | AssertionError e) {
+                            // Note: all other exceptions are let through, in particular
+                            // AmbiguousViewMatcherException.
+                            return false;
+                        }
+                    }
+                },
+                maxTimeoutMs, DEFAULT_POLLING_INTERVAL);
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiTest.java
index ea959c51..5013974 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiTest.java
@@ -48,6 +48,8 @@
 import org.chromium.chrome.browser.flags.FeatureUtilities;
 import org.chromium.chrome.browser.fullscreen.FullscreenManagerTestUtils;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations;
 import org.chromium.chrome.features.start_surface.StartSurfaceLayout;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -80,18 +82,12 @@
         FeatureUtilities.setTabGroupsAndroidEnabledForTesting(true);
         FeatureUtilities.setIsBottomToolbarEnabledForTesting(true);
         FeatureUtilities.setDuetTabStripIntegrationAndroidEnabledForTesting(true);
-        mActivityTestRule.startMainActivityFromLauncher();
-        Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-        assertTrue(layout instanceof StartSurfaceLayout);
-        CriteriaHelper.pollUiThread(mActivityTestRule.getActivity()
-                                            .getTabModelSelector()
-                                            .getTabModelFilterProvider()
-                                            .getCurrentTabModelFilter()::isTabModelRestored);
     }
 
     @Test
     @MediumTest
-    public void testOnAnchorViewChanged() throws InterruptedException {
+    public void testOnAnchorViewChanged_HOME_SEARCH_TAB_SWITCHER() throws InterruptedException {
+        launchActivity(Variations.HOME_SEARCH_TAB_SWITCHER);
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         // Tab strip should show automatically when entering tab group.
         createTabGroupAndEnterTabPage(cta, 2, null);
@@ -111,7 +107,50 @@
 
     @Test
     @MediumTest
+    public void testOnAnchorViewChanged_HOME_SEARCH_SHARE() throws InterruptedException {
+        launchActivity(Variations.HOME_SEARCH_SHARE);
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        // Tab strip should show automatically when entering tab group.
+        createTabGroupAndEnterTabPage(cta, 2, null);
+        CriteriaHelper.pollInstrumentationThread(() -> isAnchoredOnTopToolbar(cta));
+        verifyShowingTabStrip(cta, 2);
+
+        // In portrait mode, tab strip should anchor on bottom toolbar; in landscape mode, bottom
+        // toolbar hides and tab strip should anchor on top toolbar.
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
+        CriteriaHelper.pollInstrumentationThread(() -> isAnchoredOnTopToolbar(cta));
+        verifyShowingTabStrip(cta, 2);
+
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_PORTRAIT);
+        CriteriaHelper.pollInstrumentationThread(() -> isAnchoredOnTopToolbar(cta));
+        verifyShowingTabStrip(cta, 2);
+    }
+
+    @Test
+    @MediumTest
+    public void testOnAnchorViewChanged_NEW_TAB_SEARCH_SHARE() throws InterruptedException {
+        launchActivity(Variations.NEW_TAB_SEARCH_SHARE);
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        // Tab strip should show automatically when entering tab group.
+        createTabGroupAndEnterTabPage(cta, 2, null);
+        CriteriaHelper.pollInstrumentationThread(() -> isAnchoredOnTopToolbar(cta));
+        verifyShowingTabStrip(cta, 2);
+
+        // In portrait mode, tab strip should anchor on bottom toolbar; in landscape mode, bottom
+        // toolbar hides and tab strip should anchor on top toolbar.
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
+        CriteriaHelper.pollInstrumentationThread(() -> isAnchoredOnTopToolbar(cta));
+        verifyShowingTabStrip(cta, 2);
+
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_PORTRAIT);
+        CriteriaHelper.pollInstrumentationThread(() -> isAnchoredOnTopToolbar(cta));
+        verifyShowingTabStrip(cta, 2);
+    }
+
+    @Test
+    @MediumTest
     public void testTabStripShowHide() throws InterruptedException {
+        launchActivity();
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         // Try to trigger tab strip in a single tab page.
         triggerTabStripAndVerify(cta, 0);
@@ -144,6 +183,7 @@
     @Test
     @MediumTest
     public void testTabStripUpdate() throws InterruptedException {
+        launchActivity();
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
 
         // Tab strip should show automatically when entering tab group.
@@ -180,6 +220,7 @@
     @MediumTest
     @CommandLineFlags.Add({ChromeSwitches.DISABLE_MINIMUM_SHOW_DURATION})
     public void testTabStripChangeWithScrolling() throws InterruptedException {
+        launchActivity();
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         FullscreenManagerTestUtils.disableBrowserOverrides();
 
@@ -287,4 +328,19 @@
                                      .getRelatedTabList(currentTab.getId());
         return tabGroup.indexOf(currentTab);
     }
+
+    private void launchActivity() {
+        launchActivity(Variations.HOME_SEARCH_TAB_SWITCHER);
+    }
+
+    private void launchActivity(@Variations String variation) {
+        BottomToolbarVariationManager.setVariation(variation);
+        mActivityTestRule.startMainActivityFromLauncher();
+        Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
+        assertTrue(layout instanceof StartSurfaceLayout);
+        CriteriaHelper.pollUiThread(mActivityTestRule.getActivity()
+                                            .getTabModelSelector()
+                                            .getTabModelFilterProvider()
+                                            .getCurrentTabModelFilter()::isTabModelRestored);
+    }
 }
diff --git a/chrome/android/java/res/layout/bottom_toolbar_browsing.xml b/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
index 046cf2e0..e218e1d 100644
--- a/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
+++ b/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
@@ -16,23 +16,25 @@
     android:paddingStart="@dimen/bottom_toolbar_padding"
     android:paddingEnd="@dimen/bottom_toolbar_padding" >
 
+    <include layout="@layout/toolbar_space" />
+
     <org.chromium.chrome.browser.toolbar.HomeButton
-        android:id="@+id/home_button"
+        android:id="@+id/bottom_home_button"
         app:tint="@color/standard_mode_tint"
         android:background="?attr/selectableItemBackgroundBorderless"
         android:contentDescription="@string/accessibility_toolbar_btn_home"
+        android:visibility="gone"
+        style="@style/SplitToolbarButton" />
+
+    <org.chromium.chrome.browser.toolbar.bottom.BottomToolbarNewTabButton
+        android:id="@+id/bottom_new_tab_button"
+        android:contentDescription="@string/accessibility_toolbar_btn_new_tab"
+        app:tint="@color/standard_mode_tint"
+        app:srcCompat="@drawable/new_tab_icon"
+        android:visibility="gone"
         style="@style/SplitToolbarButton" />
 
     <include layout="@layout/toolbar_space" />
-
-    <org.chromium.chrome.browser.toolbar.bottom.ShareButton
-        android:id="@+id/share_button"
-        android:src="@drawable/ic_share_white_24dp"
-        app:tint="@color/standard_mode_tint"
-        android:contentDescription="@string/share"
-        android:background="?attr/selectableItemBackgroundBorderless"
-        style="@style/SplitToolbarButton" />
-
     <include layout="@layout/toolbar_space" />
 
     <org.chromium.chrome.browser.toolbar.bottom.SearchAccelerator
@@ -48,19 +50,26 @@
         android:src="@drawable/ic_search"/>
 
     <include layout="@layout/toolbar_space" />
+    <include layout="@layout/toolbar_space" />
 
     <org.chromium.chrome.browser.toolbar.TabSwitcherButtonView
-        android:id="@+id/tab_switcher_button"
+        android:id="@+id/bottom_tab_switcher_button"
         style="@style/SplitToolbarButton"
         app:menuMaxWidth="@dimen/tab_switcher_menu_width"
+        android:visibility="gone"
         android:background="?attr/selectableItemBackgroundBorderless"
         android:contentDescription="@string/accessibility_toolbar_btn_tabswitcher_toggle_default"
         app:menuVerticalOverlapAnchor="false" />
 
-    <include layout="@layout/toolbar_space" />
+    <org.chromium.chrome.browser.toolbar.bottom.ShareButton
+        android:id="@+id/bottom_share_button"
+        android:src="@drawable/ic_share_white_24dp"
+        app:tint="@color/standard_mode_tint"
+        android:visibility="gone"
+        android:background="?attr/selectableItemBackgroundBorderless"
+        android:contentDescription="@string/share"
+        style="@style/SplitToolbarButton" />
 
-    <include
-        style="@style/SplitToolbarButton"
-        layout="@layout/bottom_toolbar_menu_button" />
+    <include layout="@layout/toolbar_space" />
 
 </org.chromium.chrome.browser.toolbar.bottom.BrowsingModeBottomToolbarLinearLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 9e091293..71def338 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1288,7 +1288,7 @@
     public SnackbarManager getSnackbarManager() {
         if (mRootUiCoordinator != null && getBottomSheetController() != null
                 && getBottomSheetController().isSheetOpen()
-                && getBottomSheetController().isSheetHiding()) {
+                && !getBottomSheetController().isSheetHiding()) {
             return mRootUiCoordinator.getBottomSheetSnackbarManager();
         }
         return mSnackbarManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java
index 1f65fe62..79faee2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -206,9 +206,9 @@
                     || mDecorView.getWidth()
                             < DeviceFormFactor.getNonMultiDisplayMinimumTabletWidthPx(mContext);
 
-            final boolean bottomToolbarVisible =
-                    mToolbarManager != null && mToolbarManager.isBottomToolbarVisible();
-            shouldShowIconRow &= !bottomToolbarVisible;
+            final boolean isMenuButtonOnTop =
+                    mToolbarManager != null && !mToolbarManager.isMenuFromBottom();
+            shouldShowIconRow &= isMenuButtonOnTop;
 
             // Update the icon row items (shown in narrow form factors).
             menu.findItem(R.id.icon_row_menu_id).setVisible(shouldShowIconRow);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
index 76500b7..320617b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CloseButtonVisibilityManager;
@@ -38,7 +39,9 @@
     private final CloseButtonVisibilityManager mCloseButtonVisibilityManager;
 
     private boolean mInTwaMode;
-    private boolean mHideBrowserControlsInTwaMode;
+    private boolean mShowBrowserControlsInTwaMode;
+    private boolean mShowBrowserControlsForChildTab;
+
     private @BrowserControlsState int mBrowserControlsState = DEFAULT_BROWSER_CONTROLS_STATE;
 
     private final TabObserver mTabObserver = new EmptyTabObserver() {
@@ -70,9 +73,9 @@
         mCloseButtonVisibilityManager = closeButtonVisibilityManager;
 
         WebappExtras webappExtras = intentDataProvider.getWebappExtras();
-        mHideBrowserControlsInTwaMode =
-                (webappExtras == null || webappExtras.displayMode == WebDisplayMode.FULLSCREEN
-                        || webappExtras.displayMode == WebDisplayMode.STANDALONE);
+        mShowBrowserControlsForChildTab = (webappExtras != null);
+        mShowBrowserControlsInTwaMode =
+                (webappExtras != null && webappExtras.displayMode == WebDisplayMode.MINIMAL_UI);
     }
 
     /**
@@ -114,12 +117,17 @@
         // Show close button if toolbar is not visible, so that during the in and off-scope
         // transitions we avoid button flickering when toolbar is appearing/disappearing.
         boolean closeButtonVisibility =
-                !mInTwaMode || (mBrowserControlsState == BrowserControlsState.HIDDEN);
+                shouldShowBrowserControlsAndCloseButton(mTabProvider.getTab())
+                || (mBrowserControlsState == BrowserControlsState.HIDDEN);
 
         mCloseButtonVisibilityManager.setVisibility(closeButtonVisibility);
     }
 
-    private @BrowserControlsState int computeBrowserControlsState(Tab tab) {
+    private boolean shouldShowBrowserControlsAndCloseButton(@Nullable Tab tab) {
+        return !mInTwaMode || (isChildTab(tab) && mShowBrowserControlsForChildTab);
+    }
+
+    private @BrowserControlsState int computeBrowserControlsState(@Nullable Tab tab) {
         // Force browser controls to show when the security level is dangerous for consistency with
         // TabStateBrowserControlsVisibilityDelegate.
         if (tab != null
@@ -127,7 +135,15 @@
             return BrowserControlsState.SHOWN;
         }
 
-        return mInTwaMode && mHideBrowserControlsInTwaMode ? BrowserControlsState.HIDDEN
-                                                           : BrowserControlsState.BOTH;
+        if (mInTwaMode && mShowBrowserControlsInTwaMode) {
+            return BrowserControlsState.BOTH;
+        }
+
+        return shouldShowBrowserControlsAndCloseButton(tab) ? BrowserControlsState.BOTH
+                                                            : BrowserControlsState.HIDDEN;
+    }
+
+    private boolean isChildTab(@Nullable Tab tab) {
+        return tab != null && tab.getParentId() != Tab.INVALID_TAB_ID;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java
index da28402..66cf9b8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java
@@ -6,7 +6,9 @@
 
 import androidx.annotation.Nullable;
 
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.browserservices.BrowserServicesActivityTabController;
+import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.tab.Tab;
@@ -17,12 +19,18 @@
 import javax.inject.Inject;
 
 /**
- * Allows navigation to the most recent page that matches a criteria when the Custom Tabs close
- * button is pressed. We call this page the landing page.
+ * Closes the tab or navigates back when the Custom Tabs close button is pressed. The algorithm
+ * depends on whether the tab is a child tab - {@link Tab#getParentId()} != Tab.INVALID_TAB_ID.
  *
- * For example, in Trusted Web Activities we only show the close button when the user has left the
- * verified origin. If the user then pressed the close button, we want to navigate back to the
- * verified origin instead of closing the Activity.
+ * If the tab is not a child tab:
+ * Navigates to the most recent page which matches a criteria. We call this page the landing page.
+ * For instance, Trusted Web Activities show the close button when the user has left the verified
+ * origin. If the user then presses the close button, we want to navigate back to the verified
+ * origin instead of closing the Activity.
+ *
+ * If the tab is a child tab:
+ * Webapps: Closes the current tab
+ * Other: Same algorithm as non-child tabs.
  *
  * Thread safety: Should only be called on UI thread.
  * Native: Requires native.
@@ -32,12 +40,15 @@
     @Nullable private PageCriteria mLandingPageCriteria;
     private final BrowserServicesActivityTabController mTabController;
     private final CustomTabActivityTabProvider mTabProvider;
+    private final boolean mButtonClosesChildTab;
 
     @Inject
     public CloseButtonNavigator(BrowserServicesActivityTabController tabController,
-            CustomTabActivityTabProvider tabProvider) {
+            CustomTabActivityTabProvider tabProvider,
+            BrowserServicesIntentDataProvider intentDataProvider) {
         mTabController = tabController;
         mTabProvider = tabProvider;
+        mButtonClosesChildTab = (intentDataProvider.getWebappExtras() != null);
     }
 
     // TODO(peconn): Replace with Predicate<T> when we can use Java 8 libraries.
@@ -59,27 +70,43 @@
     }
 
     /**
-     * Handles navigation and Tab closures that should occur when the close button is pressed. It
-     * searches for a landing page in the history of the current Tab and then closes it if none are
-     * found. This continues until a landing page is found or all Tabs are closed.
+     * Handles navigation and Tab closures that should occur when the close button is pressed.
      */
     public void navigateOnClose() {
+        // If the tab is a child tab and |mButtonClosesChildTab| == true, close the child tab.
+        Tab currentTab = mTabProvider.getTab();
+        boolean isFromChildTab =
+                (currentTab != null && currentTab.getParentId() != Tab.INVALID_TAB_ID);
+        if (isFromChildTab && mButtonClosesChildTab) {
+            mTabController.closeTab();
+            return;
+        }
+
+        // Search for a landing page in the history of the current Tab and then close if if none
+        // found. Continue until a landing page is found or all Tabs are closed.
+        int numTabsClosed = 0;
         while (mTabProvider.getTab() != null) {
             // See if there's a close button navigation in our current Tab.
             NavigationController navigationController = getNavigationController();
             if (navigationController != null && navigateSingleTab(getNavigationController())) {
+                if (isFromChildTab) {
+                    recordChildTabScopeAlgorithmClosesOneTab(false);
+                }
                 return;
             }
 
             mTabController.closeTab();
+            ++numTabsClosed;
 
             // Check whether the close button navigation would have stopped on the newly revealed
             // Tab. We don't check this at the start of the loop (or make navigateSingleTab
             // consider the current Tab) because in that case if the user started on a landing page,
-            // we would not navigate at all. (Admittedly though this case would never happen at the
-            // time of writing since landing pages don't show the close button).
+            // we would not navigate at all.
             Tab nextTab = mTabProvider.getTab();
-            if (nextTab != null && isLandingPage(mTabProvider.getTab().getUrl())) {
+            if (nextTab != null && isLandingPage(nextTab.getUrl())) {
+                if (isFromChildTab) {
+                    recordChildTabScopeAlgorithmClosesOneTab(numTabsClosed == 1);
+                }
                 return;
             }
         }
@@ -104,6 +131,16 @@
         return false;
     }
 
+    /**
+     * Records how often the "navigate to landing page" algorithm for child tabs for Custom Tabs and
+     * Trusted Web Activities produces the same behaviour as the webapp "close current tab"
+     * algorithm.
+     */
+    private void recordChildTabScopeAlgorithmClosesOneTab(boolean closesOneTab) {
+        RecordHistogram.recordBooleanHistogram(
+                "CustomTabs.CloseButton.ChildTab.ScopeAlgorithm.ClosesOneTab", closesOneTab);
+    }
+
     @Nullable
     private NavigationController getNavigationController() {
         Tab tab = mTabProvider.getTab();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java
index cd63daa..73e4ef4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager;
 import org.chromium.ui.base.DeviceFormFactor;
 
 import java.util.HashMap;
@@ -219,6 +220,16 @@
     public static void cacheBottomToolbarEnabled() {
         cacheFlag(ChromePreferenceKeys.FLAGS_CACHED_BOTTOM_TOOLBAR_ENABLED,
                 ChromeFeatureList.CHROME_DUET);
+        cacheBottomToolbarVariation();
+    }
+
+    /**
+     * Cache the enabled bottom toolbar variation.
+     */
+    public static void cacheBottomToolbarVariation() {
+        cacheVariation(ChromePreferenceKeys.VARIATION_CACHED_BOTTOM_TOOLBAR,
+                ChromeFeatureList.CHROME_DUET,
+                BottomToolbarVariationManager.getVariationParamName());
     }
 
     /**
@@ -265,6 +276,15 @@
     }
 
     /**
+     * @return The currently enabled bottom toolbar variation.
+     */
+    public static String getBottomToolbarVariation() {
+        return SharedPreferencesManager.getInstance().readString(
+                ChromePreferenceKeys.VARIATION_CACHED_BOTTOM_TOOLBAR,
+                BottomToolbarVariationManager.Variations.NONE);
+    }
+
+    /**
      * Set whether the bottom toolbar is enabled for tests. Reset to null at the end of tests.
      */
     @VisibleForTesting
@@ -731,6 +751,12 @@
                 preferenceName, ChromeFeatureList.isEnabled(featureName));
     }
 
+    private static void cacheVariation(
+            String preferenceName, String featureName, String variationName) {
+        SharedPreferencesManager.getInstance().writeString(preferenceName,
+                ChromeFeatureList.getFieldTrialParamByFeature(featureName, variationName));
+    }
+
     private static boolean isFlagEnabled(String preferenceName, boolean defaultValue) {
         Boolean flag = sFlags.get(preferenceName);
         if (flag == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
index cbdf8c6..6561531b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -354,9 +354,13 @@
 
     /**
      * Records whether a WebAPK navigation is within the WebAPK's scope.
+     * @param isChildTab Whether {@link Tab#getParentId()} is non-empty.
+     * @param isNavigationInScope
      */
-    public static void recordNavigation(boolean isNavigationInScope) {
-        RecordHistogram.recordBooleanHistogram("WebApk.Navigation.InScope", isNavigationInScope);
+    public static void recordNavigation(boolean isChildTab, boolean isNavigationInScope) {
+        RecordHistogram.recordBooleanHistogram(
+                isChildTab ? "WebApk.Navigation.ChildTab.InScope" : "WebApk.Navigation.InScope",
+                isNavigationInScope);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java
index 23e47f2..1d4d05a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java
@@ -7,8 +7,9 @@
 import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.base.ContextUtils;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.components.search_engines.TemplateUrl;
 import org.chromium.components.search_engines.TemplateUrlService;
 
@@ -17,10 +18,6 @@
 
 /** Hosts common code for search engine choice metrics reporting. */
 public class SearchEngineChoiceMetrics {
-    /** Key used to store the default Search Engine Type before choice is presented. */
-    @VisibleForTesting
-    public static final String PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE =
-            "search_engine_choice_default_type_before";
 
     /**
      * AndroidSearchEngineChoiceEvents defined in tools/metrics/histograms/enums.xml. These values
@@ -112,25 +109,23 @@
 
     /** @return True if the current search engine is possibly different from the previous one. */
     static boolean isSearchEnginePossiblyDifferent() {
-        return ContextUtils.getAppSharedPreferences().contains(
-                PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE);
+        return SharedPreferencesManager.getInstance().contains(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE);
     }
 
     /** Remove the stored choice from prefs. */
     @VisibleForTesting
     static void removePreviousSearchEngineType() {
-        ContextUtils.getAppSharedPreferences()
-                .edit()
-                .remove(PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE)
-                .apply();
+        SharedPreferencesManager.getInstance().removeKey(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE);
     }
 
     /** Retrieves the previously set search engine from Android prefs. */
     @VisibleForTesting
     @SearchEngineType
     static int getPreviousSearchEngineType() {
-        return ContextUtils.getAppSharedPreferences().getInt(
-                PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE,
+        return SharedPreferencesManager.getInstance().readInt(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE,
                 SearchEngineType.SEARCH_ENGINE_UNKNOWN);
     }
 
@@ -139,10 +134,8 @@
      */
     @VisibleForTesting
     static void setPreviousSearchEngineType(@SearchEngineType int engine) {
-        ContextUtils.getAppSharedPreferences()
-                .edit()
-                .putInt(PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE, engine)
-                .apply();
+        SharedPreferencesManager.getInstance().writeInt(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE, engine);
     }
 
     /** Translates from the default search engine url to the {@link SearchEngineType} int. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
index 86226346..ffe14b9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
@@ -8,11 +8,12 @@
 
 import androidx.annotation.Nullable;
 
-import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.omaha.VersionNumber;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.search_engine.SearchEngineSettings;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
@@ -23,16 +24,9 @@
 
 /**
  * Class that prompts the user to change their search engine at the browser startup.
- * User is only meant to be propmpted once, hence the fact of prompting is saved to preferences.
+ * User is only meant to be prompted once, hence the fact of prompting is saved to preferences.
  */
 public final class SearchEngineChoiceNotification {
-    /** Key used to store the date of when search engine choice was requested. */
-    static final String PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP =
-            "search_engine_choice_requested_timestamp";
-
-    /** Key used to store the version of Chrome in which the choice was presented. */
-    static final String PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION =
-            "search_engine_choice_presented_version";
 
     /** Variations parameter name for notification snackbar duration (in seconds). */
     private static final String PARAM_NOTIFICATION_SNACKBAR_DURATION_SECONDS =
@@ -117,23 +111,19 @@
 
     private static void updateSearchEngineChoiceRequested() {
         long now = System.currentTimeMillis();
-        ContextUtils.getAppSharedPreferences()
-                .edit()
-                .putLong(PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP, now)
-                .apply();
+        SharedPreferencesManager.getInstance().writeLong(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP, now);
     }
 
     private static boolean wasSearchEngineChoiceRequested() {
-        return ContextUtils.getAppSharedPreferences().contains(
-                PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP);
+        return SharedPreferencesManager.getInstance().contains(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP);
     }
 
     private static void updateSearchEngineChoicePresented() {
         String productVersion = ChromeVersionInfo.getProductVersion();
-        ContextUtils.getAppSharedPreferences()
-                .edit()
-                .putString(PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION, productVersion)
-                .apply();
+        SharedPreferencesManager.getInstance().writeString(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION, productVersion);
     }
 
     private static boolean wasSearchEngineChoicePresented() {
@@ -148,8 +138,8 @@
 
     @Nullable
     private static VersionNumber getLastPresentedVersionNumber() {
-        return VersionNumber.fromString(ContextUtils.getAppSharedPreferences().getString(
-                PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION, null));
+        return VersionNumber.fromString(SharedPreferencesManager.getInstance().readString(
+                ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION, null));
     }
 
     @Nullable
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/ManageSyncPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/ManageSyncPreferences.java
index 4ac8dd4..f52e34e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/ManageSyncPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/ManageSyncPreferences.java
@@ -32,12 +32,14 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.ChromeSwitchPreference;
 import org.chromium.chrome.browser.settings.SettingsUtils;
+import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.sync.TrustedVaultClient;
 import org.chromium.chrome.browser.sync.ui.PassphraseCreationDialogFragment;
 import org.chromium.chrome.browser.sync.ui.PassphraseDialogFragment;
 import org.chromium.chrome.browser.sync.ui.PassphraseTypeDialogFragment;
 import org.chromium.components.signin.ChromeSigninController;
+import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.sync.ModelType;
 import org.chromium.components.sync.PassphraseType;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
@@ -214,6 +216,8 @@
      * from this state.
      */
     private void updateSyncPreferences() {
+        // TODO(crbug.com/1041815): Migrate away from ChromeSigninController and use IdentityManager
+        // instead.
         String signedInAccountName = ChromeSigninController.get().getSignedInAccountName();
         if (signedInAccountName == null) {
             // May happen if account is removed from the device while this screen is shown.
@@ -403,7 +407,12 @@
         if (mProfileSyncService.isPassphraseRequiredForPreferredDataTypes()) {
             displayPassphraseDialog();
         } else if (mProfileSyncService.isTrustedVaultKeyRequiredForPreferredDataTypes()) {
-            TrustedVaultClient.get().displayKeyRetrievalDialog(getContext());
+            CoreAccountInfo primaryAccountInfo =
+                    IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo();
+            if (primaryAccountInfo != null) {
+                TrustedVaultClient.get().displayKeyRetrievalDialog(
+                        getActivity(), primaryAccountInfo);
+            }
         } else {
             displayPassphraseTypeDialog();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/SyncAndServicesPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/SyncAndServicesPreferences.java
index 286a864..078369f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/SyncAndServicesPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/sync/SyncAndServicesPreferences.java
@@ -65,6 +65,7 @@
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChromeSigninController;
+import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.components.signin.metrics.SignoutReason;
 import org.chromium.components.sync.AndroidSyncSettings;
@@ -334,6 +335,8 @@
         mProfileSyncService.addSyncStateChangedListener(this);
         mSigninPreference.registerForUpdates();
 
+        // TODO(crbug.com/1041815): Migrate away from ChromeSigninController and use IdentityManager
+        // instead.
         if (!mIsFromSigninScreen || ChromeSigninController.get().isSignedIn()) {
             return;
         }
@@ -570,6 +573,8 @@
         }
 
         if (mCurrentSyncError == SyncError.AUTH_ERROR) {
+            // TODO(crbug.com/1041815): Migrate away from ChromeSigninController and use
+            // IdentityManager instead.
             AccountManagerFacade.get().updateCredentials(
                     ChromeSigninController.get().getSignedInUser(), getActivity(), null);
             return;
@@ -585,6 +590,8 @@
         }
 
         if (mCurrentSyncError == SyncError.OTHER_ERRORS) {
+            // TODO(crbug.com/1041815): Migrate away from ChromeSigninController and use
+            // IdentityManager instead.
             final Account account = ChromeSigninController.get().getSignedInUser();
             // TODO(https://crbug.com/873116): Pass the correct reason for the signout.
             IdentityServicesProvider.get().getSigninManager().signOut(
@@ -603,7 +610,12 @@
 
         if (mCurrentSyncError == SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_EVERYTHING
                 || mCurrentSyncError == SyncError.TRUSTED_VAULT_KEY_REQUIRED_FOR_PASSWORDS) {
-            TrustedVaultClient.get().displayKeyRetrievalDialog(getContext());
+            CoreAccountInfo primaryAccountInfo =
+                    IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo();
+            if (primaryAccountInfo != null) {
+                TrustedVaultClient.get().displayKeyRetrievalDialog(
+                        getActivity(), primaryAccountInfo);
+            }
             return;
         }
     }
@@ -645,6 +657,8 @@
             closeDialogIfOpen(FRAGMENT_ENTER_PASSPHRASE);
         }
 
+        // TODO(crbug.com/1041815): Migrate away from ChromeSigninController and use IdentityManager
+        // instead.
         if (!ChromeSigninController.get().isSignedIn()) {
             getPreferenceScreen().removePreference(mManageYourGoogleAccount);
             getPreferenceScreen().removePreference(mSyncCategory);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
index 5671ac77..33e001e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
@@ -24,8 +24,10 @@
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.sync.SyncAndServicesPreferences;
+import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.sync.GoogleServiceAuthError.State;
 import org.chromium.chrome.browser.sync.ui.PassphraseActivity;
+import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.sync.AndroidSyncSettings;
 import org.chromium.components.sync.PassphraseType;
 
@@ -84,12 +86,17 @@
             }
         } else if (mProfileSyncService.isEngineInitialized()
                 && mProfileSyncService.isTrustedVaultKeyRequiredForPreferredDataTypes()) {
-            Intent intent = TrustedVaultClient.get().createKeyRetrievalIntent();
-            if (intent != null) {
-                showSyncNotification(mProfileSyncService.isEncryptEverythingEnabled()
-                                ? R.string.sync_error_card_title
-                                : R.string.sync_passwords_error_card_title,
-                        intent);
+            CoreAccountInfo primaryAccountInfo =
+                    IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo();
+            if (primaryAccountInfo != null) {
+                Intent intent =
+                        TrustedVaultClient.get().createKeyRetrievalIntent(primaryAccountInfo);
+                if (intent != null) {
+                    showSyncNotification(mProfileSyncService.isEncryptEverythingEnabled()
+                                    ? R.string.sync_error_card_title
+                                    : R.string.sync_passwords_error_card_title,
+                            intent);
+                }
             }
         } else {
             mNotificationManager.cancel(NotificationConstants.NOTIFICATION_ID_SYNC);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java
index a56990a..8fee1d4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/TrustedVaultClient.java
@@ -15,6 +15,7 @@
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.components.signin.base.CoreAccountInfo;
 
 import java.util.Collections;
 import java.util.List;
@@ -32,29 +33,30 @@
         /**
          * Reads and returns available encryption keys without involving any user action.
          *
-         * @param gaiaId String representation of the Gaia ID.
+         * @param accountInfo Account representing the user.
          * @return a promise with known keys, if any, where the last one is the most recent.
          */
-        Promise<List<byte[]>> fetchKeys(String gaiaId);
+        Promise<List<byte[]>> fetchKeys(CoreAccountInfo accountInfo);
 
         /**
          * Gets an Intent that can be used to display a UI that allows the user to reauthenticate
          * and retrieve the sync encryption keys.
          *
+         * @param accountInfo Account representing the user.
          * @return the Intent object or null is something went wrong.
          */
         @Nullable
-        Intent createKeyRetrievalIntent();
+        Intent createKeyRetrievalIntent(CoreAccountInfo accountInfo);
 
         /**
          * Invoked when the result of fetchKeys() represents keys that cannot decrypt Nigori, which
          * should only be possible if the provided keys are not up-to-date.
          *
-         * @param gaiaId String representation of the Gaia ID.
+         * @param accountInfo Account representing the user.
          * @return a promise which indicates completion and also represents whether the operation
          * took any effect (false positives acceptable).
          */
-        Promise<Boolean> markKeysAsStale(String gaiaId);
+        Promise<Boolean> markKeysAsStale(CoreAccountInfo accountInfo);
     }
 
     /**
@@ -62,17 +64,17 @@
      */
     public static class EmptyBackend implements Backend {
         @Override
-        public Promise<List<byte[]>> fetchKeys(String gaiaId) {
+        public Promise<List<byte[]>> fetchKeys(CoreAccountInfo accountInfo) {
             return Promise.fulfilled(Collections.emptyList());
         }
 
         @Override
-        public Intent createKeyRetrievalIntent() {
+        public Intent createKeyRetrievalIntent(CoreAccountInfo accountInfo) {
             return null;
         }
 
         @Override
-        public Promise<Boolean> markKeysAsStale(String gaiaId) {
+        public Promise<Boolean> markKeysAsStale(CoreAccountInfo accountInfo) {
             return Promise.fulfilled(false);
         }
     };
@@ -103,9 +105,12 @@
 
     /**
      * Displays a UI that allows the user to reauthenticate and retrieve the sync encryption keys.
+     *
+     * @param context Context to use when starting the dialog activity.
+     * @param accountInfo Account representing the user.
      */
-    public void displayKeyRetrievalDialog(Context context) {
-        Intent intent = createKeyRetrievalIntent();
+    public void displayKeyRetrievalDialog(Context context, CoreAccountInfo accountInfo) {
+        Intent intent = createKeyRetrievalIntent(accountInfo);
         if (intent == null) return;
 
         IntentUtils.safeStartActivity(context, intent);
@@ -117,12 +122,13 @@
     /**
      * Creates an intent that launches an activity that triggers the key retrieval UI.
      *
+     * @param accountInfo Account representing the user.
      * @return the intent for opening the key retrieval activity or null if none is actually
      * required
      */
     @Nullable
-    public Intent createKeyRetrievalIntent() {
-        return mBackend.createKeyRetrievalIntent();
+    public Intent createKeyRetrievalIntent(CoreAccountInfo accountInfo) {
+        return mBackend.createKeyRetrievalIntent(accountInfo);
     }
 
     /**
@@ -165,23 +171,27 @@
      * fetchKeysCompleted().
      */
     @CalledByNative
-    private static void fetchKeys(long nativeTrustedVaultClientAndroid, String gaiaId) {
+    private static void fetchKeys(
+            long nativeTrustedVaultClientAndroid, CoreAccountInfo accountInfo) {
         assert isNativeRegistered(nativeTrustedVaultClientAndroid);
-        get().mBackend.fetchKeys(gaiaId).then(
-                (keys)
-                        -> {
-                    if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
-                        TrustedVaultClientJni.get().fetchKeysCompleted(
-                                nativeTrustedVaultClientAndroid, gaiaId,
-                                keys.toArray(new byte[0][]));
-                    }
-                },
-                (exception) -> {
-                    if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
-                        TrustedVaultClientJni.get().fetchKeysCompleted(
-                                nativeTrustedVaultClientAndroid, gaiaId, new byte[0][]);
-                    }
-                });
+
+        get().mBackend.fetchKeys(accountInfo)
+                .then(
+                        (keys)
+                                -> {
+                            if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
+                                TrustedVaultClientJni.get().fetchKeysCompleted(
+                                        nativeTrustedVaultClientAndroid, accountInfo.getGaiaId(),
+                                        keys.toArray(new byte[0][]));
+                            }
+                        },
+                        (exception) -> {
+                            if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
+                                TrustedVaultClientJni.get().fetchKeysCompleted(
+                                        nativeTrustedVaultClientAndroid, accountInfo.getGaiaId(),
+                                        new byte[0][]);
+                            }
+                        });
     }
 
     /**
@@ -189,25 +199,28 @@
      * markKeysAsStaleCompleted().
      */
     @CalledByNative
-    private static void markKeysAsStale(long nativeTrustedVaultClientAndroid, String gaiaId) {
+    private static void markKeysAsStale(
+            long nativeTrustedVaultClientAndroid, CoreAccountInfo accountInfo) {
         assert isNativeRegistered(nativeTrustedVaultClientAndroid);
-        get().mBackend.markKeysAsStale(gaiaId).then(
-                (result)
-                        -> {
-                    if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
-                        TrustedVaultClientJni.get().markKeysAsStaleCompleted(
-                                nativeTrustedVaultClientAndroid, result);
-                    }
-                },
-                (exception) -> {
-                    if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
-                        // There's no certainty about whether the operation made any difference so
-                        // let's return true indicating that it might have, since false positives
-                        // are allowed.
-                        TrustedVaultClientJni.get().markKeysAsStaleCompleted(
-                                nativeTrustedVaultClientAndroid, true);
-                    }
-                });
+
+        get().mBackend.markKeysAsStale(accountInfo)
+                .then(
+                        (result)
+                                -> {
+                            if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
+                                TrustedVaultClientJni.get().markKeysAsStaleCompleted(
+                                        nativeTrustedVaultClientAndroid, result);
+                            }
+                        },
+                        (exception) -> {
+                            if (isNativeRegistered(nativeTrustedVaultClientAndroid)) {
+                                // There's no certainty about whether the operation made any
+                                // difference so let's return true indicating that it might have,
+                                // since false positives are allowed.
+                                TrustedVaultClientJni.get().markKeysAsStaleCompleted(
+                                        nativeTrustedVaultClientAndroid, true);
+                            }
+                        });
     }
 
     @NativeMethods
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
index 30d32d3..e197619 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
@@ -40,7 +40,7 @@
     }
 
     private boolean isMenuButtonInBottomToolbar() {
-        return mToolbarManager != null && mToolbarManager.isBottomToolbarVisible();
+        return mToolbarManager != null && mToolbarManager.isMenuFromBottom();
     }
 
     private boolean shouldShowDataSaverMenuItem() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
index 589acf5..e66e813d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
@@ -151,7 +151,7 @@
      * @param tab The notifying {@link Tab} that might be selected soon, this is a hint that a tab
      *         change is likely.
      */
-    private void updateButtonEnabledState(Tab tab) {
+    public void updateButtonEnabledState(Tab tab) {
         // New tab page button takes precedence over homepage.
         final boolean isHomepageEnabled = HomepageManager.isHomepageEnabled();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
index 3cd3480..8878ce0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
@@ -6,9 +6,7 @@
 
 import android.content.res.ColorStateList;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ThemeColorProvider;
 import org.chromium.chrome.browser.ThemeColorProvider.TintObserver;
 import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
@@ -55,10 +53,9 @@
 
     /**
      * Build the controller that manages the tab switcher button.
-     * @param root The root {@link ViewGroup} for locating the view to inflate.
+     * @param view The {@link TabSwitcherButtonView} the controller manages.
      */
-    public TabSwitcherButtonCoordinator(ViewGroup root) {
-        final TabSwitcherButtonView view = root.findViewById(R.id.tab_switcher_button);
+    public TabSwitcherButtonCoordinator(TabSwitcherButtonView view) {
         PropertyModelChangeProcessor.create(
                 mTabSwitcherButtonModel, view, new TabSwitcherButtonViewBinder());
         mOverviewModeObserver = new EmptyOverviewModeObserver() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 0b50fe7..5aa6097f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -95,6 +95,7 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
 import org.chromium.chrome.browser.toolbar.bottom.BottomTabSwitcherActionMenuCoordinator;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager;
 import org.chromium.chrome.browser.toolbar.top.ActionModeController;
 import org.chromium.chrome.browser.toolbar.top.ActionModeController.ActionBarDelegate;
 import org.chromium.chrome.browser.toolbar.top.TabSwitcherActionMenuCoordinator;
@@ -718,6 +719,17 @@
             public void onOverviewModeStartedShowing(boolean showToolbar) {
                 mToolbar.setTabSwitcherMode(true, showToolbar, false);
                 updateButtonStatus();
+                if (FeatureUtilities.isBottomToolbarEnabled()
+                        && !BottomToolbarVariationManager
+                                    .shouldBottomToolbarBeVisibleInOverviewMode()) {
+                    // TODO(crbug.com/1036474): don't tell mToolbar the visibility of bottom toolbar
+                    // has been changed when entering overview, so it won't draw extra animations
+                    // or buttons during the transition. Before, bottom toolbar was always visible
+                    // in portrait mode, so the visibility was equivalent to the orientation change.
+                    // We may have to tell mToolbar extra information, like orientation, in future.
+                    // mToolbar.onBottomToolbarVisibilityChanged(false);
+                    mBottomControlsCoordinator.setBottomControlsVisible(false);
+                }
             }
 
             @Override
@@ -730,6 +742,16 @@
             public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
                 mToolbar.setTabSwitcherMode(false, showToolbar, delayAnimation);
                 updateButtonStatus();
+                if (FeatureUtilities.isBottomToolbarEnabled()
+                        && !BottomToolbarVariationManager
+                                    .shouldBottomToolbarBeVisibleInOverviewMode()) {
+                    // User may enter overview mode in landscape mode but exit in portrait mode.
+                    mIsBottomToolbarVisible = !FeatureUtilities.isAdaptiveToolbarEnabled()
+                            || mActivity.getResources().getConfiguration().orientation
+                                    != Configuration.ORIENTATION_LANDSCAPE;
+                    mToolbar.onBottomToolbarVisibilityChanged(mIsBottomToolbarVisible);
+                    mBottomControlsCoordinator.setBottomControlsVisible(mIsBottomToolbarVisible);
+                }
             }
 
             @Override
@@ -858,8 +880,11 @@
     // TODO(crbug.com/1026020): Move this logic to BottomToolbar class.
     private void onShareDelegateAvailable(ShareDelegate shareDelegate) {
         final OnClickListener shareButtonListener = v -> {
-            recordBottomToolbarUseForIPH();
-            RecordUserAction.record("MobileBottomToolbarShareButton");
+            if (BottomToolbarVariationManager.isShareButtonOnBottom()) {
+                recordBottomToolbarUseForIPH();
+                RecordUserAction.record("MobileBottomToolbarShareButton");
+            }
+
             Tab tab = null;
             Activity activity = null;
             boolean isIncognito = false;
@@ -1041,7 +1066,8 @@
         });
 
         if (mTabGroupPopupUi != null) {
-            mTabGroupPopUiParentSupplier.set(mIsBottomToolbarVisible
+            mTabGroupPopUiParentSupplier.set(
+                    mIsBottomToolbarVisible && BottomToolbarVariationManager.isTabSwitcherOnBottom()
                             ? mActivity.findViewById(R.id.bottom_controls)
                             : mActivity.findViewById(R.id.toolbar));
             mTabGroupPopupUi.initializeWithNative(mActivity);
@@ -1120,9 +1146,6 @@
      */
     public void showAppMenuUpdateBadge() {
         mToolbar.showAppMenuUpdateBadge();
-        if (mBottomControlsCoordinator != null) {
-            mBottomControlsCoordinator.showAppMenuUpdateBadge();
-        }
     }
 
     /**
@@ -1131,9 +1154,6 @@
      */
     public void removeAppMenuUpdateBadge(boolean animate) {
         mToolbar.removeAppMenuUpdateBadge(animate);
-        if (mBottomControlsCoordinator != null) {
-            mBottomControlsCoordinator.removeAppMenuUpdateBadge();
-        }
     }
 
     /**
@@ -1141,10 +1161,6 @@
      * TODO(amaralp): Only the top or bottom menu should be visible.
      */
     public boolean isShowingAppMenuUpdateBadge() {
-        if (mBottomControlsCoordinator != null
-                && mBottomControlsCoordinator.isShowingAppMenuUpdateBadge()) {
-            return true;
-        }
         return mToolbar.isShowingAppMenuUpdateBadge();
     }
 
@@ -1221,15 +1237,12 @@
 
     @Override
     public @Nullable View getMenuButtonView() {
-        if (mBottomControlsCoordinator != null && isBottomToolbarVisible()) {
-            return mBottomControlsCoordinator.getMenuButtonWrapper().getImageButton();
-        }
         return mToolbar.getMenuButton();
     }
 
     @Override
     public boolean isMenuFromBottom() {
-        return isBottomToolbarVisible();
+        return mIsBottomToolbarVisible && BottomToolbarVariationManager.isMenuButtonOnBottom();
     }
 
     /**
@@ -1356,15 +1369,20 @@
         if (mBottomControlsCoordinator != null && FeatureUtilities.isBottomToolbarEnabled()
                 && FeatureUtilities.isAdaptiveToolbarEnabled()) {
             mIsBottomToolbarVisible = newOrientation != Configuration.ORIENTATION_LANDSCAPE;
+            if (!BottomToolbarVariationManager.shouldBottomToolbarBeVisibleInOverviewMode()
+                    && mIsBottomToolbarVisible) {
+                mIsBottomToolbarVisible = !mActivity.isInOverviewMode();
+            }
             mToolbar.onBottomToolbarVisibilityChanged(mIsBottomToolbarVisible);
             mBottomControlsCoordinator.setBottomControlsVisible(mIsBottomToolbarVisible);
             if (mAppMenuButtonHelper != null) {
-                mAppMenuButtonHelper.setMenuShowsFromBottom(mIsBottomToolbarVisible);
+                mAppMenuButtonHelper.setMenuShowsFromBottom(isMenuFromBottom());
             }
             mIdentityDiscController.updateButtonState();
 
             if (mTabGroupPopupUi != null) {
                 mTabGroupPopUiParentSupplier.set(mIsBottomToolbarVisible
+                                        && BottomToolbarVariationManager.isTabSwitcherOnBottom()
                                 ? mActivity.findViewById(R.id.bottom_controls)
                                 : mActivity.findViewById(R.id.toolbar));
             }
@@ -1502,10 +1520,10 @@
             }
         });
         mAppMenuButtonHelper = mAppMenuHandler.createAppMenuButtonHelper();
-        mAppMenuButtonHelper.setMenuShowsFromBottom(isBottomToolbarVisible());
+        mAppMenuButtonHelper.setMenuShowsFromBottom(isMenuFromBottom());
         mAppMenuButtonHelper.setOnAppMenuShownListener(() -> {
             RecordUserAction.record("MobileToolbarShowMenu");
-            if (isBottomToolbarVisible()) {
+            if (isMenuFromBottom()) {
                 RecordUserAction.record("MobileBottomToolbarShowMenu");
             } else {
                 RecordUserAction.record("MobileTopToolbarShowMenu");
@@ -1524,10 +1542,6 @@
 
     @Nullable
     private MenuButton getMenuButtonWrapper() {
-        if (mBottomControlsCoordinator != null) {
-            return mBottomControlsCoordinator.getMenuButtonWrapper();
-        }
-
         return mToolbar.getMenuButtonWrapper();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
index f9e9a9d9..10e9d49 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabGroupUi;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
-import org.chromium.chrome.browser.toolbar.MenuButton;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsViewBinder.ViewHolder;
 import org.chromium.chrome.browser.ui.ImmersiveModeManager;
@@ -177,44 +176,6 @@
     }
 
     /**
-     * Show the update badge over the bottom toolbar's app menu.
-     */
-    public void showAppMenuUpdateBadge() {
-        if (mBottomToolbarCoordinator != null) {
-            mBottomToolbarCoordinator.showAppMenuUpdateBadge();
-        }
-    }
-
-    /**
-     * Remove the update badge.
-     */
-    public void removeAppMenuUpdateBadge() {
-        if (mBottomToolbarCoordinator != null) {
-            mBottomToolbarCoordinator.removeAppMenuUpdateBadge();
-        }
-    }
-
-    /**
-     * @return Whether the update badge is showing.
-     */
-    public boolean isShowingAppMenuUpdateBadge() {
-        if (mBottomToolbarCoordinator != null) {
-            return mBottomToolbarCoordinator.isShowingAppMenuUpdateBadge();
-        }
-        return false;
-    }
-
-    /**
-     * @return The wrapper for the browsing mode toolbar's app menu button.
-     */
-    public MenuButton getMenuButtonWrapper() {
-        if (mBottomToolbarCoordinator != null) {
-            return mBottomToolbarCoordinator.getMenuButtonWrapper();
-        }
-        return null;
-    }
-
-    /**
      * Handles system back press action if needed.
      * @return Whether or not the back press event is consumed here.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java
index eb16977..19475da4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java
@@ -14,11 +14,11 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.ThemeColorProvider;
+import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
 import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
 import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
-import org.chromium.chrome.browser.toolbar.MenuButton;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
 
@@ -43,6 +43,9 @@
     private OverviewModeBehavior mOverviewModeBehavior;
     private OverviewModeObserver mOverviewModeObserver;
 
+    /** The activity tab provider. */
+    private ActivityTabProvider mTabProvider;
+
     /**
      * Build the coordinator that manages the bottom toolbar.
      * @param stub The bottom toolbar {@link ViewStub} to inflate.
@@ -66,6 +69,7 @@
         mTabSwitcherModeStub = root.findViewById(R.id.bottom_toolbar_tab_switcher_mode_stub);
 
         mThemeColorProvider = themeColorProvider;
+        mTabProvider = tabProvider;
     }
 
     /**
@@ -90,18 +94,44 @@
             AppMenuButtonHelper menuButtonHelper, OverviewModeBehavior overviewModeBehavior,
             TabCountProvider tabCountProvider, IncognitoStateProvider incognitoStateProvider,
             ViewGroup topToolbarRoot) {
-        mBrowsingModeCoordinator.initializeWithNative(tabSwitcherListener, menuButtonHelper,
-                tabCountProvider, mThemeColorProvider, incognitoStateProvider,
+        mBrowsingModeCoordinator.initializeWithNative(newTabClickListener, tabSwitcherListener,
+                menuButtonHelper, tabCountProvider, mThemeColorProvider, incognitoStateProvider,
                 overviewModeBehavior);
         mTabSwitcherModeCoordinator = new TabSwitcherBottomToolbarCoordinator(mTabSwitcherModeStub,
                 topToolbarRoot, incognitoStateProvider, mThemeColorProvider, newTabClickListener,
                 closeTabsClickListener, menuButtonHelper, tabCountProvider);
+
         // Do not change bottom bar if StartSurface Single Pane is enabled and HomePage is not
         // customized.
-        if (!ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage()) {
+        if (!ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage()
+                && BottomToolbarVariationManager.shouldBottomToolbarBeVisibleInOverviewMode()) {
             mOverviewModeBehavior = overviewModeBehavior;
-            mOverviewModeObserver = new BottomToolbarAnimationCoordinator(
-                    mBrowsingModeCoordinator, mTabSwitcherModeCoordinator);
+            mOverviewModeObserver = new EmptyOverviewModeObserver() {
+                @Override
+                public void onOverviewModeStartedShowing(boolean showToolbar) {
+                    mBrowsingModeCoordinator.getSearchAccelerator().setEnabled(false);
+                    if (BottomToolbarVariationManager.isShareButtonOnBottom()) {
+                        mBrowsingModeCoordinator.getShareButton().setEnabled(false);
+                    }
+                    if (BottomToolbarVariationManager.isHomeButtonOnBottom()) {
+                        mBrowsingModeCoordinator.getHomeButton().setEnabled(false);
+                    }
+                }
+
+                @Override
+                public void onOverviewModeStartedHiding(
+                        boolean showToolbar, boolean delayAnimation) {
+                    mBrowsingModeCoordinator.getSearchAccelerator().setEnabled(true);
+                    if (BottomToolbarVariationManager.isShareButtonOnBottom()) {
+                        mBrowsingModeCoordinator.getShareButton().updateButtonEnabledState(
+                                mTabProvider.get());
+                    }
+                    if (BottomToolbarVariationManager.isHomeButtonOnBottom()) {
+                        mBrowsingModeCoordinator.getHomeButton().updateButtonEnabledState(
+                                mTabProvider.get());
+                    }
+                }
+            };
             if (mOverviewModeBehavior != null) {
                 mOverviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver);
             }
@@ -119,34 +149,6 @@
     }
 
     /**
-     * Show the update badge over the bottom toolbar's app menu.
-     */
-    void showAppMenuUpdateBadge() {
-        mBrowsingModeCoordinator.showAppMenuUpdateBadge();
-    }
-
-    /**
-     * Remove the update badge.
-     */
-    void removeAppMenuUpdateBadge() {
-        mBrowsingModeCoordinator.removeAppMenuUpdateBadge();
-    }
-
-    /**
-     * @return Whether the update badge is showing.
-     */
-    boolean isShowingAppMenuUpdateBadge() {
-        return mBrowsingModeCoordinator.isShowingAppMenuUpdateBadge();
-    }
-
-    /**
-     * @return The wrapper for the browsing mode toolbar's app menu button.
-     */
-    MenuButton getMenuButtonWrapper() {
-        return mBrowsingModeCoordinator.getMenuButton();
-    }
-
-    /**
      * Clean up any state when the bottom toolbar is destroyed.
      */
     void destroy() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java
index be823cc..a501280 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarNewTabButton.java
@@ -9,7 +9,6 @@
 import android.content.res.Resources;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.support.graphics.drawable.VectorDrawableCompat;
 import android.util.AttributeSet;
 
 import androidx.annotation.StringRes;
@@ -30,7 +29,7 @@
 class BottomToolbarNewTabButton extends ChromeImageButton
         implements IncognitoStateObserver, ThemeColorObserver, TintObserver {
     /** The gray pill background behind the plus icon. */
-    private final Drawable mBackground;
+    private Drawable mBackground;
 
     /** The {@link Resources} used to compute the background color. */
     private final Resources mResources;
@@ -45,13 +44,12 @@
         super(context, attrs);
 
         mResources = context.getResources();
+    }
 
-        setImageDrawable(VectorDrawableCompat.create(
-                getContext().getResources(), R.drawable.new_tab_icon, getContext().getTheme()));
-
-        mBackground = ApiCompatibilityUtils.getDrawable(mResources, R.drawable.ntp_search_box);
-        mBackground.mutate();
-        setBackground(mBackground);
+    @Override
+    public void setBackground(Drawable background) {
+        super.setBackground(background);
+        mBackground = background;
     }
 
     /**
@@ -101,8 +99,9 @@
     }
 
     private void updateBackground() {
-        if (mThemeColorProvider == null || mIncognitoStateProvider == null) return;
-
+        if (mThemeColorProvider == null || mIncognitoStateProvider == null || mBackground == null) {
+            return;
+        }
         mBackground.setColorFilter(
                 ToolbarColors.getTextBoxColorForToolbarBackgroundInNonNativePage(mResources,
                         mThemeColorProvider.getThemeColor(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarVariationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarVariationManager.java
new file mode 100644
index 0000000..5aca8d3
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarVariationManager.java
@@ -0,0 +1,119 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.toolbar.bottom;
+
+import androidx.annotation.StringDef;
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.chrome.browser.flags.FeatureUtilities;
+import org.chromium.chrome.browser.incognito.IncognitoUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * The variation manager helps figure out the current variation and the visibility of buttons on
+ * bottom toolbar. Every operation related to the variation, e.g. getting variation value, should be
+ * through {@link BottomToolbarVariationManager} rather than calling {@link FeatureUtilities}.
+ */
+public class BottomToolbarVariationManager {
+    @StringDef({Variations.NONE, Variations.HOME_SEARCH_TAB_SWITCHER, Variations.HOME_SEARCH_SHARE,
+            Variations.NEW_TAB_SEARCH_SHARE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Variations {
+        String NONE = "";
+        String HOME_SEARCH_TAB_SWITCHER = "HomeSearchTabSwitcher";
+        String HOME_SEARCH_SHARE = "HomeSearchShare";
+        String NEW_TAB_SEARCH_SHARE = "NewTabSearchShare";
+    }
+
+    private static String sVariation;
+
+    /**
+     * @return The currently enabled bottom toolbar variation.
+     *         Should be called after FeatureUtilities.isBottomToolbarEnabled().
+     */
+    private static @Variations String getVariation() {
+        if (sVariation != null) return sVariation;
+        if (!FeatureUtilities.isBottomToolbarEnabled()) {
+            return Variations.HOME_SEARCH_TAB_SWITCHER;
+        }
+        sVariation = FeatureUtilities.getBottomToolbarVariation();
+        if (sVariation.equals(Variations.NONE)) {
+            return Variations.HOME_SEARCH_TAB_SWITCHER;
+        }
+        return sVariation;
+    }
+
+    /**
+     * @return Whether or not share button should be visible on the top toolbar in portrait mode
+     *         in the current variation.
+     */
+    public static boolean isShareButtonOnBottom() {
+        return FeatureUtilities.isBottomToolbarEnabled()
+                && !getVariation().equals(Variations.HOME_SEARCH_TAB_SWITCHER);
+    }
+
+    /**
+     * @return Whether or not new tab button should be visible on the bottom toolbar
+     *         in portrait mode in the current variation.
+     */
+    public static boolean isNewTabButtonOnBottom() {
+        return FeatureUtilities.isBottomToolbarEnabled()
+                && getVariation().equals(Variations.NEW_TAB_SEARCH_SHARE);
+    }
+
+    /**
+     * @return Whether or not menu button should be visible on the top toolbar
+     *         in portrait mode in the current variation.
+     */
+    public static boolean isMenuButtonOnBottom() {
+        // If we don't have variations that put menu on bottom in the future,
+        // then this method can be removed.
+        return false;
+    }
+
+    /**
+     * @return Whether or not bottom toolbar should be visible in overview mode of portrait mode
+     *         in the current variation.
+     */
+    public static boolean shouldBottomToolbarBeVisibleInOverviewMode() {
+        return (getVariation().equals(Variations.NEW_TAB_SEARCH_SHARE)
+                       && !FeatureUtilities.isStartSurfaceEnabled())
+                || ((!FeatureUtilities.isGridTabSwitcherEnabled()
+                            || !IncognitoUtils.isIncognitoModeEnabled())
+                        && getVariation().equals(Variations.HOME_SEARCH_TAB_SWITCHER));
+    }
+
+    /**
+     * @return Whether or not home button should be visible in top toolbar of portrait mode
+     *         in current variation.
+     */
+    public static boolean isHomeButtonOnBottom() {
+        return FeatureUtilities.isBottomToolbarEnabled()
+                && !getVariation().equals(Variations.NEW_TAB_SEARCH_SHARE);
+    }
+
+    /**
+     * @return Whether or not tab switcher button should be visible in bottom toolbar
+     *         of portrait mode in current variation.
+     */
+    public static boolean isTabSwitcherOnBottom() {
+        return FeatureUtilities.isBottomToolbarEnabled()
+                && getVariation().equals(Variations.HOME_SEARCH_TAB_SWITCHER);
+    }
+
+    /**
+     * @return Name of the variation parameter of bottom toolbar.
+     */
+    public static String getVariationParamName() {
+        return "chrome_duet_variation";
+    }
+
+    @VisibleForTesting
+    public static void setVariation(String variation) {
+        sVariation = variation;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
index 73acce327..c770288 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
 import org.chromium.chrome.browser.toolbar.HomeButton;
 import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
-import org.chromium.chrome.browser.toolbar.MenuButton;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.toolbar.TabSwitcherButtonCoordinator;
 import org.chromium.chrome.browser.toolbar.TabSwitcherButtonView;
@@ -45,6 +44,9 @@
     /** The share button that lives in the bottom toolbar. */
     private final ShareButton mShareButton;
 
+    /** The new tab button that lives in the bottom toolbar. */
+    private final BottomToolbarNewTabButton mNewTabButton;
+
     /** The search accelerator that lives in the bottom toolbar. */
     private final SearchAccelerator mSearchAccelerator;
 
@@ -54,9 +56,6 @@
     /** The tab switcher button view that lives in the bottom toolbar. */
     private final TabSwitcherButtonView mTabSwitcherButtonView;
 
-    /** The menu button that lives in the browsing mode bottom toolbar. */
-    private final MenuButton mMenuButton;
-
     /** The view group that includes all views shown on browsing mode */
     private final BrowsingModeBottomToolbarLinearLayout mToolbarRoot;
 
@@ -64,10 +63,10 @@
     private final BrowsingModeBottomToolbarModel mModel;
 
     /** The callback to be exectured when the share button on click listener is available. */
-    private final Callback<OnClickListener> mShareButtonListenerSupplierCallback;
+    private Callback<OnClickListener> mShareButtonListenerSupplierCallback;
 
     /** The supplier for the share button on click listener. */
-    private final ObservableSupplier<OnClickListener> mShareButtonListenerSupplier;
+    private ObservableSupplier<OnClickListener> mShareButtonListenerSupplier;
 
     /** The activity tab provider that used for making the IPH. */
     private final ActivityTabProvider mTabProvider;
@@ -83,7 +82,7 @@
     BrowsingModeBottomToolbarCoordinator(View root, ActivityTabProvider tabProvider,
             OnClickListener homeButtonListener, OnClickListener searchAcceleratorListener,
             ObservableSupplier<OnClickListener> shareButtonListenerSupplier,
-            OnLongClickListener tabSwitcherLongClickListner) {
+            OnLongClickListener tabSwitcherLongClickListener) {
         mModel = new BrowsingModeBottomToolbarModel();
         mToolbarRoot = root.findViewById(R.id.bottom_toolbar_browsing);
         mTabProvider = tabProvider;
@@ -93,30 +92,44 @@
 
         mMediator = new BrowsingModeBottomToolbarMediator(mModel);
 
-        mHomeButton = mToolbarRoot.findViewById(R.id.home_button);
+        mHomeButton = mToolbarRoot.findViewById(R.id.bottom_home_button);
         mHomeButton.setOnClickListener(homeButtonListener);
         mHomeButton.setActivityTabProvider(mTabProvider);
         setupIPH(FeatureConstants.CHROME_DUET_HOME_BUTTON_FEATURE, mHomeButton, homeButtonListener);
 
-        mShareButton = mToolbarRoot.findViewById(R.id.share_button);
-        mShareButtonListenerSupplierCallback = shareButtonListener -> {
-            mShareButton.setOnClickListener(shareButtonListener);
-        };
-        mShareButtonListenerSupplier = shareButtonListenerSupplier;
-        mShareButtonListenerSupplier.addObserver(mShareButtonListenerSupplierCallback);
-        mShareButton.setActivityTabProvider(mTabProvider);
+        mNewTabButton = mToolbarRoot.findViewById(R.id.bottom_new_tab_button);
+
+        mShareButton = mToolbarRoot.findViewById(R.id.bottom_share_button);
 
         mSearchAccelerator = mToolbarRoot.findViewById(R.id.search_accelerator);
         mSearchAccelerator.setOnClickListener(searchAcceleratorListener);
         setupIPH(FeatureConstants.CHROME_DUET_SEARCH_FEATURE, mSearchAccelerator,
                 searchAcceleratorListener);
 
-        mTabSwitcherButtonCoordinator = new TabSwitcherButtonCoordinator(mToolbarRoot);
         // TODO(amaralp): Make this adhere to MVC framework.
-        mTabSwitcherButtonView = mToolbarRoot.findViewById(R.id.tab_switcher_button);
+        mTabSwitcherButtonView = mToolbarRoot.findViewById(R.id.bottom_tab_switcher_button);
+        mTabSwitcherButtonCoordinator = new TabSwitcherButtonCoordinator(mTabSwitcherButtonView);
 
-        mTabSwitcherButtonView.setOnLongClickListener(tabSwitcherLongClickListner);
-        mMenuButton = mToolbarRoot.findViewById(R.id.menu_button_wrapper);
+        mTabSwitcherButtonView.setOnLongClickListener(tabSwitcherLongClickListener);
+        if (BottomToolbarVariationManager.isNewTabButtonOnBottom()) {
+            mNewTabButton.setVisibility(View.VISIBLE);
+        }
+        if (BottomToolbarVariationManager.isHomeButtonOnBottom()) {
+            mHomeButton.setVisibility(View.VISIBLE);
+        }
+
+        if (BottomToolbarVariationManager.isTabSwitcherOnBottom()) {
+            mTabSwitcherButtonView.setVisibility(View.VISIBLE);
+        }
+        if (BottomToolbarVariationManager.isShareButtonOnBottom()) {
+            mShareButton.setVisibility(View.VISIBLE);
+            mShareButtonListenerSupplierCallback = shareButtonListener -> {
+                mShareButton.setOnClickListener(shareButtonListener);
+            };
+            mShareButtonListenerSupplier = shareButtonListenerSupplier;
+            mShareButton.setActivityTabProvider(mTabProvider);
+            mShareButtonListenerSupplier.addObserver(mShareButtonListenerSupplierCallback);
+        }
     }
 
     /**
@@ -166,6 +179,8 @@
      * Calling this must occur after the native library have completely loaded.
      * @param tabSwitcherListener An {@link OnClickListener} that is triggered when the
      *                            tab switcher button is clicked.
+     * @param tabSwitcherListener An {@link OnClickListener} that is triggered when the
+     *                            tab switcher button is clicked.
      * @param menuButtonHelper An {@link AppMenuButtonHelper} that is triggered when the
      *                         menu button is clicked.
      * @param tabCountProvider Updates the tab count number in the tab switcher button.
@@ -173,32 +188,41 @@
      * @param incognitoStateProvider Notifies components when incognito state changes.
      * @param overviewModeBehavior Notifies components when overview mode changes.
      */
-    void initializeWithNative(OnClickListener tabSwitcherListener,
+    void initializeWithNative(OnClickListener newTabListener, OnClickListener tabSwitcherListener,
             AppMenuButtonHelper menuButtonHelper, TabCountProvider tabCountProvider,
             ThemeColorProvider themeColorProvider, IncognitoStateProvider incognitoStateProvider,
             OverviewModeBehavior overviewModeBehavior) {
         mMediator.setThemeColorProvider(themeColorProvider);
+        if (BottomToolbarVariationManager.isNewTabButtonOnBottom()) {
+            mNewTabButton.setOnClickListener(newTabListener);
+            mNewTabButton.setThemeColorProvider(themeColorProvider);
+            mNewTabButton.setIncognitoStateProvider(incognitoStateProvider);
+        }
+        if (BottomToolbarVariationManager.isHomeButtonOnBottom()) {
+            mHomeButton.setThemeColorProvider(themeColorProvider);
+        }
 
-        mHomeButton.setThemeColorProvider(themeColorProvider);
-        mShareButton.setThemeColorProvider(themeColorProvider);
+        if (BottomToolbarVariationManager.isShareButtonOnBottom()) {
+            mShareButton.setThemeColorProvider(themeColorProvider);
+        }
+
         mSearchAccelerator.setThemeColorProvider(themeColorProvider);
         mSearchAccelerator.setIncognitoStateProvider(incognitoStateProvider);
 
-        mTabSwitcherButtonCoordinator.setTabSwitcherListener(tabSwitcherListener);
-        mTabSwitcherButtonCoordinator.setThemeColorProvider(themeColorProvider);
-        mTabSwitcherButtonCoordinator.setTabCountProvider(tabCountProvider);
-        // Send null to IPH here to avoid tabSwitcherListener to be called twince, since
-        // mTabSwitcherButtonView has it own OnClickListener, but other buttons set OnClickListener
-        // to their wrappers.
-        setupIPH(FeatureConstants.CHROME_DUET_TAB_SWITCHER_FEATURE, mTabSwitcherButtonView, null);
-
-        assert menuButtonHelper != null;
-        mMenuButton.setAppMenuButtonHelper(menuButtonHelper);
-        mMenuButton.setThemeColorProvider(themeColorProvider);
+        if (BottomToolbarVariationManager.isTabSwitcherOnBottom()) {
+            mTabSwitcherButtonCoordinator.setTabSwitcherListener(tabSwitcherListener);
+            mTabSwitcherButtonCoordinator.setThemeColorProvider(themeColorProvider);
+            mTabSwitcherButtonCoordinator.setTabCountProvider(tabCountProvider);
+            // Send null to IPH here to avoid tabSwitcherListener to be called twince, since
+            // mTabSwitcherButtonView has it own OnClickListener, but other buttons set
+            // OnClickListener to their wrappers.
+            setupIPH(FeatureConstants.CHROME_DUET_TAB_SWITCHER_FEATURE, mTabSwitcherButtonView,
+                    null);
+        }
 
         // If StartSurface is HomePage, BrowsingModeBottomToolbar is shown in browsing mode and in
         // overview mode. We need to pass the OverviewModeBehavior to the buttons so they are
-        // disabled based on the moverview state.
+        // disabled based on the overview state.
         if (ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage()) {
             mShareButton.setOverviewModeBehavior(overviewModeBehavior);
             mTabSwitcherButtonCoordinator.setOverviewModeBehavior(overviewModeBehavior);
@@ -207,27 +231,6 @@
     }
 
     /**
-     * Show the update badge over the bottom toolbar's app menu.
-     */
-    void showAppMenuUpdateBadge() {
-        mMenuButton.showAppMenuUpdateBadgeIfAvailable(true);
-    }
-
-    /**
-     * Remove the update badge.
-     */
-    void removeAppMenuUpdateBadge() {
-        mMenuButton.removeAppMenuUpdateBadge(true);
-    }
-
-    /**
-     * @return Whether the update badge is showing.
-     */
-    boolean isShowingAppMenuUpdateBadge() {
-        return mMenuButton.isShowingAppMenuUpdateBadge();
-    }
-
-    /**
      * @param enabled Whether to disable click events on the bottom toolbar. Setting true can also
      *                prevent from all click events on toolbar and all children views on toolbar.
      */
@@ -243,13 +246,6 @@
     }
 
     /**
-     * @return The browsing mode bottom toolbar's menu button.
-     */
-    MenuButton getMenuButton() {
-        return mMenuButton;
-    }
-
-    /**
      * @return The browsing mode bottom toolbar's share button.
      */
     ShareButton getShareButton() {
@@ -281,12 +277,13 @@
      * Clean up any state when the browsing mode bottom toolbar is destroyed.
      */
     public void destroy() {
-        mShareButtonListenerSupplier.removeObserver(mShareButtonListenerSupplierCallback);
+        if (mShareButtonListenerSupplier != null) {
+            mShareButtonListenerSupplier.removeObserver(mShareButtonListenerSupplierCallback);
+        }
         mMediator.destroy();
         mHomeButton.destroy();
         mShareButton.destroy();
         mSearchAccelerator.destroy();
         mTabSwitcherButtonCoordinator.destroy();
-        mMenuButton.destroy();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java
index 73b0ff9..e4bacfa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java
@@ -10,7 +10,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.view.View;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
@@ -39,9 +38,6 @@
     /** A provider that notifies when incognito mode is entered or exited. */
     private IncognitoStateProvider mIncognitoStateProvider;
 
-    /** The wrapper View that contains the search accelerator and the label. */
-    private View mWrapper;
-
     public SearchAccelerator(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -52,15 +48,6 @@
         setBackground(mBackground);
     }
 
-    @Override
-    public void setOnClickListener(OnClickListener listener) {
-        if (mWrapper != null) {
-            mWrapper.setOnClickListener(listener);
-        } else {
-            super.setOnClickListener(listener);
-        }
-    }
-
     void setThemeColorProvider(ThemeColorProvider themeColorProvider) {
         mThemeColorProvider = themeColorProvider;
         mThemeColorProvider.addThemeColorObserver(this);
@@ -93,6 +80,7 @@
     @Override
     public void onTintChanged(ColorStateList tint, boolean useLight) {
         ApiCompatibilityUtils.setImageTintList(this, tint);
+        updateBackground();
     }
 
     @Override
@@ -105,7 +93,8 @@
 
         mBackground.setColorFilter(ToolbarColors.getTextBoxColorForToolbarBackgroundInNonNativePage(
                                            mResources, mThemeColorProvider.getThemeColor(),
-                                           mIncognitoStateProvider.isIncognitoSelected()),
+                                           mIncognitoStateProvider.isIncognitoSelected()
+                                                   && mThemeColorProvider.useLight()),
                 PorterDuff.Mode.SRC_IN);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
index 0d9bd287..c08514c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
@@ -90,7 +90,11 @@
         }
     }
 
-    private void updateButtonEnabledState(Tab tab) {
+    public void updateButtonEnabledState(Tab tab) {
+        if (tab == null) {
+            setEnabled(false);
+            return;
+        }
         final String url = tab.getUrl();
         final boolean isChromeScheme = url.startsWith(UrlConstants.CHROME_URL_PREFIX)
                 || url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java
index 27881e593..0d834990 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java
@@ -4,11 +4,13 @@
 
 package org.chromium.chrome.browser.toolbar.bottom;
 
+import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ThemeColorProvider;
 import org.chromium.chrome.browser.flags.FeatureUtilities;
@@ -21,6 +23,8 @@
 /**
  * The coordinator for the tab switcher mode bottom toolbar. This class handles all interactions
  * that the tab switcher bottom toolbar has with the outside world.
+ * TODO(crbug.com/1036474): This coordinator is not used currently and can be removed if the final
+ *                          duet design doesn't need a stand-alone toolbar in tab switcher mode.
  */
 public class TabSwitcherBottomToolbarCoordinator {
     /** The mediator that handles events from outside the tab switcher bottom toolbar. */
@@ -82,6 +86,10 @@
         mCloseAllTabsButton.setVisibility(View.INVISIBLE);
 
         mNewTabButton = root.findViewById(R.id.tab_switcher_new_tab_button);
+        Drawable background =
+                ApiCompatibilityUtils.getDrawable(root.getResources(), R.drawable.ntp_search_box);
+        background.mutate();
+        mNewTabButton.setBackground(background);
         mNewTabButton.setOnClickListener(newTabClickListener);
         mNewTabButton.setIncognitoStateProvider(incognitoStateProvider);
         mNewTabButton.setThemeColorProvider(themeColorProvider);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
index f3c79db..2282856 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeState;
-import org.chromium.chrome.browser.flags.FeatureUtilities;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
@@ -46,7 +45,7 @@
 
     StartSurfaceToolbarMediator(PropertyModel model) {
         mPropertyModel = model;
-        mPropertyModel.set(MENU_IS_VISIBLE, !FeatureUtilities.isBottomToolbarEnabled());
+        mPropertyModel.set(MENU_IS_VISIBLE, true);
         mOverviewModeState = OverviewModeState.NOT_SHOWN;
     }
 
@@ -118,9 +117,7 @@
         mPropertyModel.set(ACCESSIBILITY_ENABLED, enabled);
     }
 
-    void onBottomToolbarVisibilityChanged(boolean isVisible) {
-        mPropertyModel.set(MENU_IS_VISIBLE, !isVisible);
-    }
+    void onBottomToolbarVisibilityChanged(boolean isVisible) {}
 
     void setOverviewModeBehavior(OverviewModeBehavior overviewModeBehavior) {
         assert mOverviewModeBehavior == null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java
index 4593e37..903ebbb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java
@@ -31,12 +31,12 @@
 import org.chromium.chrome.browser.toolbar.NewTabButton;
 import org.chromium.chrome.browser.toolbar.TabCountProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.widget.animation.CancelAwareAnimatorListener;
 import org.chromium.components.browser_ui.widget.animation.Interpolators;
-import org.chromium.ui.UiUtils;
 import org.chromium.ui.widget.OptimizedFrameLayout;
 
 /** The tab switcher mode top toolbar shown on phones. */
@@ -64,7 +64,7 @@
     private ColorStateList mDarkIconTint;
 
     private boolean mIsIncognito;
-    private boolean mShouldShowButtons;
+    private boolean mShouldShowNewTabButton;
     private boolean mShouldShowNewTabVariation;
 
     private ObjectAnimator mVisiblityAnimator;
@@ -82,38 +82,15 @@
         mMenuButton = findViewById(R.id.menu_button_wrapper);
         mToggleTabStackButton = findViewById(R.id.tab_switcher_mode_tab_switcher_button);
 
-        boolean isBottomToolbarEnabled = FeatureUtilities.isBottomToolbarEnabled();
-        boolean isGridTabSwitcherEnabled = FeatureUtilities.isGridTabSwitcherEnabled();
+        // TODO(twellington): Try to make NewTabButton responsible for handling its own clicks.
+        //                    TabSwitcherBottomToolbarCoordinator also uses NewTabButton and
+        //                    sets an onClickListener directly on NewTabButton rather than
+        //                    acting as the click listener itself so the behavior between this
+        //                    class and the bottom toolbar will need to be unified.
+        mNewTabImageButton.setOnClickListener(this);
+        mNewTabViewButton.setOnClickListener(this);
 
-        if (isBottomToolbarEnabled && !isGridTabSwitcherEnabled) {
-            UiUtils.removeViewFromParent(mNewTabImageButton);
-            mNewTabImageButton.destroy();
-            mNewTabImageButton = null;
-
-            UiUtils.removeViewFromParent(mMenuButton);
-            mMenuButton.destroy();
-            mMenuButton = null;
-
-            UiUtils.removeViewFromParent(mToggleTabStackButton);
-            mToggleTabStackButton.destroy();
-            mToggleTabStackButton = null;
-
-            UiUtils.removeViewFromParent(mNewTabViewButton);
-            mNewTabViewButton = null;
-        } else {
-            // TODO(twellington): Try to make NewTabButton responsible for handling its own clicks.
-            //                    TabSwitcherBottomToolbarCoordinator also uses NewTabButton and
-            //                    sets an onClickListener directly on NewTabButton rather than
-            //                    acting as the click listener itself so the behavior between this
-            //                    class and the bottom toolbar will need to be unified.
-            mNewTabImageButton.setOnClickListener(this);
-            mNewTabViewButton.setOnClickListener(this);
-        }
-
-        if ((usingHorizontalTabSwitcher() || FeatureUtilities.isGridTabSwitcherEnabled())
-                && IncognitoUtils.isIncognitoModeEnabled()) {
-            updateTabSwitchingElements(true);
-        }
+        updateTabSwitchingElements(shouldShowIncognitoToggle());
     }
 
     @Override
@@ -295,11 +272,14 @@
      * @param isVisible Whether the bottom toolbar is visible.
      */
     void onBottomToolbarVisibilityChanged(boolean isVisible) {
-        // When bottom toolbar is showing, hide buttons in top toolbar that have overlapping
-        // functionality; otherwise show buttons in top toolbar.
-        mShouldShowButtons = !isVisible;
-        setNewTabButtonVisibility(mShouldShowButtons);
-        setMenuButtonVisibility(mShouldShowButtons);
+        mShouldShowNewTabButton = !isVisible
+                || (FeatureUtilities.isBottomToolbarEnabled()
+                        && !BottomToolbarVariationManager.isNewTabButtonOnBottom());
+        setNewTabButtonVisibility(mShouldShowNewTabButton);
+        // show tab switcher button on the top in landscape mode.
+        if (BottomToolbarVariationManager.isTabSwitcherOnBottom() && !shouldShowIncognitoToggle()) {
+            mToggleTabStackButton.setVisibility(isVisible ? GONE : VISIBLE);
+        }
     }
 
     private void setNewTabButtonVisibility(boolean isButtonVisible) {
@@ -414,6 +394,15 @@
         setToggleTabStackButtonVisibility(!showIncognitoToggle);
     }
 
+    /**
+     * @return Whether or not incognito toggle should be visible based on the enabled features
+     *         and incognito status.
+     */
+    private boolean shouldShowIncognitoToggle() {
+        return (usingHorizontalTabSwitcher() || FeatureUtilities.isGridTabSwitcherEnabled())
+                && IncognitoUtils.isIncognitoModeEnabled();
+    }
+
     private void updateIncognitoToggleTabsVisibility() {
         // TODO(yuezhanggg): Add a regression test for this "New Tab" variation. (crbug: 977546)
         if (!FeatureUtilities.isGridTabSwitcherEnabled() || !ChromeFeatureList.isInitialized()
@@ -430,7 +419,7 @@
         // Show new tab variation when there are no incognito tabs.
         mShouldShowNewTabVariation = !hasIncognitoTabs();
         mIncognitoToggleTabLayout.setVisibility(mShouldShowNewTabVariation ? GONE : VISIBLE);
-        setNewTabButtonVisibility(mShouldShowButtons);
+        setNewTabButtonVisibility(mShouldShowNewTabButton);
     }
 
     private boolean hasIncognitoTabs() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index 5efae4f1..f1c571ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -73,6 +73,7 @@
 import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable;
 import org.chromium.chrome.browser.toolbar.ToolbarColors;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager;
 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator.UrlExpansionObserver;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.ViewUtils;
@@ -376,7 +377,7 @@
 
             setLayoutTransition(null);
 
-            if (getMenuButtonWrapper() != null && !mIsBottomToolbarVisible) {
+            if (getMenuButtonWrapper() != null) {
                 getMenuButtonWrapper().setVisibility(View.VISIBLE);
             }
 
@@ -945,7 +946,7 @@
 
         int toolbarButtonVisibility = getToolbarButtonVisibility();
         mToolbarButtonsContainer.setVisibility(toolbarButtonVisibility);
-        if (!mIsBottomToolbarVisible && !getToolbarDataProvider().isInOverviewAndShowingOmnibox()) {
+        if (!getToolbarDataProvider().isInOverviewAndShowingOmnibox()) {
             if (mHomeButton != null && mHomeButton.getVisibility() != GONE) {
                 mHomeButton.setVisibility(toolbarButtonVisibility);
             }
@@ -1286,9 +1287,9 @@
             canvas.restore();
         }
 
-        // Draw the tab stack button and associated text.
+        // Draw the tab stack button and associated text if necessary.
         if (mTabSwitcherAnimationTabStackDrawable != null && mToggleTabStackButton != null
-                && !mIsBottomToolbarVisible && mUrlExpansionPercent != 1f) {
+                && mUrlExpansionPercent != 1f && !isTabSwitcherOnBottom()) {
             // Draw the tab stack button image.
             canvas.save();
             translateCanvasToView(mToolbarButtonsContainer, mToggleTabStackButton, canvas);
@@ -1316,7 +1317,7 @@
 
         // Draw the menu button if necessary.
         final ImageButton menuButton = getMenuButton();
-        if (menuButton != null && !mIsBottomToolbarVisible && !isShowingAppMenuUpdateBadge()
+        if (menuButton != null && !isShowingAppMenuUpdateBadge()
                 && mTabSwitcherAnimationMenuDrawable != null && mUrlExpansionPercent != 1f) {
             mTabSwitcherAnimationMenuDrawable.setBounds(menuButton.getPaddingLeft(),
                     menuButton.getPaddingTop(),
@@ -1334,8 +1335,8 @@
                                             : mTabSwitcherAnimationMenuBadgeDarkDrawable;
 
         final View menuBadge = getMenuBadge();
-        if (menuBadge != null && !mIsBottomToolbarVisible && isShowingAppMenuUpdateBadge()
-                && badgeDrawable != null && mUrlExpansionPercent != 1f) {
+        if (menuBadge != null && isShowingAppMenuUpdateBadge() && badgeDrawable != null
+                && mUrlExpansionPercent != 1f) {
             badgeDrawable.setBounds(menuBadge.getPaddingLeft(), menuBadge.getPaddingTop(),
                     menuBadge.getWidth() - menuBadge.getPaddingRight(),
                     menuBadge.getHeight() - menuBadge.getPaddingBottom());
@@ -1656,7 +1657,8 @@
     public void updateButtonVisibility() {
         if (mHomeButton == null) return;
 
-        boolean hideHomeButton = !mIsHomeButtonEnabled || mIsBottomToolbarVisible
+        boolean hideHomeButton = !mIsHomeButtonEnabled
+                || (mIsBottomToolbarVisible && BottomToolbarVariationManager.isHomeButtonOnBottom())
                 || (FeatureUtilities.isStartSurfaceEnabled()
                         && !FeatureUtilities.isStartSurfaceSinglePaneEnabled());
         if (hideHomeButton) {
@@ -1906,8 +1908,8 @@
         mIsHomeButtonEnabled = !inTabSwitcherMode;
 
         if (mToggleTabStackButton != null) {
-            mToggleTabStackButton.setVisibility(
-                    inTabSwitcherMode || mIsBottomToolbarVisible ? GONE : VISIBLE);
+            boolean isGone = inTabSwitcherMode || isTabSwitcherOnBottom();
+            mToggleTabStackButton.setVisibility(isGone ? GONE : VISIBLE);
         }
 
         if (getMenuButton() != null) {
@@ -2025,7 +2027,7 @@
                 MathUtils.flipSignIf(URL_FOCUS_TOOLBAR_BUTTONS_TRANSLATION_X_DP, isRtl) * density;
 
         final View menuButtonWrapper = getMenuButtonWrapper();
-        if (menuButtonWrapper != null && !mIsBottomToolbarVisible) {
+        if (menuButtonWrapper != null) {
             animator = ObjectAnimator.ofFloat(
                     menuButtonWrapper, TRANSLATION_X, toolbarButtonTranslationX);
             animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS);
@@ -2038,7 +2040,7 @@
             animators.add(animator);
         }
 
-        if (mToggleTabStackButton != null && !mIsBottomToolbarVisible) {
+        if (mToggleTabStackButton != null && !isTabSwitcherOnBottom()) {
             animator = ObjectAnimator.ofFloat(
                     mToggleTabStackButton, TRANSLATION_X, toolbarButtonTranslationX);
             animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS);
@@ -2077,7 +2079,7 @@
         animators.add(animator);
 
         final View menuButtonWrapper = getMenuButtonWrapper();
-        if (menuButtonWrapper != null && !mIsBottomToolbarVisible) {
+        if (menuButtonWrapper != null) {
             animator = ObjectAnimator.ofFloat(menuButtonWrapper, TRANSLATION_X, 0);
             animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS);
             animator.setStartDelay(URL_CLEAR_FOCUS_MENU_DELAY_MS);
@@ -2091,7 +2093,7 @@
             animators.add(animator);
         }
 
-        if (mToggleTabStackButton != null && !mIsBottomToolbarVisible) {
+        if (mToggleTabStackButton != null && !isTabSwitcherOnBottom()) {
             animator = ObjectAnimator.ofFloat(mToggleTabStackButton, TRANSLATION_X, 0);
             animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS);
             animator.setStartDelay(URL_CLEAR_FOCUS_TABSTACK_DELAY_MS);
@@ -2432,6 +2434,14 @@
         return getToolbarDataProvider().getPrimaryColor();
     }
 
+    /**
+     * @return Whether tab switcher is shown on the bottom toolbar.
+     *         Return false when bottom toolbar is not visible.
+     */
+    private boolean isTabSwitcherOnBottom() {
+        return mIsBottomToolbarVisible && BottomToolbarVariationManager.isTabSwitcherOnBottom();
+    }
+
     private void updateVisualsForLocationBarState() {
         // These are used to skip setting state unnecessarily while in the tab switcher.
         boolean inOrEnteringStaticTab =
@@ -2828,9 +2838,7 @@
     public void onBottomToolbarVisibilityChanged(boolean isVisible) {
         mIsBottomToolbarVisible = isVisible;
 
-        final int visibility = isVisible ? GONE : VISIBLE;
-        mToggleTabStackButton.setVisibility(visibility);
-        getMenuButtonWrapper().setVisibility(visibility);
+        mToggleTabStackButton.setVisibility(isTabSwitcherOnBottom() ? GONE : VISIBLE);
         updateButtonVisibility();
         mToolbarButtonsContainer.requestLayout();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index b215e4f..4511acd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -272,7 +272,7 @@
                 tab.reloadIgnoringCache();
             }
         }
-        tab.addObserver(createTabObserver());
+        mTabObserverRegistrar.registerActivityTabObserver(createTabObserver());
     }
 
     @Override
@@ -532,7 +532,8 @@
                         mToolbarCoordinator.showToolbarTemporarily();
                     }
                     if (mWebappInfo.isForWebApk()) {
-                        WebApkUma.recordNavigation(isNavigationInScope);
+                        boolean isChildTab = (tab.getParentId() != Tab.INVALID_TAB_ID);
+                        WebApkUma.recordNavigation(isChildTab, isNavigationInScope);
                     }
                 }
             }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java
index c25d54c..cdf951db 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.flags.FeatureUtilities;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
@@ -43,7 +44,6 @@
     @Before
     public void setUp() throws InterruptedException {
         FeatureUtilities.setIsBottomToolbarEnabledForTesting(true);
-        mActivityTestRule.startMainActivityOnBlankPage();
     }
 
     @After
@@ -54,6 +54,7 @@
     @Test
     @MediumTest
     public void testBottomToolbarVisibility() {
+        mActivityTestRule.startMainActivityOnBlankPage();
         Assert.assertNotNull("BottomToolbarCoordinator should be constructed.",
                 mActivityTestRule.getActivity().getToolbarManager().getBottomToolbarCoordinator());
 
@@ -64,12 +65,15 @@
 
     @Test
     @MediumTest
-    public void testBottomToolbarTabSwitcherButton() throws ExecutionException {
+    public void testBottomToolbarTabSwitcherButton_Home_Search_Tab_Switcher()
+            throws ExecutionException {
+        BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_TAB_SWITCHER);
+        mActivityTestRule.startMainActivityOnBlankPage();
         Assert.assertFalse("Tab switcher should not be visible.",
                 mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible());
 
         ViewGroup bottomToolbar = mActivityTestRule.getActivity().findViewById(R.id.bottom_toolbar);
-        View tabSwitcherButton = bottomToolbar.findViewById(R.id.tab_switcher_button);
+        View tabSwitcherButton = bottomToolbar.findViewById(R.id.bottom_tab_switcher_button);
 
         OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
                 mActivityTestRule.getActivity().getOverviewModeBehavior(), true, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java
index 49f18ca..3cef483 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java
@@ -37,6 +37,8 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.flags.FeatureUtilities;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager;
+import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations;
 import org.chromium.chrome.features.start_surface.StartSurfaceLayout;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
@@ -89,8 +91,9 @@
     // clang-format off
     @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID +
             "<Study", "force-fieldtrials=Study/Group", NO_NEW_TAB_VARIATION_PARAMS})
-    public void testTopToolbar_WithGTS_WithBottomToolbar() throws InterruptedException {
+    public void testTopToolbar_WithGTS_WithBottomToolbar_Home_Search_Tab_Switcher() {
         // clang-format on
+        BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_TAB_SWITCHER);
         setupFlagsAndLaunchActivity(true, true);
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         Layout layout = cta.getLayoutManager().getOverviewLayout();
@@ -98,11 +101,66 @@
         enterTabSwitcher(cta);
         verifyTabSwitcherCardCount(cta, 1);
 
+        // Both menu and new tab button should be visible in top tab switcher toolbar.
         checkTopToolbarButtonsExistence(true);
-        checkTopToolbarButtonsVisibility(false);
+        checkTopToolbarButtonsVisibility(true);
 
         rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
 
+        // Both menu and new tab button should be visible in top tab switcher toolbar.
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
+    }
+
+    @Test
+    @MediumTest
+    // clang-format off
+    @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID +
+            "<Study", "force-fieldtrials=Study/Group", NO_NEW_TAB_VARIATION_PARAMS})
+    public void testTopToolbar_WithGTS_WithBottomToolbar_Home_Search_Share() {
+        // clang-format on
+        BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_SHARE);
+        setupFlagsAndLaunchActivity(true, true);
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        Layout layout = cta.getLayoutManager().getOverviewLayout();
+        assertTrue(layout instanceof StartSurfaceLayout);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 1);
+
+        // Both menu and new tab button should be visible in top tab switcher toolbar.
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
+
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
+
+        // Both menu and new tab button should be visible in top tab switcher toolbar.
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
+    }
+
+    @Test
+    @MediumTest
+    // clang-format off
+    @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID +
+            "<Study", "force-fieldtrials=Study/Group", NO_NEW_TAB_VARIATION_PARAMS})
+    public void testTopToolbar_WithGTS_WithBottomToolbar_New_Tab_Search_Share() {
+        // clang-format on
+        BottomToolbarVariationManager.setVariation(Variations.NEW_TAB_SEARCH_SHARE);
+        setupFlagsAndLaunchActivity(true, true);
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        Layout layout = cta.getLayoutManager().getOverviewLayout();
+        assertTrue(layout instanceof StartSurfaceLayout);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 1);
+
+        // Menu button should be visible and new tab button should be invisible
+        // in top tab switcher toolbar.
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(false, true);
+
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
+
+        // Both menu and new tab button should be visible in top tab switcher toolbar.
         checkTopToolbarButtonsExistence(true);
         checkTopToolbarButtonsVisibility(true);
     }
@@ -132,18 +190,59 @@
 
     @Test
     @MediumTest
-    public void testTopToolbar_WithoutGTS_WithBottomToolbar() throws InterruptedException {
+    public void testTopToolbar_WithoutGTS_WithBottomToolbar_Home_Search_Tab_Switcher() {
+        BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_TAB_SWITCHER);
         setupFlagsAndLaunchActivity(true, false);
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         Layout layout = cta.getLayoutManager().getOverviewLayout();
         assertFalse(layout instanceof StartSurfaceLayout);
         enterTabSwitcher(cta);
 
-        checkTopToolbarButtonsExistence(false);
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
 
         rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
 
-        checkTopToolbarButtonsExistence(false);
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
+    }
+
+    @Test
+    @MediumTest
+    public void testTopToolbar_WithoutGTS_WithBottomToolbar_Home_Search_Share() {
+        BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_SHARE);
+        setupFlagsAndLaunchActivity(true, false);
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        Layout layout = cta.getLayoutManager().getOverviewLayout();
+        assertFalse(layout instanceof StartSurfaceLayout);
+        enterTabSwitcher(cta);
+
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
+
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
+
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
+    }
+
+    @Test
+    @MediumTest
+    public void testTopToolbar_WithoutGTS_WithBottomToolbar_New_Tab_Search_Share() {
+        BottomToolbarVariationManager.setVariation(Variations.NEW_TAB_SEARCH_SHARE);
+        setupFlagsAndLaunchActivity(true, false);
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        Layout layout = cta.getLayoutManager().getOverviewLayout();
+        assertFalse(layout instanceof StartSurfaceLayout);
+        enterTabSwitcher(cta);
+
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(false, true);
+
+        rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
+
+        checkTopToolbarButtonsExistence(true);
+        checkTopToolbarButtonsVisibility(true);
     }
 
     private void checkTopToolbarButtonsExistence(boolean isNotNull) {
@@ -161,12 +260,16 @@
     }
 
     private void checkTopToolbarButtonsVisibility(boolean isVisible) {
-        int visibility = isVisible ? View.VISIBLE : View.GONE;
+        checkTopToolbarButtonsVisibility(isVisible, isVisible);
+    }
+
+    private void checkTopToolbarButtonsVisibility(
+            boolean isNewTabButtonVisible, boolean isMenuButtonVisible) {
         onView(withId(R.id.tab_switcher_toolbar)).check((v, noMatchingViewException) -> {
             View newTabButton = v.findViewById(R.id.new_tab_button);
             View menuButton = v.findViewById(R.id.menu_button_wrapper);
-            assertEquals(visibility, newTabButton.getVisibility());
-            assertEquals(visibility, menuButton.getVisibility());
+            assertEquals(isNewTabButtonVisible, newTabButton.getVisibility() == View.VISIBLE);
+            assertEquals(isMenuButtonVisible, menuButton.getVisibility() == View.VISIBLE);
         });
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java
index b2e1231..f38de87 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java
@@ -26,6 +26,7 @@
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
 import org.chromium.chrome.browser.webapps.WebDisplayMode;
 import org.chromium.chrome.test.util.browser.webapps.WebApkInfoBuilder;
@@ -55,6 +56,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         when(mTabProvider.getTab()).thenReturn(mTab);
+        when(mTab.getParentId()).thenReturn(Tab.INVALID_TAB_ID);
         setTabSecurityLevel(ConnectionSecurityLevel.NONE);
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java
index c37585a9..93f3728 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java
@@ -10,38 +10,63 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.BlockJUnit4ClassRunner;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.ParameterizedRobolectricTestRunner;
+import org.robolectric.ParameterizedRobolectricTestRunner.Parameter;
+import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
+import org.robolectric.annotation.Config;
 
+import org.chromium.base.metrics.test.DisableHistogramsRule;
+import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.webapps.WebappExtras;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
 import org.chromium.content_public.browser.NavigationHistory;
 import org.chromium.content_public.browser.WebContents;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Stack;
 
 /**
  * Tests for {@link CloseButtonNavigator}.
  */
-@RunWith(BlockJUnit4ClassRunner.class)
+@RunWith(ParameterizedRobolectricTestRunner.class)
+@Config(sdk = 21, manifest = Config.NONE)
 public class CloseButtonNavigatorTest {
+    @Rule
+    public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
+
+    @Parameters
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {{true}, {false}});
+    }
+
+    @Parameter(0)
+    public boolean mIsWebapp;
+
     @Mock public CustomTabActivityTabController mTabController;
     @Mock public CustomTabActivityTabProvider mTabProvider;
+    @Mock
+    public WebappExtras mWebappExtras;
+    @Mock
+    public BrowserServicesIntentDataProvider mIntentDataProvider;
 
-    // private final List<Tab> mTabs = new ArrayList<>();
     private final Stack<Tab> mTabs = new Stack<>();
     private CloseButtonNavigator mCloseButtonNavigator;
 
@@ -49,7 +74,13 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        mCloseButtonNavigator = new CloseButtonNavigator(mTabController, mTabProvider);
+        if (!mIsWebapp) {
+            mWebappExtras = null;
+        }
+        doReturn(mWebappExtras).when(mIntentDataProvider).getWebappExtras();
+
+        mCloseButtonNavigator =
+                new CloseButtonNavigator(mTabController, mTabProvider, mIntentDataProvider);
 
         // Set up our mTabs to act as the mock tab model:
         // - mTabController.closeTab removes the top tab.
@@ -83,10 +114,15 @@
         when(tab.getWebContents()).thenReturn(webContents);
         when(webContents.getNavigationController()).thenReturn(navigationController);
         when(navigationController.getNavigationHistory()).thenReturn(history);
+        setParentTabId(tab, Tab.INVALID_TAB_ID);
 
         return tab;
     }
 
+    private void setParentTabId(Tab childTab, int parentTabId) {
+        when(childTab.getParentId()).thenReturn(parentTabId);
+    }
+
     private NavigationController currentTabsNavigationController() {
         // The navigation controller will be a mock object created in the above method.
         return mTabs.peek().getWebContents().getNavigationController();
@@ -113,10 +149,16 @@
     public void noCriteria_multipleTabs() {
         mTabs.push(createTabWithNavigationHistory( "www.blue.com/page1"));
         mTabs.push(createTabWithNavigationHistory( "www.blue.com/page2"));
+        setParentTabId(mTabs.get(1), mTabs.get(0).getId());
 
         mCloseButtonNavigator.navigateOnClose();
 
-        assertTrue(mTabs.empty());
+        if (mIsWebapp) {
+            assertEquals(1, mTabs.size());
+            verify(currentTabsNavigationController(), never()).goToNavigationIndex(anyInt());
+        } else {
+            assertTrue(mTabs.empty());
+        }
     }
 
     @Test
@@ -137,10 +179,16 @@
         mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed);
         mTabs.push(createTabWithNavigationHistory( "www.blue.com/page1"));
         mTabs.push(createTabWithNavigationHistory( "www.blue.com/page2"));
+        setParentTabId(mTabs.get(1), mTabs.get(0).getId());
 
         mCloseButtonNavigator.navigateOnClose();
 
-        assertTrue(mTabs.empty());
+        if (mIsWebapp) {
+            assertEquals(1, mTabs.size());
+            verify(currentTabsNavigationController(), never()).goToNavigationIndex(anyInt());
+        } else {
+            assertTrue(mTabs.empty());
+        }
     }
 
     @Test
@@ -172,6 +220,7 @@
                 "www.blue.com/page1",
                 "www.blue.com/page2"
         ));
+        setParentTabId(mTabs.get(1), mTabs.get(0).getId());
 
         mCloseButtonNavigator.navigateOnClose();
 
@@ -190,12 +239,17 @@
                 "www.blue.com/page2",
                 "www.blue.com/page3"
         ));
+        setParentTabId(mTabs.get(1), mTabs.get(0).getId());
 
         mCloseButtonNavigator.navigateOnClose();
 
         assertEquals(1, mTabs.size());
-        verify(currentTabsNavigationController()).goToNavigationIndex(eq(0));
-        verify(currentTabsNavigationController()).goToNavigationIndex(anyInt());
+        if (mIsWebapp) {
+            verify(currentTabsNavigationController(), never()).goToNavigationIndex(anyInt());
+        } else {
+            verify(currentTabsNavigationController()).goToNavigationIndex(eq(0));
+            verify(currentTabsNavigationController()).goToNavigationIndex(anyInt());
+        }
     }
 
     @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java
index e11cb726..234c61d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java
@@ -35,6 +35,8 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeVersionInfo;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.search_engines.TemplateUrl;
@@ -92,17 +94,16 @@
     @Test
     @SmallTest
     public void receiveSearchEngineChoiceRequest() {
-        assertFalse(ContextUtils.getAppSharedPreferences().contains(
-                SearchEngineChoiceNotification.PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP));
+        SharedPreferencesManager prefs = SharedPreferencesManager.getInstance();
+        assertFalse(prefs.contains(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP));
         SearchEngineChoiceNotification.receiveSearchEngineChoiceRequest();
-        assertTrue(ContextUtils.getAppSharedPreferences().contains(
-                SearchEngineChoiceNotification.PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP));
+        assertTrue(prefs.contains(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP));
 
-        long firstTimestamp = ContextUtils.getAppSharedPreferences().getLong(
-                SearchEngineChoiceNotification.PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP, 0);
+        long firstTimestamp =
+                prefs.readLong(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP);
         SearchEngineChoiceNotification.receiveSearchEngineChoiceRequest();
-        long secondTimestamp = ContextUtils.getAppSharedPreferences().getLong(
-                SearchEngineChoiceNotification.PREF_SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP, 0);
+        long secondTimestamp =
+                prefs.readLong(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP);
 
         assertEquals(firstTimestamp, secondTimestamp);
     }
@@ -110,15 +111,13 @@
     @Test
     @SmallTest
     public void handleSearchEngineChoice_ignoredWhenNotRequested() {
-        assertFalse(ContextUtils.getAppSharedPreferences().contains(
-                SearchEngineChoiceNotification.PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION));
+        SharedPreferencesManager prefs = SharedPreferencesManager.getInstance();
+        assertFalse(prefs.contains(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION));
 
         SearchEngineChoiceNotification.handleSearchEngineChoice(mContext, null);
 
         assertFalse("When not requested, the call should have been ignored.",
-                ContextUtils.getAppSharedPreferences().contains(
-                        SearchEngineChoiceNotification
-                                .PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION));
+                prefs.contains(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION));
 
         assertEquals(0,
                 ShadowRecordHistogram.getHistogramValueCountForTesting(
@@ -140,16 +139,14 @@
                         "Android.SearchEngineChoice.Events",
                         SearchEngineChoiceMetrics.Events.SNACKBAR_SHOWN));
 
+        SharedPreferencesManager prefs = SharedPreferencesManager.getInstance();
         assertTrue("Version of the app should be persisted upon prompting.",
-                ContextUtils.getAppSharedPreferences().contains(
-                        SearchEngineChoiceNotification
-                                .PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION));
+                prefs.contains(ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION));
 
         assertEquals("Presented version should be set to the current product version.",
                 ChromeVersionInfo.getProductVersion(),
-                ContextUtils.getAppSharedPreferences().getString(
-                        SearchEngineChoiceNotification.PREF_SEARCH_ENGINE_CHOICE_PRESENTED_VERSION,
-                        null));
+                prefs.readString(
+                        ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_PRESENTED_VERSION, null));
     }
 
     @Test
@@ -161,8 +158,8 @@
 
         SearchEngineChoiceNotification.handleSearchEngineChoice(mContext, mSnackbarManager);
         assertFalse("Second call removes the preference for search engine choice before.",
-                ContextUtils.getAppSharedPreferences().contains(
-                        SearchEngineChoiceMetrics.PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
+                SharedPreferencesManager.getInstance().contains(
+                        ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
 
         SearchEngineChoiceNotification.handleSearchEngineChoice(mContext, mSnackbarManager);
 
@@ -202,8 +199,8 @@
 
         assertFalse(
                 "First handleSearchEngineChoice call after prompt removes SE choice before pref.",
-                ContextUtils.getAppSharedPreferences().contains(
-                        SearchEngineChoiceMetrics.PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
+                SharedPreferencesManager.getInstance().contains(
+                        ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
 
         assertEquals(0,
                 ShadowRecordHistogram.getHistogramValueCountForTesting(
@@ -227,8 +224,8 @@
         SearchEngineChoiceNotification.handleSearchEngineChoice(mContext, mSnackbarManager);
         assertFalse(
                 "First handleSearchEngineChoice call after prompt removes SE choice before pref.",
-                ContextUtils.getAppSharedPreferences().contains(
-                        SearchEngineChoiceMetrics.PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
+                SharedPreferencesManager.getInstance().contains(
+                        ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
 
         doReturn(mAlternativeSearchEngine)
                 .when(mTemplateUrlService)
@@ -270,8 +267,8 @@
 
         assertFalse(
                 "First handleSearchEngineChoice call after prompt removes SE choice before pref.",
-                ContextUtils.getAppSharedPreferences().contains(
-                        SearchEngineChoiceMetrics.PREF_SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
+                SharedPreferencesManager.getInstance().contains(
+                        ChromePreferenceKeys.SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE));
 
         SearchEngineChoiceNotification.handleSearchEngineChoice(mContext, mSnackbarManager);
 
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index cbe0a11..6991e7c 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -10486,6 +10486,35 @@
       The limit on "<ph name="APP_NAME">$1<ex>Google Photos</ex></ph>" that your parent set ran out. You can use it for <ph name="TIME_LIMIT">$2<ex>2 hours and 30 minutes</ex></ph> tomorrow.
     </message>
 
+    <!-- Extension request -->
+    <if expr="not is_android">
+      <message name="IDS_ENTERPRISE_EXTENSION_REQUEST_APPROVED_TITLE" desc="The notification title when there are some extension requests approved.">
+        {NUM_EXTENSIONS, plural,
+          =1 {An extension has been approved}
+          other {# extensions have been approved}}
+      </message>
+      <message name="IDS_ENTERPRISE_EXTENSION_REQUEST_REJECTED_TITLE" desc="The notification title when there are some extension requests rejected.">
+        {NUM_EXTENSIONS, plural,
+          =1 {An extension has been rejected}
+          other {# extensions have been rejected}}
+      </message>
+      <message name="IDS_ENTERPRISE_EXTENSION_REQUEST_FORCE_INSTALLED_TITLE" desc="The notification title when there are some extension requests force installed.">
+        {NUM_EXTENSIONS, plural,
+          =1 {An extension has been installed by your administrator}
+          other {# extensions have been installed by your administrator}}
+      </message>
+
+      <message name="IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_INSTALL" desc="The notification message that tell user how to install the approved extension.">
+        {NUM_EXTENSIONS, plural,
+          =1 {Click to install the extension}
+          other {Click to install these extensions}}
+      </message>
+      <message name="IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_VIEW" desc="The notification message that show user the reviewed installed extension requests.">
+        {NUM_EXTENSIONS, plural,
+          =1 {Click to view the extension}
+          other {Click to view these extensions}}
+      </message>
+    </if>
   </messages>
 </release>
 </grit>
diff --git a/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_APPROVED_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_APPROVED_TITLE.png.sha1
new file mode 100644
index 0000000..24482fe3
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_APPROVED_TITLE.png.sha1
@@ -0,0 +1 @@
+56753fdeb3266b58301fb3c9aed33fff5a53e503
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_INSTALL.png.sha1 b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_INSTALL.png.sha1
new file mode 100644
index 0000000..24482fe3
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_INSTALL.png.sha1
@@ -0,0 +1 @@
+56753fdeb3266b58301fb3c9aed33fff5a53e503
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_VIEW.png.sha1 b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_VIEW.png.sha1
new file mode 100644
index 0000000..cc5b7602
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_VIEW.png.sha1
@@ -0,0 +1 @@
+11d8350374f809e9fdcd389bd6d93b565b83ef98
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_FORCE_INSTALLED_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_FORCE_INSTALLED_TITLE.png.sha1
new file mode 100644
index 0000000..5e589d0f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_FORCE_INSTALLED_TITLE.png.sha1
@@ -0,0 +1 @@
+5f7ecf4d397c645aac55c4bd2acf0583943aef26
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_REJECTED_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_REJECTED_TITLE.png.sha1
new file mode 100644
index 0000000..cc5b7602
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_ENTERPRISE_EXTENSION_REQUEST_REJECTED_TITLE.png.sha1
@@ -0,0 +1 @@
+11d8350374f809e9fdcd389bd6d93b565b83ef98
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 553c2b2..9df82e6 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -72,9 +72,7 @@
 
 # This proto library is used for non-android NTPs below.
 proto_library("ntp_background_proto") {
-  sources = [
-    "search/background/ntp_background.proto",
-  ]
+  sources = [ "search/background/ntp_background.proto" ]
   generate_python = false
 }
 
@@ -3075,6 +3073,8 @@
       "chrome_browser_field_trials_desktop.h",
       "chrome_process_singleton.cc",
       "chrome_process_singleton.h",
+      "component_updater/intervention_policy_database_component_installer.cc",
+      "component_updater/intervention_policy_database_component_installer.h",
       "component_updater/tls_deprecation_config_component_installer.cc",
       "component_updater/tls_deprecation_config_component_installer.h",
       "custom_handlers/register_protocol_handler_permission_request.cc",
@@ -3117,6 +3117,8 @@
       "enterprise_reporting/browser_report_generator.h",
       "enterprise_reporting/extension_info.cc",
       "enterprise_reporting/extension_info.h",
+      "enterprise_reporting/notification/extension_request_notification.cc",
+      "enterprise_reporting/notification/extension_request_notification.h",
       "enterprise_reporting/policy_info.cc",
       "enterprise_reporting/policy_info.h",
       "enterprise_reporting/prefs.cc",
@@ -3385,6 +3387,8 @@
       "resource_coordinator/decision_details.h",
       "resource_coordinator/discard_metrics_lifecycle_unit_observer.cc",
       "resource_coordinator/discard_metrics_lifecycle_unit_observer.h",
+      "resource_coordinator/intervention_policy_database.cc",
+      "resource_coordinator/intervention_policy_database.h",
       "resource_coordinator/leveldb_site_characteristics_database.cc",
       "resource_coordinator/leveldb_site_characteristics_database.h",
       "resource_coordinator/lifecycle_unit.cc",
@@ -3680,6 +3684,7 @@
       "//chrome/app/vector_icons",
       "//chrome/browser/policy:path_parser",
       "//chrome/browser/profile_resetter:profile_reset_report_proto",
+      "//chrome/browser/resource_coordinator:intervention_policy_database_proto",
       "//chrome/browser/resource_coordinator:tab_metrics_event_proto",
       "//chrome/browser/resource_coordinator/tab_ranker",
       "//chrome/browser/resources:component_extension_resources",
@@ -5329,27 +5334,19 @@
 
 if (is_android) {
   proto_library("client_discourse_context_proto") {
-    sources = [
-      "android/proto/client_discourse_context.proto",
-    ]
+    sources = [ "android/proto/client_discourse_context.proto" ]
   }
 
   proto_library("delta_file_proto") {
-    sources = [
-      "android/proto/delta_file.proto",
-    ]
+    sources = [ "android/proto/delta_file.proto" ]
   }
 
   proto_library("explore_sites_proto") {
-    sources = [
-      "android/explore_sites/catalog.proto",
-    ]
+    sources = [ "android/explore_sites/catalog.proto" ]
   }
 
   proto_library("usage_stats_proto") {
-    sources = [
-      "android/usage_stats/website_event.proto",
-    ]
+    sources = [ "android/usage_stats/website_event.proto" ]
   }
 }
 
@@ -5385,27 +5382,19 @@
 }
 
 source_set("theme_properties") {
-  sources = [
-    "themes/theme_properties.h",
-  ]
+  sources = [ "themes/theme_properties.h" ]
 }
 
 proto_library("availability_protos") {
-  sources = [
-    "availability/proto/availability_prober_cache_entry.proto",
-  ]
+  sources = [ "availability/proto/availability_prober_cache_entry.proto" ]
 }
 
 proto_library("resource_prefetch_predictor_proto") {
-  sources = [
-    "predictors/resource_prefetch_predictor.proto",
-  ]
+  sources = [ "predictors/resource_prefetch_predictor.proto" ]
 }
 
 proto_library("permissions_proto") {
-  sources = [
-    "permissions/crowd_deny.proto",
-  ]
+  sources = [ "permissions/crowd_deny.proto" ]
 }
 
 grit("resources") {
@@ -5450,24 +5439,16 @@
   if (enable_plugins) {
     # .json is not in the default sources_assignment_filter.
     if (is_chromeos) {
-      inputs = [
-        "resources/plugin_metadata/plugins_chromeos.json",
-      ]
+      inputs = [ "resources/plugin_metadata/plugins_chromeos.json" ]
     }
     if (is_linux && !is_chromeos) {
-      inputs = [
-        "resources/plugin_metadata/plugins_linux.json",
-      ]
+      inputs = [ "resources/plugin_metadata/plugins_linux.json" ]
     }
     if (is_mac) {
-      inputs = [
-        "resources/plugin_metadata/plugins_mac.json",
-      ]
+      inputs = [ "resources/plugin_metadata/plugins_mac.json" ]
     }
     if (is_win) {
-      inputs = [
-        "resources/plugin_metadata/plugins_win.json",
-      ]
+      inputs = [ "resources/plugin_metadata/plugins_win.json" ]
     }
   }
 
@@ -5523,12 +5504,8 @@
 if (is_chrome_branded) {
   action("chrome_internal_resources_gen") {
     script = "internal/transform_additional_modules_list.py"
-    sources = [
-      "internal/resources/additional_modules_list.input",
-    ]
-    outputs = [
-      additional_modules_list_file,
-    ]
+    sources = [ "internal/resources/additional_modules_list.input" ]
+    outputs = [ additional_modules_list_file ]
     args = rebase_path(sources, root_build_dir) +
            rebase_path(outputs, root_build_dir)
   }
@@ -5572,26 +5549,16 @@
 
 action("expired_flags_list_gen") {
   script = "//tools/flags/generate_expired_list.py"
-  sources = [
-    "flag-metadata.json",
-  ]
-  inputs = [
-    "//chrome/VERSION",
-  ]
-  outputs = [
-    "$root_gen_dir/chrome/browser/expired_flags_list.cc",
-  ]
+  sources = [ "flag-metadata.json" ]
+  inputs = [ "//chrome/VERSION" ]
+  outputs = [ "$root_gen_dir/chrome/browser/expired_flags_list.cc" ]
   args = rebase_path(sources, root_build_dir) +
          rebase_path(outputs, root_build_dir)
 }
 
 source_set("expired_flags_list") {
-  deps = [
-    ":expired_flags_list_gen",
-  ]
-  sources = [
-    "$root_gen_dir/chrome/browser/expired_flags_list.cc",
-  ]
+  deps = [ ":expired_flags_list_gen" ]
+  sources = [ "$root_gen_dir/chrome/browser/expired_flags_list.cc" ]
 }
 
 # Use a static library here because many test binaries depend on this but don't
@@ -5954,21 +5921,15 @@
       "//components/translate/content/common",
     ]
 
-    public_deps = [
-      "//net:test_support",
-    ]
+    public_deps = [ "//net:test_support" ]
   }
 }
 
 if (is_android) {
   java_cpp_enum("sharing_send_message_result_generated_enum") {
-    sources = [
-      "sharing/sharing_send_message_result.h",
-    ]
+    sources = [ "sharing/sharing_send_message_result.h" ]
   }
   java_cpp_enum("sharing_dialog_type_generated_enum") {
-    sources = [
-      "sharing/sharing_metrics.h",
-    ]
+    sources = [ "sharing/sharing_metrics.h" ]
   }
 }
diff --git a/chrome/browser/OWNERS b/chrome/browser/OWNERS
index 8eb63f5b..365eb267 100644
--- a/chrome/browser/OWNERS
+++ b/chrome/browser/OWNERS
@@ -69,10 +69,10 @@
 per-file web_bluetooth*=file://content/browser/bluetooth/OWNERS
 
 # For security review.
-per-file chrome_browser_interface_binders.cc=set noparent
-per-file chrome_browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
-per-file chrome_content_browser_client_receiver_bindings.cc=set noparent
-per-file chrome_content_browser_client_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
+per-file chrome_browser_interface_binders.*=set noparent
+per-file chrome_browser_interface_binders.*=file://ipc/SECURITY_OWNERS
+per-file chrome_content_browser_client_receiver_bindings.*=set noparent
+per-file chrome_content_browser_client_receiver_bindings.*=file://ipc/SECURITY_OWNERS
 
 # BackForwardCache
 per-file chrome_back_forward_cache_browsertest.cc=arthursonzogni@chromium.org
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b9403ab..efa95d5 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1230,6 +1230,24 @@
 #endif  // OS_ANDROID
 
 #if defined(OS_ANDROID)
+const FeatureEntry::FeatureParam kChromeDuet_HomeSearchTabSwitcher[] = {
+    {"chrome_duet_variation", "HomeSearchTabSwitcher"}};
+
+const FeatureEntry::FeatureParam kChromeDuet_HomeSearchShare[] = {
+    {"chrome_duet_variation", "HomeSearchShare"}};
+
+const FeatureEntry::FeatureParam kChromeDuet_NewTabSearchShare[] = {
+    {"chrome_duet_variation", "NewTabSearchShare"}};
+
+const FeatureEntry::FeatureVariation kChromeDuetVariations[] = {
+    {"Home-Search-TabSwitcher Variation", kChromeDuet_HomeSearchTabSwitcher,
+     base::size(kChromeDuet_HomeSearchTabSwitcher), nullptr},
+    {"Home-Search-Share Variation", kChromeDuet_HomeSearchShare,
+     base::size(kChromeDuet_HomeSearchShare), nullptr},
+    {"NewTab-Search-Share Variation", kChromeDuet_NewTabSearchShare,
+     base::size(kChromeDuet_NewTabSearchShare), nullptr},
+};
+
 const FeatureEntry::FeatureParam kTabGridLayoutAndroid_NewTabVariation[] = {
     {"tab_grid_layout_android_new_tab", "NewTabVariation"}};
 
@@ -2064,7 +2082,9 @@
 #if defined(OS_ANDROID)
     {"enable-chrome-duet", flag_descriptions::kChromeDuetName,
      flag_descriptions::kChromeDuetDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(chrome::android::kChromeDuetFeature)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kChromeDuetFeature,
+                                    kChromeDuetVariations,
+                                    "ChromeDuet")},
     {"enable-chrome-duet-labels", flag_descriptions::kChromeDuetLabelsName,
      flag_descriptions::kChromeDuetLabelsDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kChromeDuetLabeled)},
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
index 108e576..b9ea8a4 100644
--- a/chrome/browser/android/favicon_helper.cc
+++ b/chrome/browser/android/favicon_helper.cc
@@ -47,29 +47,6 @@
 
 namespace {
 
-void OnFaviconBitmapResultAvailable(
-    const JavaRef<jobject>& j_favicon_image_callback,
-    const favicon_base::FaviconRawBitmapResult& result) {
-  JNIEnv* env = AttachCurrentThread();
-
-  // Convert favicon_image_result to java objects.
-  ScopedJavaLocalRef<jstring> j_icon_url =
-      ConvertUTF8ToJavaString(env, result.icon_url.spec());
-  ScopedJavaLocalRef<jobject> j_favicon_bitmap;
-  if (result.is_valid()) {
-    SkBitmap favicon_bitmap;
-    gfx::PNGCodec::Decode(result.bitmap_data->front(),
-                          result.bitmap_data->size(),
-                          &favicon_bitmap);
-    if (!favicon_bitmap.isNull())
-      j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap);
-  }
-
-  // Call java side OnFaviconBitmapResultAvailable method.
-  Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback,
-                                               j_favicon_bitmap, j_icon_url);
-}
-
 void OnEnsureIconIsAvailableFinished(
     const ScopedJavaGlobalRef<jobject>& j_availability_callback,
     bool newly_available) {
@@ -111,7 +88,8 @@
     return false;
 
   favicon_base::FaviconRawBitmapCallback callback_runner =
-      base::BindOnce(&OnFaviconBitmapResultAvailable,
+      base::BindOnce(&FaviconHelper::OnFaviconBitmapResultAvailable,
+                     weak_ptr_factory_.GetWeakPtr(),
                      ScopedJavaGlobalRef<jobject>(j_favicon_image_callback));
 
   // |j_page_url| is an origin, and it may not have had a favicon associated
@@ -157,13 +135,13 @@
     return false;
   history_ui_favicon_request_handler->GetRawFaviconForPageURL(
       page_url, static_cast<int>(j_desired_size_in_pixel),
-      base::BindOnce(&OnFaviconBitmapResultAvailable,
+      base::BindOnce(&FaviconHelper::OnFaviconBitmapResultAvailable,
+                     weak_ptr_factory_.GetWeakPtr(),
                      ScopedJavaGlobalRef<jobject>(j_favicon_image_callback)),
       favicon::FaviconRequestPlatform::kMobile,
       favicon::HistoryUiFaviconRequestOrigin::kRecentTabs,
       /*icon_url_for_uma=*/
-      open_tabs ? open_tabs->GetIconUrlForPageUrl(page_url) : GURL(),
-      cancelable_task_tracker_.get());
+      open_tabs ? open_tabs->GetIconUrlForPageUrl(page_url) : GURL());
   return true;
 }
 
@@ -238,6 +216,7 @@
   return ret;
 }
 
+// static
 void FaviconHelper::OnFaviconDownloaded(
     const ScopedJavaGlobalRef<jobject>& j_availability_callback,
     Profile* profile,
@@ -266,6 +245,7 @@
       base::Bind(&OnEnsureIconIsAvailableFinished, j_availability_callback));
 }
 
+// static
 void FaviconHelper::OnFaviconImageResultAvailable(
     const ScopedJavaGlobalRef<jobject>& j_availability_callback,
     Profile* profile,
@@ -289,3 +269,25 @@
       base::BindOnce(&FaviconHelper::OnFaviconDownloaded,
                      j_availability_callback, profile, page_url, icon_type));
 }
+
+void FaviconHelper::OnFaviconBitmapResultAvailable(
+    const JavaRef<jobject>& j_favicon_image_callback,
+    const favicon_base::FaviconRawBitmapResult& result) {
+  JNIEnv* env = AttachCurrentThread();
+
+  // Convert favicon_image_result to java objects.
+  ScopedJavaLocalRef<jstring> j_icon_url =
+      ConvertUTF8ToJavaString(env, result.icon_url.spec());
+  ScopedJavaLocalRef<jobject> j_favicon_bitmap;
+  if (result.is_valid()) {
+    SkBitmap favicon_bitmap;
+    gfx::PNGCodec::Decode(result.bitmap_data->front(),
+                          result.bitmap_data->size(), &favicon_bitmap);
+    if (!favicon_bitmap.isNull())
+      j_favicon_bitmap = gfx::ConvertToJavaBitmap(&favicon_bitmap);
+  }
+
+  // Call java side OnFaviconBitmapResultAvailable method.
+  Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback,
+                                               j_favicon_bitmap, j_icon_url);
+}
diff --git a/chrome/browser/android/favicon_helper.h b/chrome/browser/android/favicon_helper.h
index 2b72f76..bb4bf4dc 100644
--- a/chrome/browser/android/favicon_helper.h
+++ b/chrome/browser/android/favicon_helper.h
@@ -12,6 +12,7 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "components/favicon_base/favicon_types.h"
 #include "url/gurl.h"
@@ -55,6 +56,8 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(FaviconHelperTest, GetLargestSizeIndex);
 
+  virtual ~FaviconHelper();
+
   static void OnFaviconImageResultAvailable(
       const base::android::ScopedJavaGlobalRef<jobject>&
           j_availability_callback,
@@ -79,9 +82,16 @@
 
   static size_t GetLargestSizeIndex(const std::vector<gfx::Size>& sizes);
 
+  // This function is expected to be bound to a WeakPtr<FaviconHelper>, so that
+  // it won't be run if the FaviconHelper is deleted and
+  // |j_favicon_image_callback| isn't executed in that case.
+  void OnFaviconBitmapResultAvailable(
+      const base::android::JavaRef<jobject>& j_favicon_image_callback,
+      const favicon_base::FaviconRawBitmapResult& result);
+
   std::unique_ptr<base::CancelableTaskTracker> cancelable_task_tracker_;
 
-  virtual ~FaviconHelper();
+  base::WeakPtrFactory<FaviconHelper> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(FaviconHelper);
 };
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index c176e05c..38dd1b3d 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -341,6 +341,7 @@
 #endif
 
 #if !defined(OS_ANDROID)
+#include "chrome/browser/component_updater/intervention_policy_database_component_installer.h"
 #include "chrome/browser/component_updater/tls_deprecation_config_component_installer.h"
 #include "chrome/browser/resource_coordinator/tab_manager.h"
 #endif
@@ -548,6 +549,8 @@
 #endif  // defined(OS_WIN)
 
 #if !defined(OS_ANDROID)
+  RegisterInterventionPolicyDatabaseComponent(
+      cus, g_browser_process->GetTabManager()->intervention_policy_database());
   RegisterTLSDeprecationConfigComponent(cus, path);
 #endif
 
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 46c5bc0..b471059 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -811,6 +811,8 @@
     "child_accounts/time_limit_override.h",
     "child_accounts/time_limits/app_activity_registry.cc",
     "child_accounts/time_limits/app_activity_registry.h",
+    "child_accounts/time_limits/app_activity_report_interface.cc",
+    "child_accounts/time_limits/app_activity_report_interface.h",
     "child_accounts/time_limits/app_service_wrapper.cc",
     "child_accounts/time_limits/app_service_wrapper.h",
     "child_accounts/time_limits/app_time_controller.cc",
@@ -2691,6 +2693,7 @@
     "child_accounts/time_limits/app_activity_registry_unittest.cc",
     "child_accounts/time_limits/app_service_wrapper_unittest.cc",
     "child_accounts/time_limits/app_time_controller_unittest.cc",
+    "child_accounts/time_limits/app_types_unittest.cc",
     "child_accounts/usage_time_limit_processor_unittest.cc",
     "child_accounts/usage_time_state_notifier_unittest.cc",
     "chrome_content_browser_client_chromeos_part_unittest.cc",
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service.cc b/chrome/browser/chromeos/child_accounts/child_user_service.cc
index 1bf13cec..b199b12 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service.cc
+++ b/chrome/browser/chromeos/child_accounts/child_user_service.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/child_accounts/child_user_service.h"
 
 #include "base/time/time.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer.h"
 #include "chrome/browser/profiles/profile.h"
@@ -60,6 +61,21 @@
   web_time_enforcer->OnWebTimeLimitEnded();
 }
 
+app_time::AppActivityReportInterface::ReportParams
+ChildUserService::GenerateAppActivityReport(
+    enterprise_management::ChildStatusReportRequest* report) const {
+  DCHECK(app_time_controller_);
+  return app_time_controller_->app_registry()->GenerateAppActivityReport(
+      report);
+}
+
+void ChildUserService::AppActivityReportSubmitted(
+    base::Time report_generation_timestamp) {
+  DCHECK(app_time_controller_);
+  app_time_controller_->app_registry()->CleanRegistry(
+      report_generation_timestamp);
+}
+
 bool ChildUserService::WebTimeLimitReached() const {
   if (!app_time_controller_)
     return false;
diff --git a/chrome/browser/chromeos/child_accounts/child_user_service.h b/chrome/browser/chromeos/child_accounts/child_user_service.h
index c72aa67..7a953d9 100644
--- a/chrome/browser/chromeos/child_accounts/child_user_service.h
+++ b/chrome/browser/chromeos/child_accounts/child_user_service.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_interface.h"
 #include "components/keyed_service/core/keyed_service.h"
 
@@ -19,6 +20,10 @@
 class BrowserContext;
 }  // namespace content
 
+namespace enterprise_management {
+class ChildStatusReportRequest;
+}  // namespace enterprise_management
+
 class GURL;
 
 namespace chromeos {
@@ -31,7 +36,8 @@
 // TODO(crbug.com/1022231): Migrate ConsumerStatusReportingService,
 // EventBasedStatusReporting and ScreenTimeController to ChildUserService.
 class ChildUserService : public KeyedService,
-                         public app_time::WebTimeLimitInterface {
+                         public app_time::WebTimeLimitInterface,
+                         public app_time::AppActivityReportInterface {
  public:
   // Used for tests to get internal implementation details.
   class TestApi {
@@ -51,10 +57,16 @@
   ChildUserService& operator=(const ChildUserService&) = delete;
   ~ChildUserService() override;
 
-  // WebTimeLimitInterface:
+  // app_time::WebTimeLimitInterface:
   void PauseWebActivity(const std::string& app_id) override;
   void ResumeWebActivity(const std::string& app_id) override;
 
+  // app_time::AppActivityReportInterface:
+  app_time::AppActivityReportInterface::ReportParams GenerateAppActivityReport(
+      enterprise_management::ChildStatusReportRequest* report) const override;
+  void AppActivityReportSubmitted(
+      base::Time report_generation_timestamp) override;
+
   // Returns whether web time limit was reached for child user.
   // Always returns false if per-app times limits feature is disabled.
   bool WebTimeLimitReached() const;
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
index f22acb5..7d25ebd 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
@@ -5,10 +5,50 @@
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h"
 
 #include "base/stl_util.h"
+#include "components/policy/proto/device_management_backend.pb.h"
 
 namespace chromeos {
 namespace app_time {
 
+namespace {
+enterprise_management::App::AppType AppTypeForReporting(
+    apps::mojom::AppType type) {
+  switch (type) {
+    case apps::mojom::AppType::kArc:
+      return enterprise_management::App::ARC;
+    case apps::mojom::AppType::kBuiltIn:
+      return enterprise_management::App::BUILT_IN;
+    case apps::mojom::AppType::kCrostini:
+      return enterprise_management::App::CROSTINI;
+    case apps::mojom::AppType::kExtension:
+      return enterprise_management::App::EXTENSION;
+    case apps::mojom::AppType::kWeb:
+      return enterprise_management::App::WEB;
+    default:
+      return enterprise_management::App::UNKNOWN;
+  }
+}
+
+enterprise_management::AppActivity::AppState AppStateForReporting(
+    AppState state) {
+  switch (state) {
+    case AppState::kAvailable:
+      return enterprise_management::AppActivity::DEFAULT;
+    case AppState::kAlwaysAvailable:
+      return enterprise_management::AppActivity::ALWAYS_AVAILABLE;
+    case AppState::kBlocked:
+      return enterprise_management::AppActivity::BLOCKED;
+    case AppState::kLimitReached:
+      return enterprise_management::AppActivity::LIMIT_REACHED;
+    case AppState::kUninstalled:
+      return enterprise_management::AppActivity::UNINSTALLED;
+    default:
+      return enterprise_management::AppActivity::UNKNOWN;
+  }
+}
+
+}  // namespace
+
 AppActivityRegistry::AppDetails::AppDetails() = default;
 
 AppActivityRegistry::AppDetails::AppDetails(const AppActivity& activity)
@@ -130,6 +170,65 @@
   return activity_registry_.at(app_id).activity.RunningActiveTime();
 }
 
+AppActivityReportInterface::ReportParams
+AppActivityRegistry::GenerateAppActivityReport(
+    enterprise_management::ChildStatusReportRequest* report) const {
+  // TODO(agawronska): We should also report the ongoing activity if it started
+  // before the reporting, because it could have been going for a long time.
+  const base::Time timestamp = base::Time::Now();
+  bool anything_reported = false;
+
+  for (const auto& entry : activity_registry_) {
+    const AppId& app_id = entry.first;
+    const AppActivity& registered_activity = entry.second.activity;
+
+    // Do not report if there is no activity.
+    if (registered_activity.active_times().empty())
+      continue;
+
+    enterprise_management::AppActivity* app_activity =
+        report->add_app_activity();
+    enterprise_management::App* app_info = app_activity->mutable_app_info();
+    app_info->set_app_id(app_id.app_id());
+    app_info->set_app_type(AppTypeForReporting(app_id.app_type()));
+    // AppService is is only different for ARC++ apps.
+    if (app_id.app_type() == apps::mojom::AppType::kArc) {
+      app_info->add_additional_app_id(
+          app_service_wrapper_->GetAppServiceId(app_id));
+    }
+    app_activity->set_app_state(
+        AppStateForReporting(registered_activity.app_state()));
+    app_activity->set_populated_at(timestamp.ToJavaTime());
+
+    for (const auto& active_time : registered_activity.active_times()) {
+      enterprise_management::TimePeriod* time_period =
+          app_activity->add_active_time_periods();
+      time_period->set_start_timestamp(active_time.active_from().ToJavaTime());
+      time_period->set_end_timestamp(active_time.active_to().ToJavaTime());
+    }
+    anything_reported = true;
+  }
+
+  return AppActivityReportInterface::ReportParams{timestamp, anything_reported};
+}
+
+void AppActivityRegistry::CleanRegistry(base::Time timestamp) {
+  for (auto it = activity_registry_.begin(); it != activity_registry_.end();) {
+    const AppId& app_id = it->first;
+    AppActivity& registered_activity = it->second.activity;
+    // TODO(agawronska): Update data stored in user pref.
+    registered_activity.RemoveActiveTimeEarlierThan(timestamp);
+    // Remove app that was uninstalled and does not have any past activity
+    // stored.
+    if (GetAppState(app_id) == AppState::kUninstalled &&
+        registered_activity.active_times().empty()) {
+      it = activity_registry_.erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
+
 void AppActivityRegistry::Add(const AppId& app_id) {
   auto result = activity_registry_.emplace(
       app_id, AppDetails(AppActivity(AppState::kAvailable)));
@@ -158,16 +257,5 @@
   activity_registry_.at(app_id).activity.SetAppInactive(timestamp);
 }
 
-void AppActivityRegistry::CleanRegistry() {
-  for (auto it = activity_registry_.cbegin();
-       it != activity_registry_.cend();) {
-    if (GetAppState(it->first) == AppState::kUninstalled) {
-      it = activity_registry_.erase(it);
-    } else {
-      ++it;
-    }
-  }
-}
-
 }  // namespace app_time
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
index 29e05ff..9990d7b 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
@@ -9,6 +9,7 @@
 #include <set>
 
 #include "base/time/time.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h"
 #include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
 
@@ -16,6 +17,10 @@
 class Window;
 }  // namespace aura
 
+namespace enterprise_management {
+class ChildStatusReportRequest;
+}  // namespace enterprise_management
+
 namespace chromeos {
 namespace app_time {
 
@@ -52,6 +57,16 @@
   // reset.
   base::TimeDelta GetActiveTime(const AppId& app_id) const;
 
+  // Populates |report| with collected app activity. Returns whether any data
+  // were reported.
+  AppActivityReportInterface::ReportParams GenerateAppActivityReport(
+      enterprise_management::ChildStatusReportRequest* report) const;
+
+  // Removes data older than |timestamp| from the registry.
+  // Removes entries for uninstalled apps if there is no more relevant activity
+  // data left.
+  void CleanRegistry(base::Time timestamp);
+
  private:
   // Bundles detailed data stored for a specific app.
   struct AppDetails {
@@ -83,10 +98,6 @@
   void SetAppActive(const AppId& app_id, base::Time timestamp);
   void SetAppInactive(const AppId& app_id, base::Time timestamp);
 
-  // Removes uninstalled apps from the registry. Should be called after the
-  // recent data was successfully uploaded to server.
-  void CleanRegistry();
-
   // Owned by AppTimeController.
   AppServiceWrapper* const app_service_wrapper_;
 
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.cc
new file mode 100644
index 0000000..27e1bce
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.cc
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h"
+
+#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
+#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h"
+#include "chrome/browser/profiles/profile.h"
+
+namespace chromeos {
+namespace app_time {
+
+// static
+AppActivityReportInterface* AppActivityReportInterface::Get(Profile* profile) {
+  return static_cast<AppActivityReportInterface*>(
+      ChildUserServiceFactory::GetForBrowserContext(profile));
+}
+
+// static
+bool AppActivityReportInterface::ShouldReportAppActivity() {
+  return AppTimeController::ArePerAppTimeLimitsEnabled() &&
+         AppTimeController::IsAppActivityReportingEnabled();
+}
+
+AppActivityReportInterface::~AppActivityReportInterface() = default;
+
+}  // namespace app_time
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h
new file mode 100644
index 0000000..920aa6490
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h
@@ -0,0 +1,55 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_ACTIVITY_REPORT_INTERFACE_H_
+#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_ACTIVITY_REPORT_INTERFACE_H_
+
+#include "base/time/time.h"
+
+class Profile;
+
+namespace enterprise_management {
+class ChildStatusReportRequest;
+}  // namespace enterprise_management
+
+namespace chromeos {
+namespace app_time {
+
+// Interface of the object generating app activity for child user.
+class AppActivityReportInterface {
+ public:
+  // Parameters of the generated report.
+  struct ReportParams {
+    // Time the report was generated.
+    base::Time generation_time;
+
+    // Whether any data were added to the report.
+    bool anything_reported = false;
+  };
+
+  // Factory method that returns object generating app activity for child user.
+  // feature. Provided to reduce the dependencies between API consumer and child
+  // user related code. AppActivityReportInterface object has a lifetime of a
+  // KeyedService.
+  static AppActivityReportInterface* Get(Profile* profile);
+
+  static bool ShouldReportAppActivity();
+
+  virtual ~AppActivityReportInterface();
+
+  // Populates child status |report| with collected app activity.
+  // Returns whether any data were populated.
+  virtual ReportParams GenerateAppActivityReport(
+      enterprise_management::ChildStatusReportRequest* report) const = 0;
+
+  // Clears the stored app activity older than |report_generation_timestamp|.
+  // Should be called when child status report was successfully submitted.
+  virtual void AppActivityReportSubmitted(
+      base::Time report_generation_timestamp) = 0;
+};
+
+}  // namespace app_time
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_ACTIVITY_REPORT_INTERFACE_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.cc
index 0ab6313..321226f 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.cc
@@ -90,6 +90,10 @@
   return app_name;
 }
 
+std::string AppServiceWrapper::GetAppServiceId(const AppId& app_id) const {
+  return AppServiceIdFromAppId(app_id, profile_);
+}
+
 void AppServiceWrapper::AddObserver(EventListener* listener) {
   DCHECK(listener);
   listeners_.AddObserver(listener);
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h b/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h
index a2045208..6e42148 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h
@@ -84,6 +84,11 @@
   // Might return empty string.
   std::string GetAppName(const AppId& app_id) const;
 
+  // Returns app service id for the app identified by |app_id|.
+  // App service id will be only different from app_id.app_id() for ARC++ apps.
+  // It does not make sense to call it for other apps.
+  std::string GetAppServiceId(const AppId& app_id) const;
+
   void AddObserver(EventListener* observer);
   void RemoveObserver(EventListener* observer);
 
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
index 20c98e9..69731b5 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
@@ -27,6 +27,10 @@
   return base::FeatureList::IsEnabled(features::kPerAppTimeLimits);
 }
 
+bool AppTimeController::IsAppActivityReportingEnabled() {
+  return base::FeatureList::IsEnabled(features::kAppActivityReporting);
+}
+
 // static
 void AppTimeController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterDictionaryPref(prefs::kPerAppTimeLimitsPolicy);
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h
index a440c25b..2090948 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h
@@ -24,6 +24,7 @@
 class AppTimeController {
  public:
   static bool ArePerAppTimeLimitsEnabled();
+  static bool IsAppActivityReportingEnabled();
 
   // Registers preferences
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
@@ -41,6 +42,12 @@
 
   WebTimeLimitEnforcer* web_time_enforcer() { return web_time_enforcer_.get(); }
 
+  const AppActivityRegistry* app_registry() const {
+    return app_registry_.get();
+  }
+
+  AppActivityRegistry* app_registry() { return app_registry_.get(); }
+
  private:
   void RegisterProfilePrefObservers(PrefService* pref_service);
   void TimeLimitsPolicyUpdated(const std::string& pref_name);
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
index 743e38a7..0b2fa45 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types.cc
@@ -92,7 +92,7 @@
 
 AppActivity::ActiveTime::ActiveTime(base::Time start, base::Time end)
     : active_from_(start), active_to_(end) {
-  DCHECK_GT(end, start);
+  DCHECK_GT(active_to_, active_from_);
 }
 
 AppActivity::ActiveTime::ActiveTime(const AppActivity::ActiveTime& rhs) =
@@ -101,6 +101,36 @@
 AppActivity::ActiveTime& AppActivity::ActiveTime::operator=(
     const AppActivity::ActiveTime& rhs) = default;
 
+bool AppActivity::ActiveTime::operator==(const ActiveTime& rhs) const {
+  return active_from_ == rhs.active_from() && active_to_ == rhs.active_to();
+}
+
+bool AppActivity::ActiveTime::operator!=(const ActiveTime& rhs) const {
+  return !(*this == rhs);
+}
+
+bool AppActivity::ActiveTime::Contains(base::Time timestamp) const {
+  return active_from_ < timestamp && active_to_ > timestamp;
+}
+
+bool AppActivity::ActiveTime::IsEarlierThan(base::Time timestamp) const {
+  return active_to_ <= timestamp;
+}
+
+bool AppActivity::ActiveTime::IsLaterThan(base::Time timestamp) const {
+  return active_from_ >= timestamp;
+}
+
+void AppActivity::ActiveTime::set_active_from(base::Time active_from) {
+  DCHECK_GT(active_to_, active_from);
+  active_from_ = active_from;
+}
+
+void AppActivity::ActiveTime::set_active_to(base::Time active_to) {
+  DCHECK_GT(active_to, active_from_);
+  active_to_ = active_to;
+}
+
 AppActivity::AppActivity(AppState app_state)
     : app_state_(app_state),
       running_active_time_(base::TimeDelta::FromSeconds(0)),
@@ -147,6 +177,23 @@
          (base::TimeTicks::Now() - last_updated_time_ticks_);
 }
 
+void AppActivity::RemoveActiveTimeEarlierThan(base::Time timestamp) {
+  for (auto active_time = active_times_.begin();
+       active_time != active_times_.end();) {
+    if (active_time->IsEarlierThan(timestamp)) {
+      active_time = active_times_.erase(active_time);
+      continue;
+    }
+    if (active_time->IsLaterThan(timestamp)) {
+      ++active_time;
+      continue;
+    }
+    DCHECK(active_time->Contains(timestamp));
+    active_time->set_active_from(timestamp);
+    ++active_time;
+  }
+}
+
 }  // namespace app_time
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types.h b/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
index 8998859..26e315f 100644
--- a/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
@@ -5,10 +5,10 @@
 #ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TYPES_H_
 #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TYPES_H_
 
-#include <optional>
+#include <list>
 #include <string>
-#include <vector>
 
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "chrome/services/app_service/public/mojom/types.mojom.h"
 
@@ -110,8 +110,22 @@
     ActiveTime(const ActiveTime& rhs);
     ActiveTime& operator=(const ActiveTime& rhs);
 
+    bool operator==(const ActiveTime&) const;
+    bool operator!=(const ActiveTime&) const;
+
+    // Returns whether |timestamp| is included in this time period.
+    bool Contains(base::Time timestamp) const;
+
+    // Returns whether |timestamp| is earlier than this time period's start.
+    bool IsEarlierThan(base::Time timestamp) const;
+
+    // Returns whether |timestamp| is later than this time period's end.
+    bool IsLaterThan(base::Time timestamp) const;
+
     base::Time active_from() const { return active_from_; }
+    void set_active_from(base::Time active_from);
     base::Time active_to() const { return active_to_; }
+    void set_active_to(base::Time active_to);
 
    private:
     base::Time active_from_;
@@ -136,9 +150,12 @@
 
   base::TimeDelta RunningActiveTime() const;
 
+  // Removes active time data older than given |timestamp|.
+  void RemoveActiveTimeEarlierThan(base::Time timestamp);
+
   bool is_active() const { return is_active_; }
   AppState app_state() const { return app_state_; }
-  const std::vector<ActiveTime>& active_times() const { return active_times_; }
+  const std::list<ActiveTime>& active_times() const { return active_times_; }
 
  private:
   // boolean to specify if the application is active.
@@ -153,7 +170,7 @@
   base::TimeDelta running_active_time_;
 
   // The time app was active.
-  std::vector<ActiveTime> active_times_;
+  std::list<ActiveTime> active_times_;
 
   // Time tick for the last time the activity was updated.
   base::TimeTicks last_updated_time_ticks_;
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc
new file mode 100644
index 0000000..8a06c9d
--- /dev/null
+++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types_unittest.cc
@@ -0,0 +1,143 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h"
+
+#include <string>
+
+#include "base/stl_util.h"
+#include "base/test/gtest_util.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace app_time {
+
+namespace {
+base::Time TimeFromString(const std::string& str) {
+  base::Time timestamp;
+  EXPECT_TRUE(base::Time::FromString(str.c_str(), &timestamp));
+  return timestamp;
+}
+
+}  // namespace
+
+using ActiveTimeTest = testing::Test;
+using AppActivityTest = testing::Test;
+
+TEST_F(ActiveTimeTest, CreateActiveTime) {
+  const base::Time start = TimeFromString("11 Jan 2020 10:00:00 PST");
+  const base::Time end = TimeFromString("11 Jan 2020 10:10:00 PST");
+
+  // Create ActiveTime with the correct timestamps.
+  const AppActivity::ActiveTime active_time(start, end);
+  EXPECT_EQ(start, active_time.active_from());
+  EXPECT_EQ(end, active_time.active_to());
+
+  // Try to create ActiveTime with invalid ranges.
+  EXPECT_DCHECK_DEATH(AppActivity::ActiveTime(start, start));
+  EXPECT_DCHECK_DEATH(AppActivity::ActiveTime(end, start));
+}
+
+TEST_F(ActiveTimeTest, UpdateActiveTime) {
+  AppActivity::ActiveTime active_time(
+      TimeFromString("11 Jan 2020 10:00:00 PST"),
+      TimeFromString("11 Jan 2020 10:10:00 PST"));
+  const base::Time& start_equal_end = active_time.active_to();
+  EXPECT_DCHECK_DEATH(active_time.set_active_from(start_equal_end));
+
+  const base::Time start_after_end =
+      active_time.active_to() + base::TimeDelta::FromSeconds(1);
+  EXPECT_DCHECK_DEATH(active_time.set_active_from(start_after_end));
+
+  const base::Time& end_equal_start = active_time.active_from();
+  EXPECT_DCHECK_DEATH(active_time.set_active_to(end_equal_start));
+
+  const base::Time end_before_start =
+      active_time.active_from() - base::TimeDelta::FromSeconds(1);
+  EXPECT_DCHECK_DEATH(active_time.set_active_to(end_before_start));
+}
+
+TEST_F(ActiveTimeTest, ActiveTimeTimestampComparisions) {
+  const AppActivity::ActiveTime active_time(
+      TimeFromString("11 Jan 2020 10:00:00 PST"),
+      TimeFromString("11 Jan 2020 10:10:00 PST"));
+
+  const base::Time contained = TimeFromString("11 Jan 2020 10:05:00 PST");
+  EXPECT_TRUE(active_time.Contains(contained));
+  EXPECT_FALSE(active_time.IsEarlierThan(contained));
+  EXPECT_FALSE(active_time.IsLaterThan(contained));
+
+  const base::Time before = TimeFromString("11 Jan 2020 09:58:00 PST");
+  EXPECT_FALSE(active_time.Contains(before));
+  EXPECT_FALSE(active_time.IsEarlierThan(before));
+  EXPECT_TRUE(active_time.IsLaterThan(before));
+
+  const base::Time after = TimeFromString("11 Jan 2020 10:11:00 PST");
+  EXPECT_FALSE(active_time.Contains(after));
+  EXPECT_TRUE(active_time.IsEarlierThan(after));
+  EXPECT_FALSE(active_time.IsLaterThan(after));
+
+  const base::Time& equal_start = active_time.active_from();
+  EXPECT_FALSE(active_time.Contains(equal_start));
+  EXPECT_FALSE(active_time.IsEarlierThan(equal_start));
+  EXPECT_TRUE(active_time.IsLaterThan(equal_start));
+
+  const base::Time& equal_end = active_time.active_to();
+  EXPECT_FALSE(active_time.Contains(equal_end));
+  EXPECT_TRUE(active_time.IsEarlierThan(equal_end));
+  EXPECT_FALSE(active_time.IsLaterThan(equal_end));
+}
+
+TEST_F(AppActivityTest, RemoveActiveTimes) {
+  base::test::TaskEnvironment task_environment(
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+  AppActivity activity(AppState::kAvailable);
+
+  // Time interval that will be removed.
+  base::Time start = base::Time::Now();
+  activity.SetAppActive(start);
+  task_environment.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  base::Time end = base::Time::Now();
+  activity.SetAppInactive(end);
+  const AppActivity::ActiveTime to_remove(start, end);
+
+  // Time interval that will be trimmed.
+  start = base::Time::Now();
+  activity.SetAppActive(start);
+  task_environment.FastForwardBy(base::TimeDelta::FromMinutes(5));
+  const base::Time report_time = base::Time::Now();
+  task_environment.FastForwardBy(base::TimeDelta::FromMinutes(5));
+  end = base::Time::Now();
+  activity.SetAppInactive(end);
+  const AppActivity::ActiveTime to_trim(start, end);
+
+  // Time interval that will be kept.
+  start = base::Time::Now();
+  activity.SetAppActive(start);
+  task_environment.FastForwardBy(base::TimeDelta::FromMinutes(10));
+  end = base::Time::Now();
+  activity.SetAppInactive(end);
+  const AppActivity::ActiveTime to_keep(start, end);
+
+  EXPECT_EQ(3u, activity.active_times().size());
+  EXPECT_TRUE(base::Contains(activity.active_times(), to_remove));
+  EXPECT_TRUE(base::Contains(activity.active_times(), to_trim));
+  EXPECT_TRUE(base::Contains(activity.active_times(), to_keep));
+
+  activity.RemoveActiveTimeEarlierThan(report_time);
+
+  EXPECT_EQ(2u, activity.active_times().size());
+  EXPECT_FALSE(base::Contains(activity.active_times(), to_remove));
+  EXPECT_TRUE(base::Contains(activity.active_times(), to_keep));
+
+  const AppActivity::ActiveTime trimmed(report_time, to_trim.active_to());
+  EXPECT_TRUE(base::Contains(activity.active_times(), trimmed));
+}
+
+// TODO(agawronska) : Add more tests for app activity.
+
+}  // namespace app_time
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/eula_browsertest.cc b/chrome/browser/chromeos/login/eula_browsertest.cc
index c1027e7..a7c0fc38 100644
--- a/chrome/browser/chromeos/login/eula_browsertest.cc
+++ b/chrome/browser/chromeos/login/eula_browsertest.cc
@@ -272,8 +272,14 @@
                   .find(kOfflineEULAWarning) != std::string::npos);
 }
 
+#if defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER)
+// TODO(http://crbug.com/1041188): flaky on ChromeOS MSAN.
+#define MAYBE_LoadOnline DISABLED_LoadOnline
+#else
+#define MAYBE_LoadOnline LoadOnline
+#endif
 // Tests that online version is shown when it is accessible.
-IN_PROC_BROWSER_TEST_F(EulaTest, LoadOnline) {
+IN_PROC_BROWSER_TEST_F(EulaTest, MAYBE_LoadOnline) {
   ShowEulaScreen();
 
   // Wait until the webview has finished loading.
diff --git a/chrome/browser/component_updater/intervention_policy_database_component_installer.cc b/chrome/browser/component_updater/intervention_policy_database_component_installer.cc
new file mode 100644
index 0000000..1da07b90
--- /dev/null
+++ b/chrome/browser/component_updater/intervention_policy_database_component_installer.cc
@@ -0,0 +1,127 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/intervention_policy_database_component_installer.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
+#include "components/component_updater/component_updater_paths.h"
+#include "components/component_updater/component_updater_service.h"
+#include "components/crx_file/id_util.h"
+
+using component_updater::ComponentUpdateService;
+
+namespace {
+
+// The SHA256 of the SubjectPublicKeyInfo used to sign the component.
+// The component id is: copjbmjbojbakpaedmpkhmiplmmehfck
+const uint8_t kInterventionPolicyDatabasePublicKeySHA256[32] = {
+    0x2e, 0xf9, 0x1c, 0x91, 0xe9, 0x10, 0xaf, 0x04, 0x3c, 0xfa, 0x7c,
+    0x8f, 0xbc, 0xc4, 0x75, 0x2a, 0x48, 0x9a, 0x64, 0x74, 0xc6, 0xda,
+    0xb7, 0xb9, 0xdf, 0x5f, 0x51, 0x3e, 0x50, 0x39, 0x04, 0xab};
+
+// The name of the component, used in the chrome://components page.
+const char kInterventionPolicyDatabaseComponentName[] =
+    "Intervention Policy Database";
+
+// The name of the database file inside of an installation of this component.
+const base::FilePath::CharType kInterventionPolicyDatabaseBinaryPbFileName[] =
+    FILE_PATH_LITERAL("intervention_policy_database.pb");
+
+}  // namespace
+
+namespace component_updater {
+
+InterventionPolicyDatabaseComponentInstallerPolicy::
+    InterventionPolicyDatabaseComponentInstallerPolicy(
+        resource_coordinator::InterventionPolicyDatabase* database)
+    : database_(database) {
+  DCHECK(database_);
+}
+
+bool InterventionPolicyDatabaseComponentInstallerPolicy::
+    SupportsGroupPolicyEnabledComponentUpdates() const {
+  return false;
+}
+
+bool InterventionPolicyDatabaseComponentInstallerPolicy::
+    RequiresNetworkEncryption() const {
+  // Public data is delivered via this component, no need for encryption.
+  return false;
+}
+
+update_client::CrxInstaller::Result
+InterventionPolicyDatabaseComponentInstallerPolicy::OnCustomInstall(
+    const base::DictionaryValue& manifest,
+    const base::FilePath& install_dir) {
+  return update_client::CrxInstaller::Result(0);
+}
+
+void InterventionPolicyDatabaseComponentInstallerPolicy::OnCustomUninstall() {}
+
+// Called during startup and installation before ComponentReady().
+bool InterventionPolicyDatabaseComponentInstallerPolicy::VerifyInstallation(
+    const base::DictionaryValue& manifest,
+    const base::FilePath& install_dir) const {
+  return base::PathExists(
+      install_dir.Append(kInterventionPolicyDatabaseBinaryPbFileName));
+}
+
+// NOTE: This is always called on the main UI thread. It is called once every
+// startup to notify of an already installed component, and may be called
+// repeatedly after that every time a new component is ready.
+void InterventionPolicyDatabaseComponentInstallerPolicy::ComponentReady(
+    const base::Version& version,
+    const base::FilePath& install_dir,
+    std::unique_ptr<base::DictionaryValue> manifest) {
+  DCHECK(database_);
+  database_->InitializeDatabaseWithProtoFile(
+      install_dir.Append(kInterventionPolicyDatabaseBinaryPbFileName), version,
+      std::move(manifest));
+}
+
+base::FilePath
+InterventionPolicyDatabaseComponentInstallerPolicy::GetRelativeInstallDir()
+    const {
+  return base::FilePath(FILE_PATH_LITERAL("InterventionPolicyDatabase"));
+}
+
+void InterventionPolicyDatabaseComponentInstallerPolicy::GetHash(
+    std::vector<uint8_t>* hash) const {
+  hash->assign(kInterventionPolicyDatabasePublicKeySHA256,
+               kInterventionPolicyDatabasePublicKeySHA256 +
+                   base::size(kInterventionPolicyDatabasePublicKeySHA256));
+}
+
+std::string InterventionPolicyDatabaseComponentInstallerPolicy::GetName()
+    const {
+  return kInterventionPolicyDatabaseComponentName;
+}
+
+update_client::InstallerAttributes
+InterventionPolicyDatabaseComponentInstallerPolicy::GetInstallerAttributes()
+    const {
+  return update_client::InstallerAttributes();
+}
+
+std::vector<std::string>
+InterventionPolicyDatabaseComponentInstallerPolicy::GetMimeTypes() const {
+  return std::vector<std::string>();
+}
+
+void RegisterInterventionPolicyDatabaseComponent(
+    ComponentUpdateService* cus,
+    resource_coordinator::InterventionPolicyDatabase* database) {
+  std::unique_ptr<ComponentInstallerPolicy> policy(
+      new InterventionPolicyDatabaseComponentInstallerPolicy(database));
+  auto installer = base::MakeRefCounted<ComponentInstaller>(std::move(policy));
+  installer->Register(cus, base::OnceClosure());
+}
+
+}  // namespace component_updater
diff --git a/chrome/browser/component_updater/intervention_policy_database_component_installer.h b/chrome/browser/component_updater/intervention_policy_database_component_installer.h
new file mode 100644
index 0000000..1abe36d
--- /dev/null
+++ b/chrome/browser/component_updater/intervention_policy_database_component_installer.h
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_INTERVENTION_POLICY_DATABASE_COMPONENT_INSTALLER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_INTERVENTION_POLICY_DATABASE_COMPONENT_INSTALLER_H_
+
+#include "components/component_updater/component_installer.h"
+
+namespace resource_coordinator {
+class InterventionPolicyDatabase;
+}
+
+namespace component_updater {
+
+class ComponentUpdateService;
+
+// Component for receiving the intervention policy database. The database
+// consists in a proto, defined in
+// chrome/browser/resource_coordinator/intervention_policy_database.proto.
+class InterventionPolicyDatabaseComponentInstallerPolicy
+    : public ComponentInstallerPolicy {
+ public:
+  InterventionPolicyDatabaseComponentInstallerPolicy(
+      resource_coordinator::InterventionPolicyDatabase* database);
+  ~InterventionPolicyDatabaseComponentInstallerPolicy() override = default;
+
+ private:
+  // ComponentInstallerPolicy:
+  bool SupportsGroupPolicyEnabledComponentUpdates() const override;
+  bool RequiresNetworkEncryption() const override;
+  update_client::CrxInstaller::Result OnCustomInstall(
+      const base::DictionaryValue& manifest,
+      const base::FilePath& install_dir) override;
+  void OnCustomUninstall() override;
+  bool VerifyInstallation(const base::DictionaryValue& manifest,
+                          const base::FilePath& install_dir) const override;
+  void ComponentReady(const base::Version& version,
+                      const base::FilePath& install_dir,
+                      std::unique_ptr<base::DictionaryValue> manifest) override;
+  base::FilePath GetRelativeInstallDir() const override;
+  void GetHash(std::vector<uint8_t>* hash) const override;
+  std::string GetName() const override;
+  update_client::InstallerAttributes GetInstallerAttributes() const override;
+  std::vector<std::string> GetMimeTypes() const override;
+
+  resource_coordinator::InterventionPolicyDatabase* database_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterventionPolicyDatabaseComponentInstallerPolicy);
+};
+
+// Call once to make the component update service aware of the Intervention
+// Policy Database component.
+void RegisterInterventionPolicyDatabaseComponent(
+    ComponentUpdateService* cus,
+    resource_coordinator::InterventionPolicyDatabase* database);
+
+}  // namespace component_updater
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_INTERVENTION_POLICY_DATABASE_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/enterprise_reporting/notification/extension_request_notification.cc b/chrome/browser/enterprise_reporting/notification/extension_request_notification.cc
new file mode 100644
index 0000000..659efac2
--- /dev/null
+++ b/chrome/browser/enterprise_reporting/notification/extension_request_notification.cc
@@ -0,0 +1,109 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/enterprise_reporting/notification/extension_request_notification.h"
+
+#include <memory>
+
+#include "chrome/browser/notifications/notification_display_service.h"
+#include "chrome/browser/notifications/notification_display_service_factory.h"
+#include "chrome/browser/notifications/notification_handler.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/message_center/public/cpp/message_center_constants.h"
+#include "ui/message_center/public/cpp/notification.h"
+#include "ui/message_center/public/cpp/notification_delegate.h"
+#include "ui/native_theme/native_theme.h"
+
+namespace enterprise_reporting {
+namespace {
+
+constexpr char kApprovedNotificationId[] = "extension_approved_notificaiton";
+constexpr char kRejectedNotificationId[] = "extension_rejected_notificaiton";
+constexpr char kInstalledNotificationId[] = "extension_installed_notificaiton";
+constexpr char kExtensionRequestNotifierId[] =
+    "chrome_browser_cloud_management_extension_request";
+constexpr char kChromeWebstoreUrl[] =
+    "https://chrome.google.com/webstore/detail/";
+
+// The elements order of array below must match the order in enum
+// ExtensionRequestNotification::NotifyType.
+const char* const kNotificationIds[] = {
+    kApprovedNotificationId, kRejectedNotificationId, kInstalledNotificationId};
+constexpr int kNotificationTitles[] = {
+    IDS_ENTERPRISE_EXTENSION_REQUEST_APPROVED_TITLE,
+    IDS_ENTERPRISE_EXTENSION_REQUEST_REJECTED_TITLE,
+    IDS_ENTERPRISE_EXTENSION_REQUEST_FORCE_INSTALLED_TITLE};
+constexpr int kNotificationBodies[] = {
+    IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_INSTALL,
+    IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_VIEW,
+    IDS_ENTERPRISE_EXTENSION_REQUEST_CLICK_TO_VIEW};
+
+}  // namespace
+
+ExtensionRequestNotification::ExtensionRequestNotification() = default;
+
+ExtensionRequestNotification::ExtensionRequestNotification(
+    Profile* profile,
+    const NotifyType notify_type,
+    const ExtensionIds& extension_ids)
+    : profile_(profile),
+      notify_type_(notify_type),
+      extension_ids_(extension_ids) {}
+
+ExtensionRequestNotification::~ExtensionRequestNotification() = default;
+
+void ExtensionRequestNotification::Show() {
+  if (extension_ids_.empty()) {
+    NOTREACHED();
+    return;
+  }
+
+  const base::string16 title = l10n_util::GetPluralStringFUTF16(
+      kNotificationTitles[notify_type_], extension_ids_.size());
+  const base::string16 body = l10n_util::GetPluralStringFUTF16(
+      kNotificationBodies[notify_type_], extension_ids_.size());
+  GURL original_url("https://chrome.google.com/webstore");
+  gfx::Image icon(gfx::CreateVectorIcon(
+      vector_icons::kBusinessIcon, message_center::kSmallImageSize,
+      ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
+          ui::NativeTheme::kColorId_DefaultIconColor)));
+
+  notification_ = std::make_unique<message_center::Notification>(
+      message_center::NOTIFICATION_TYPE_SIMPLE, kNotificationIds[notify_type_],
+      title, body, icon, /*source=*/base::string16(), original_url,
+      message_center::NotifierId(message_center::NotifierType::APPLICATION,
+                                 kExtensionRequestNotifierId),
+      message_center::RichNotificationData(),
+      new message_center::HandleNotificationClickDelegate(base::BindRepeating(
+          &ExtensionRequestNotification::OnClick, weak_factory_.GetWeakPtr())));
+  notification_->set_never_timeout(true);
+
+  NotificationDisplayService::GetForProfile(profile_)->Display(
+      NotificationHandler::Type::TRANSIENT, *notification_, nullptr);
+}
+
+void ExtensionRequestNotification::Close() {
+  NotificationDisplayService::GetForProfile(profile_)->Close(
+      NotificationHandler::Type::TRANSIENT, kNotificationIds[notify_type_]);
+  notification_.reset();
+}
+
+void ExtensionRequestNotification::OnClick(
+    const base::Optional<int> button_index) {
+  for (const std::string& extension_id : extension_ids_) {
+    NavigateParams params(profile_, GURL(kChromeWebstoreUrl + extension_id),
+                          ui::PAGE_TRANSITION_LINK);
+    params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
+    params.window_action = NavigateParams::SHOW_WINDOW;
+    Navigate(&params);
+  }
+  Close();
+}
+
+}  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/notification/extension_request_notification.h b/chrome/browser/enterprise_reporting/notification/extension_request_notification.h
new file mode 100644
index 0000000..70fab98
--- /dev/null
+++ b/chrome/browser/enterprise_reporting/notification/extension_request_notification.h
@@ -0,0 +1,49 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ENTERPRISE_REPORTING_NOTIFICATION_EXTENSION_REQUEST_NOTIFICATION_H_
+#define CHROME_BROWSER_ENTERPRISE_REPORTING_NOTIFICATION_EXTENSION_REQUEST_NOTIFICATION_H_
+
+#include "ui/message_center/public/cpp/notification_delegate.h"
+
+namespace message_center {
+class Notification;
+}
+
+class Profile;
+
+namespace enterprise_reporting {
+
+class ExtensionRequestNotification {
+ public:
+  using ExtensionIds = std::vector<std::string>;
+  enum NotifyType { kApproved = 0, kRejected = 1, kForceInstalled = 2 };
+
+  ExtensionRequestNotification();
+  ExtensionRequestNotification(Profile* profile,
+                               const NotifyType notify_type,
+                               const ExtensionIds& extension_ids);
+  ExtensionRequestNotification(const ExtensionRequestNotification&) = delete;
+  ExtensionRequestNotification& operator=(const ExtensionRequestNotification&) =
+      delete;
+  virtual ~ExtensionRequestNotification();
+
+  void Show();
+  void Close();
+
+ private:
+  void OnClick(const base::Optional<int> button_index);
+
+  std::unique_ptr<message_center::Notification> notification_;
+
+  Profile* profile_;
+  const NotifyType notify_type_ = kApproved;
+  const ExtensionIds extension_ids_;
+
+  base::WeakPtrFactory<ExtensionRequestNotification> weak_factory_{this};
+};
+
+}  // namespace enterprise_reporting
+
+#endif  // CHROME_BROWSER_ENTERPRISE_REPORTING_NOTIFICATION_EXTENSION_REQUEST_NOTIFICATION_H_
diff --git a/chrome/browser/enterprise_reporting/notification/extension_request_notification_unittest.cc b/chrome/browser/enterprise_reporting/notification/extension_request_notification_unittest.cc
new file mode 100644
index 0000000..f6ecddc9
--- /dev/null
+++ b/chrome/browser/enterprise_reporting/notification/extension_request_notification_unittest.cc
@@ -0,0 +1,115 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/enterprise_reporting/notification/extension_request_notification.h"
+
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/notifications/notification_display_service_tester.h"
+#include "chrome/browser/notifications/notification_handler.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::HasSubstr;
+
+namespace enterprise_reporting {
+
+constexpr char kChromeWebstoreUrl[] =
+    "https://chrome.google.com/webstore/detail/";
+constexpr char kFakeExtensionId[] = "fake-extension-id";
+
+// The elements order of array below must match the order in enum
+// ExtensionRequestNotification::NotifyType.
+const char* const kNotificationIds[] = {"extension_approved_notificaiton",
+                                        "extension_rejected_notificaiton",
+                                        "extension_installed_notificaiton"};
+const char* const kNotificationTitleKeywords[] = {"approved", "rejected",
+                                                  "installed"};
+const char* const kNotificationBodyKeywords[] = {"to install", "to view",
+                                                 "to view"};
+
+class ExtensionRequestNotificationTest
+    : public BrowserWithTestWindowTest,
+      public testing::WithParamInterface<
+          ExtensionRequestNotification::NotifyType> {
+ public:
+  ExtensionRequestNotificationTest() = default;
+  ~ExtensionRequestNotificationTest() override = default;
+
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+    display_service_tester_ =
+        std::make_unique<NotificationDisplayServiceTester>(profile());
+  }
+
+  ExtensionRequestNotification::NotifyType GetNotifyType() {
+    return GetParam();
+  }
+
+  base::Optional<message_center::Notification> GetNotification() {
+    return display_service_tester_->GetNotification(
+        kNotificationIds[GetNotifyType()]);
+  }
+
+  std::unique_ptr<NotificationDisplayServiceTester> display_service_tester_;
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    ExtensionRequestNotificationTest,
+    ExtensionRequestNotificationTest,
+    ::testing::Values(ExtensionRequestNotification::kApproved,
+                      ExtensionRequestNotification::kRejected,
+                      ExtensionRequestNotification::kForceInstalled));
+
+TEST_P(ExtensionRequestNotificationTest, NoExtension) {
+  ExtensionRequestNotification request_notification(
+      profile(), GetNotifyType(), ExtensionRequestNotification::ExtensionIds());
+#if DCHECK_IS_ON()
+  EXPECT_DEATH_IF_SUPPORTED(request_notification.Show(), "");
+#else
+  request_notification.Show();
+#endif
+  task_environment()->RunUntilIdle();
+  EXPECT_FALSE(GetNotification().has_value());
+}
+
+TEST_P(ExtensionRequestNotificationTest, HasExtension) {
+  ExtensionRequestNotification request_notification(
+      profile(), GetNotifyType(),
+      ExtensionRequestNotification::ExtensionIds({kFakeExtensionId}));
+  base::RunLoop show_run_loop;
+  display_service_tester_->SetNotificationAddedClosure(
+      show_run_loop.QuitClosure());
+  request_notification.Show();
+  show_run_loop.Run();
+
+  base::Optional<message_center::Notification> notification = GetNotification();
+  ASSERT_TRUE(notification.has_value());
+
+  EXPECT_THAT(base::UTF16ToUTF8(notification->title()),
+              HasSubstr(kNotificationTitleKeywords[GetNotifyType()]));
+  EXPECT_THAT(base::UTF16ToUTF8(notification->message()),
+              HasSubstr(kNotificationBodyKeywords[GetNotifyType()]));
+
+  base::RunLoop close_run_loop;
+  display_service_tester_->SetNotificationClosedClosure(
+      close_run_loop.QuitClosure());
+  display_service_tester_->SimulateClick(
+      NotificationHandler::Type::TRANSIENT, kNotificationIds[GetNotifyType()],
+      base::Optional<int>(), base::Optional<base::string16>());
+  close_run_loop.Run();
+
+  EXPECT_FALSE(GetNotification().has_value());
+  std::string expected_url =
+      std::string(kChromeWebstoreUrl) + std::string(kFakeExtensionId);
+  EXPECT_EQ(GURL(expected_url),
+            browser()->tab_strip_model()->GetWebContentsAt(0)->GetURL());
+}
+
+}  // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_scheduler.h b/chrome/browser/enterprise_reporting/report_scheduler.h
index d169e7b1..dc07250 100644
--- a/chrome/browser/enterprise_reporting/report_scheduler.h
+++ b/chrome/browser/enterprise_reporting/report_scheduler.h
@@ -12,6 +12,7 @@
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "chrome/browser/enterprise_reporting/notification/extension_request_notification.h"
 #include "chrome/browser/enterprise_reporting/report_generator.h"
 #include "chrome/browser/enterprise_reporting/report_uploader.h"
 #include "chrome/browser/profiles/profile_manager_observer.h"
@@ -88,6 +89,11 @@
 
   std::unique_ptr<base::flat_set<base::FilePath>> stale_profiles_;
 
+  // Create an un-used notification instance so that the resources won't be
+  // filtered out in the unit test. This will be removed once the whole
+  // implementation is finished.
+  ExtensionRequestNotification notification_;
+
   DISALLOW_COPY_AND_ASSIGN(ReportScheduler);
 };
 
diff --git a/chrome/browser/extensions/OWNERS b/chrome/browser/extensions/OWNERS
index e0f532e..77d2753 100644
--- a/chrome/browser/extensions/OWNERS
+++ b/chrome/browser/extensions/OWNERS
@@ -6,8 +6,8 @@
 per-file extension_gcm_app_handler*=file://chrome/browser/extensions/api/gcm/OWNERS
 
 # For security review.
-per-file chrome_extensions_browser_interface_binders.cc=set noparent
-per-file chrome_extensions_browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
+per-file chrome_extensions_browser_interface_binders.*=set noparent
+per-file chrome_extensions_browser_interface_binders.*=file://ipc/SECURITY_OWNERS
 
 # For adding/renaming files for Chrome OS apps APIs.
 per-file BUILD.gn=stevenjb@chromium.org
diff --git a/chrome/browser/image_fetcher/BUILD.gn b/chrome/browser/image_fetcher/BUILD.gn
index 77877e0..25b0a79 100644
--- a/chrome/browser/image_fetcher/BUILD.gn
+++ b/chrome/browser/image_fetcher/BUILD.gn
@@ -27,7 +27,5 @@
 }
 
 generate_jni("jni_headers") {
-  sources = [
-    "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
-  ]
+  sources = [ "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java" ]
 }
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index f3c7ced..c7e94a2 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -212,9 +212,7 @@
     "//chrome/test:test_support",
     "//testing/gmock",
   ]
-  public_deps = [
-    ":router",
-  ]
+  public_deps = [ ":router" ]
   sources = [
     "test/mock_media_router.cc",
     "test/mock_media_router.h",
@@ -350,9 +348,7 @@
 }
 
 fuzzer_test("dial_internal_message_fuzzer") {
-  sources = [
-    "providers/dial/dial_internal_message_fuzzer.cc",
-  ]
+  sources = [ "providers/dial/dial_internal_message_fuzzer.cc" ]
   deps = [
     ":router",
     "//base",
diff --git a/chrome/browser/media/router/discovery/BUILD.gn b/chrome/browser/media/router/discovery/BUILD.gn
index c5e3bf57..902ab86 100644
--- a/chrome/browser/media/router/discovery/BUILD.gn
+++ b/chrome/browser/media/router/discovery/BUILD.gn
@@ -5,9 +5,7 @@
 assert(!is_android)
 
 static_library("discovery") {
-  inputs = [
-    "$root_gen_dir/chrome/grit/generated_resources.h",
-  ]
+  inputs = [ "$root_gen_dir/chrome/grit/generated_resources.h" ]
   deps = [
     "//base",
     "//base:i18n",
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
index f3ff52eb..7073d93f7 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
@@ -575,8 +575,8 @@
       0);
 }
 
-// TODO(https://crbug.com/1034433) Flaky on Mac10.12
-#if defined(OS_MACOSX)
+// TODO(https://crbug.com/1034433) Flaky on Mac10.12 and Windows.
+#if defined(OS_MACOSX) || defined(OS_WIN)
 #define MAYBE_NoPredictionModelForRegisteredOptimizationTarget \
   DISABLED_NoPredictionModelForRegisteredOptimizationTarget
 #else
@@ -1038,8 +1038,8 @@
       PredictionManagerModelStatus::kStoreAvailableModelNotLoaded, 1);
 }
 
-// TODO(https://crbug.com/1034433) Flaky on Mac10.12
-#if defined(OS_MACOSX)
+// TODO(https://crbug.com/1034433) Flaky on Mac10.12 and Windows.
+#if defined(OS_MACOSX) || defined(OS_WIN)
 #define MAYBE_ShouldTargetNavigationStoreUnavailableModelUnknown \
   DISABLED_ShouldTargetNavigationStoreUnavailableModelUnknown
 #else
@@ -1107,8 +1107,8 @@
       "OptimizationGuide.PredictionManager.HostModelFeaturesStored", 0);
 }
 
-// TODO(https://crbug.com/1034433) Flaky on Mac10.12
-#if defined(OS_MACOSX)
+// TODO(https://crbug.com/1034433) Flaky on Mac10.12 and Windows.
+#if defined(OS_MACOSX) || defined(OS_WIN)
 #define MAYBE_UpdateModelWithUnsupportedOptimizationTarget \
   DISABLED_UpdateModelWithUnsupportedOptimizationTarget
 #else
diff --git a/chrome/browser/performance_manager/BUILD.gn b/chrome/browser/performance_manager/BUILD.gn
index ab1114ae..a0a3843 100644
--- a/chrome/browser/performance_manager/BUILD.gn
+++ b/chrome/browser/performance_manager/BUILD.gn
@@ -6,7 +6,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("site_data_proto") {
-  sources = [
-    "persistence/site_data/site_data.proto",
-  ]
+  sources = [ "persistence/site_data/site_data.proto" ]
 }
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 21b3a49..ec99041 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -508,14 +508,8 @@
 
 // Tests that when closing a Picture-in-Picture window, the video element is
 // reflected as no longer in Picture-in-Picture.
-// TODO(crbug.com/1001421): Flaky on ASan.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_CloseWindowWhilePlaying DISABLED_CloseWindowWhilePlaying
-#else
-#define MAYBE_CloseWindowWhilePlaying CloseWindowWhilePlaying
-#endif
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       MAYBE_CloseWindowWhilePlaying) {
+                       CloseWindowWhilePlaying) {
   GURL test_page_url = ui_test_utils::GetTestUrl(
       base::FilePath(base::FilePath::kCurrentDirectory),
       base::FilePath(kPictureInPictureWindowSizePage));
@@ -665,16 +659,8 @@
 
 // Tests that when starting a new Picture-in-Picture session from the same
 // video, the video stays in Picture-in-Picture mode.
-// TODO(crbug.com/1001446): Flaky on ASan.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_RequestPictureInPictureTwiceFromSameVideo \
-  DISABLED_RequestPictureInPictureTwiceFromSameVideo
-#else
-#define MAYBE_RequestPictureInPictureTwiceFromSameVideo \
-  RequestPictureInPictureTwiceFromSameVideo
-#endif
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       MAYBE_RequestPictureInPictureTwiceFromSameVideo) {
+                       RequestPictureInPictureTwiceFromSameVideo) {
   GURL test_page_url = ui_test_utils::GetTestUrl(
       base::FilePath(base::FilePath::kCurrentDirectory),
       base::FilePath(kPictureInPictureWindowSizePage));
@@ -730,16 +716,8 @@
 
 // Tests that when starting a new Picture-in-Picture session from the same tab,
 // the previous video is no longer in Picture-in-Picture mode.
-// TODO(crbug.com/1001421): Flaky on ASan.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_OpenSecondPictureInPictureStopsFirst \
-  DISABLED_OpenSecondPictureInPictureStopsFirst
-#else
-#define MAYBE_OpenSecondPictureInPictureStopsFirst \
-  OpenSecondPictureInPictureStopsFirst
-#endif
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       MAYBE_OpenSecondPictureInPictureStopsFirst) {
+                       OpenSecondPictureInPictureStopsFirst) {
   GURL test_page_url = ui_test_utils::GetTestUrl(
       base::FilePath(base::FilePath::kCurrentDirectory),
       base::FilePath(kPictureInPictureWindowSizePage));
@@ -1436,14 +1414,8 @@
 
 // Tests that the play/pause icon state is properly updated when a
 // Picture-in-Picture is created after a reload.
-// TODO(crbug.com/1001421): Flaky on ASan.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_PlayPauseStateAtCreation DISABLED_PlayPauseStateAtCreation
-#else
-#define MAYBE_PlayPauseStateAtCreation PlayPauseStateAtCreation
-#endif
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       MAYBE_PlayPauseStateAtCreation) {
+                       PlayPauseStateAtCreation) {
   LoadTabAndEnterPictureInPicture(
       browser(), base::FilePath(kPictureInPictureWindowSizePage));
 
@@ -1555,14 +1527,8 @@
 // changing source willproperly update the associated media player id. This is
 // checked by closing the window because the test it at a too high level to be
 // able to check the actual media player id being used.
-// TODO(crbug.com/1001421): Flaky on ASan.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_PreloadNoneSrcChangeThenLoad DISABLED_PreloadNoneSrcChangeThenLoad
-#else
-#define MAYBE_PreloadNoneSrcChangeThenLoad PreloadNoneSrcChangeThenLoad
-#endif
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       MAYBE_PreloadNoneSrcChangeThenLoad) {
+                       PreloadNoneSrcChangeThenLoad) {
   GURL test_page_url = ui_test_utils::GetTestUrl(
       base::FilePath(base::FilePath::kCurrentDirectory),
       base::FilePath(FILE_PATH_LITERAL(
@@ -2997,14 +2963,8 @@
   ExpectLeavePictureInPicture(active_web_contents);
 }
 
-// TODO(crbug.com/1002489): Test is flaky on Linux.
-#if defined(OS_LINUX)
-#define MAYBE_UpdateMaxSize DISABLED_UpdateMaxSize
-#else
-#define MAYBE_UpdateMaxSize UpdateMaxSize
-#endif
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
-                       MAYBE_UpdateMaxSize) {
+                       UpdateMaxSize) {
   LoadTabAndEnterPictureInPicture(
       browser(), base::FilePath(kPictureInPictureWindowSizePage));
 
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index e20d7f8c..c167871 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -665,6 +665,9 @@
   { key::kHighContrastEnabled,
     ash::prefs::kAccessibilityHighContrastEnabled,
     base::Value::Type::BOOLEAN },
+  { key::kAccessibilityShortcutsEnabled,
+    ash::prefs::kAccessibilityShortcutsEnabled,
+    base::Value::Type::BOOLEAN },
   { key::kVirtualKeyboardEnabled,
     ash::prefs::kAccessibilityVirtualKeyboardEnabled,
     base::Value::Type::BOOLEAN },
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index ba8df24..102bedc 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -429,6 +429,11 @@
     public static final String PRIVACY_ALLOW_PRERENDER_OLD = "allow_prefetch";
 
     /**
+     * Key to cache the enabled bottom toolbar parameter.
+     */
+    public static final String VARIATION_CACHED_BOTTOM_TOOLBAR = "bottom_toolbar_variation";
+
+    /**
      * Whether the promotion for data reduction has been skipped on first invocation.
      * Default value is false.
      */
@@ -442,6 +447,16 @@
 
     public static final String RLZ_NOTIFIED = "rlz_first_search_notified";
 
+    /** Key used to store the default Search Engine Type before choice is presented. */
+    public static final String SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE =
+            "search_engine_choice_default_type_before";
+    /** Key used to store the version of Chrome in which the choice was presented. */
+    public static final String SEARCH_ENGINE_CHOICE_PRESENTED_VERSION =
+            "search_engine_choice_presented_version";
+    /** Key used to store the date of when search engine choice was requested. */
+    public static final String SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP =
+            "search_engine_choice_requested_timestamp";
+
     /**
      * Generic signin and sync promo preferences.
      */
@@ -710,6 +725,9 @@
                 PROMOS_SKIPPED_ON_FIRST_START,
                 REACHED_CODE_PROFILER_GROUP,
                 RLZ_NOTIFIED,
+                SEARCH_ENGINE_CHOICE_DEFAULT_TYPE_BEFORE,
+                SEARCH_ENGINE_CHOICE_PRESENTED_VERSION,
+                SEARCH_ENGINE_CHOICE_REQUESTED_TIMESTAMP,
                 SIGNIN_AND_SYNC_PROMO_SHOW_COUNT,
                 SIGNIN_PROMO_IMPRESSIONS_COUNT_BOOKMARKS,
                 SIGNIN_PROMO_IMPRESSIONS_COUNT_SETTINGS,
@@ -729,6 +747,7 @@
                 TWA_DISCLOSURE_ACCEPTED_PACKAGES,
                 UI_THEME_DARKEN_WEBSITES_ENABLED,
                 UI_THEME_SETTING,
+                VARIATION_CACHED_BOTTOM_TOOLBAR,
                 VERIFIED_DIGITAL_ASSET_LINKS,
                 VR_SHOULD_REGISTER_ASSETS_COMPONENT_ON_STARTUP,
                 WEBAPK_UNINSTALLED_PACKAGES
diff --git a/chrome/browser/profiles/gaia_info_update_service.cc b/chrome/browser/profiles/gaia_info_update_service.cc
index 894f4742..893d0149 100644
--- a/chrome/browser/profiles/gaia_info_update_service.cc
+++ b/chrome/browser/profiles/gaia_info_update_service.cc
@@ -176,6 +176,5 @@
 
 bool GAIAInfoUpdateService::ShouldUpdate() {
   return identity_manager_->HasPrimaryAccount() ||
-         (identity_manager_->HasUnconsentedPrimaryAccount() &&
-          base::FeatureList::IsEnabled(kPersistUPAInProfileInfoCache));
+         identity_manager_->HasUnconsentedPrimaryAccount();
 }
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc
index 62035f2c..b660629 100644
--- a/chrome/browser/profiles/profile_attributes_entry.cc
+++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -51,9 +51,6 @@
 
 }  // namespace
 
-const base::Feature kPersistUPAInProfileInfoCache{
-    "PersistUPAInProfileInfoCache", base::FEATURE_ENABLED_BY_DEFAULT};
-
 const char ProfileAttributesEntry::kSupervisedUserId[] = "managed_user_id";
 const char ProfileAttributesEntry::kIsOmittedFromProfileListKey[] =
     "is_omitted_from_profile_list";
diff --git a/chrome/browser/profiles/profile_attributes_entry.h b/chrome/browser/profiles/profile_attributes_entry.h
index a843931..1502b67 100644
--- a/chrome/browser/profiles/profile_attributes_entry.h
+++ b/chrome/browser/profiles/profile_attributes_entry.h
@@ -32,8 +32,6 @@
   kSignedInWithConsentedPrimaryAccount,
 };
 
-extern const base::Feature kPersistUPAInProfileInfoCache;
-
 class ProfileAttributesEntry {
  public:
   static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
diff --git a/chrome/browser/resource_coordinator/BUILD.gn b/chrome/browser/resource_coordinator/BUILD.gn
index c5e180f..48db683 100644
--- a/chrome/browser/resource_coordinator/BUILD.gn
+++ b/chrome/browser/resource_coordinator/BUILD.gn
@@ -14,6 +14,12 @@
   sources = [ "lifecycle_unit_state.mojom" ]
 }
 
+proto_library("intervention_policy_database_proto") {
+  sources = [
+    "intervention_policy_database.proto",
+  ]
+}
+
 source_set("tab_manager_features") {
   public = [ "tab_manager_features.h" ]
 
diff --git a/chrome/browser/resource_coordinator/intervention_policy_database.cc b/chrome/browser/resource_coordinator/intervention_policy_database.cc
new file mode 100644
index 0000000..e15b9dacb
--- /dev/null
+++ b/chrome/browser/resource_coordinator/intervention_policy_database.cc
@@ -0,0 +1,102 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/task/post_task.h"
+#include "base/task_runner_util.h"
+#include "base/values.h"
+#include "chrome/browser/resource_coordinator/utils.h"
+
+namespace resource_coordinator {
+
+InterventionPolicyDatabase::OriginInterventionPolicies::
+    OriginInterventionPolicies(InterventionPolicy discarding_policy,
+                               InterventionPolicy freezing_policy)
+    : discarding_policy(discarding_policy), freezing_policy(freezing_policy) {}
+
+InterventionPolicyDatabase::InterventionPolicyDatabase() {}
+InterventionPolicyDatabase::~InterventionPolicyDatabase() = default;
+
+InterventionPolicyDatabase::InterventionPolicy
+InterventionPolicyDatabase::GetDiscardingPolicy(
+    const url::Origin& origin) const {
+  const auto iter = database_.find(SerializeOriginIntoDatabaseKey(origin));
+  if (iter == database_.end())
+    return OriginInterventions::DEFAULT;
+  return iter->second.discarding_policy;
+}
+
+InterventionPolicyDatabase::InterventionPolicy
+InterventionPolicyDatabase::GetFreezingPolicy(const url::Origin& origin) const {
+  const auto iter = database_.find(SerializeOriginIntoDatabaseKey(origin));
+  if (iter == database_.end())
+    return OriginInterventions::DEFAULT;
+  return iter->second.freezing_policy;
+}
+
+void InterventionPolicyDatabase::InitializeDatabaseWithProtoFile(
+    const base::FilePath& proto_location,
+    const base::Version& version,
+    std::unique_ptr<base::DictionaryValue> manifest) {
+  // TODO(sebmarchand): Validate the version and the manifest?
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()},
+      base::BindOnce(
+          &InterventionPolicyDatabase::ReadDatabaseFromProtoFileOnSequence,
+          proto_location),
+      base::BindOnce(&InterventionPolicyDatabase::OnReadDatabaseProtoFromFile,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void InterventionPolicyDatabase::AddOriginPoliciesForTesting(
+    const url::Origin& origin,
+    OriginInterventionPolicies policies) {
+  database_.emplace(SerializeOriginIntoDatabaseKey(origin),
+                    std::move(policies));
+}
+
+// static
+InterventionPolicyDatabase::InterventionsMap
+InterventionPolicyDatabase::ReadDatabaseFromProtoFileOnSequence(
+    const base::FilePath& proto_location) {
+  DCHECK(base::PathExists(proto_location));
+
+  InterventionsMap database;
+
+  std::string proto_str;
+  if (!base::ReadFileToString(proto_location, &proto_str)) {
+    DLOG(ERROR) << "Failed to read the interventon policy database.";
+    return database;
+  }
+
+  OriginInterventionsDatabase proto;
+  if (!proto.ParseFromString(proto_str)) {
+    DLOG(ERROR) << "Unable to parse the intervention policy database proto.";
+    return database;
+  }
+
+  database.reserve(proto.origin_interventions_size());
+  for (int i = 0; i < proto.origin_interventions_size(); ++i) {
+    const OriginInterventions& origin_interventions_proto =
+        proto.origin_interventions(i);
+    OriginInterventionPolicies origin_intervention_policies(
+        origin_interventions_proto.discarding_policy(),
+        origin_interventions_proto.freezing_policy());
+    database.emplace(origin_interventions_proto.host_hash(),
+                     std::move(origin_intervention_policies));
+  }
+  return database;
+}
+
+void InterventionPolicyDatabase::OnReadDatabaseProtoFromFile(
+    InterventionsMap database) {
+  database_ = std::move(database);
+}
+
+}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/intervention_policy_database.h b/chrome/browser/resource_coordinator/intervention_policy_database.h
new file mode 100644
index 0000000..42b9df1
--- /dev/null
+++ b/chrome/browser/resource_coordinator/intervention_policy_database.h
@@ -0,0 +1,85 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_INTERVENTION_POLICY_DATABASE_H_
+#define CHROME_BROWSER_RESOURCE_COORDINATOR_INTERVENTION_POLICY_DATABASE_H_
+
+#include "base/containers/flat_map.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/version.h"
+#include "chrome/browser/resource_coordinator/intervention_policy_database.pb.h"
+#include "url/origin.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace resource_coordinator {
+
+// Intervention policy database, this should receive data from the
+// InterventionPolicyDatabaseComponentInstallerPolicy component once it's ready.
+//
+// It is meant to be used to assist intervention decisions made for the
+// LifecycleUnits.
+class InterventionPolicyDatabase {
+ public:
+  using InterventionPolicy = OriginInterventions::InterventionPolicy;
+
+  // The intervention policies to use for a given origin.
+  struct OriginInterventionPolicies {
+    OriginInterventionPolicies(InterventionPolicy discarding_policy,
+                               InterventionPolicy freezing_policy);
+
+    InterventionPolicy discarding_policy;
+    InterventionPolicy freezing_policy;
+  };
+
+  InterventionPolicyDatabase();
+  ~InterventionPolicyDatabase();
+
+  InterventionPolicy GetDiscardingPolicy(const url::Origin& origin) const;
+  InterventionPolicy GetFreezingPolicy(const url::Origin& origin) const;
+
+  // Initialize the database with the OriginInterventionsDatabase protobuf
+  // stored in |proto_location|.
+  void InitializeDatabaseWithProtoFile(
+      const base::FilePath& proto_location,
+      const base::Version& version,
+      std::unique_ptr<base::DictionaryValue> manifest);
+
+  void AddOriginPoliciesForTesting(const url::Origin& origin,
+                                   OriginInterventionPolicies policies);
+
+ protected:
+  // Map that associates the MD5 hash of an origin to its polices.
+  using InterventionsMap =
+      base::flat_map<std::string, OriginInterventionPolicies>;
+
+  friend class InterventionPolicyDatabaseTest;
+
+  const InterventionsMap& database_for_testing() { return database_; }
+
+ private:
+  // Asynchronously initialize an |InterventionsMap| object with the content of
+  // the OriginInterventionsDatabase proto stored at |proto_location|.
+  static InterventionsMap ReadDatabaseFromProtoFileOnSequence(
+      const base::FilePath& proto_location);
+
+  // Needs to be called to initialize |database_| with the data read in
+  // InitializeDatabaseWithProtoAsync.
+  void OnReadDatabaseProtoFromFile(InterventionsMap database);
+
+  // The map that stores all the per-origin intervention policies.
+  InterventionsMap database_;
+
+  base::WeakPtrFactory<InterventionPolicyDatabase> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(InterventionPolicyDatabase);
+};
+
+}  // namespace resource_coordinator
+
+#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_INTERVENTION_POLICY_DATABASE_H_
diff --git a/chrome/browser/resource_coordinator/intervention_policy_database.proto b/chrome/browser/resource_coordinator/intervention_policy_database.proto
new file mode 100644
index 0000000..876952e
--- /dev/null
+++ b/chrome/browser/resource_coordinator/intervention_policy_database.proto
@@ -0,0 +1,31 @@
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+// Information about an origin and the intervention it supports.
+// Next Id: 4
+message OriginInterventions {
+  // The MD5 hash of the origin, the value used to generate this hash
+  // should be the ‘host’ part of the origin, e.g. in
+  // “http://example.com/foo” the host is “example.com”.
+  required string host_hash = 1;
+
+  // Policy associated with an intervention. A DEFAULT value indicates
+  // that the existing heuristics should be applied.
+  enum InterventionPolicy {
+    OPT_IN = 0;
+    OPT_OUT = 1;
+    DEFAULT = 2;
+  }
+  // The discarding policy.
+  required InterventionPolicy discarding_policy = 2;
+  // The freezing policy.
+  required InterventionPolicy freezing_policy = 3;
+}
+
+// The database that contains all the origins and the interventions they
+// support.
+// Next Id: 2
+message OriginInterventionsDatabase {
+  repeated OriginInterventions origin_interventions = 1;
+}
diff --git a/chrome/browser/resource_coordinator/intervention_policy_database_unittest.cc b/chrome/browser/resource_coordinator/intervention_policy_database_unittest.cc
new file mode 100644
index 0000000..cb7c389d
--- /dev/null
+++ b/chrome/browser/resource_coordinator/intervention_policy_database_unittest.cc
@@ -0,0 +1,105 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
+
+#include <map>
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "base/values.h"
+#include "chrome/browser/resource_coordinator/intervention_policy_database.pb.h"
+#include "chrome/browser/resource_coordinator/utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace resource_coordinator {
+
+namespace {
+
+using InterventionPolicy = InterventionPolicyDatabase::InterventionPolicy;
+using OriginInterventionPolicies =
+    InterventionPolicyDatabase::OriginInterventionPolicies;
+
+// Initialize a protobuf in |path| with the content of |data_map|.
+void WriteProtoToFile(
+    const base::FilePath& path,
+    std::map<url::Origin, OriginInterventionPolicies> data_map) {
+  OriginInterventionsDatabase proto;
+
+  for (const auto& iter : data_map) {
+    OriginInterventions* origin_interventions =
+        proto.add_origin_interventions();
+    EXPECT_TRUE(origin_interventions);
+    origin_interventions->set_host_hash(
+        SerializeOriginIntoDatabaseKey(iter.first));
+    origin_interventions->set_discarding_policy(iter.second.discarding_policy);
+    origin_interventions->set_freezing_policy(iter.second.freezing_policy);
+  }
+  std::string serialized_proto;
+  EXPECT_TRUE(proto.SerializeToString(&serialized_proto));
+  EXPECT_EQ(static_cast<int>(serialized_proto.length()),
+            base::WriteFile(path, serialized_proto.c_str(),
+                            serialized_proto.length()));
+}
+
+}  // namespace
+
+class InterventionPolicyDatabaseTest : public ::testing::Test {
+ protected:
+  InterventionPolicyDatabaseTest() = default;
+
+  void WaitForDatabaseToBeInitialized() {
+    while (intervention_policy_database_.database_for_testing().empty())
+      test_env_.RunUntilIdle();
+  }
+
+  InterventionPolicyDatabase* GetDatabase() {
+    return &intervention_policy_database_;
+  }
+
+ private:
+  base::test::TaskEnvironment test_env_;
+  InterventionPolicyDatabase intervention_policy_database_;
+};
+
+TEST_F(InterventionPolicyDatabaseTest, EndToEnd) {
+  base::ScopedTempDir temp_dir;
+  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath proto_path;
+  EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &proto_path));
+
+  std::map<url::Origin, OriginInterventionPolicies> policy_map;
+  policy_map.emplace(url::Origin::Create(GURL("https://a.com")),
+                     OriginInterventionPolicies(OriginInterventions::OPT_IN,
+                                                OriginInterventions::OPT_IN));
+  policy_map.emplace(url::Origin::Create(GURL("https://b.com")),
+                     OriginInterventionPolicies(OriginInterventions::OPT_IN,
+                                                OriginInterventions::OPT_OUT));
+  policy_map.emplace(url::Origin::Create(GURL("https://c.com")),
+                     OriginInterventionPolicies(OriginInterventions::OPT_OUT,
+                                                OriginInterventions::OPT_OUT));
+  policy_map.emplace(url::Origin::Create(GURL("https://d.com")),
+                     OriginInterventionPolicies(OriginInterventions::OPT_IN,
+                                                OriginInterventions::DEFAULT));
+  WriteProtoToFile(proto_path, policy_map);
+
+  GetDatabase()->InitializeDatabaseWithProtoFile(proto_path, base::Version(),
+                                                 nullptr);
+
+  WaitForDatabaseToBeInitialized();
+
+  for (const auto& iter : policy_map) {
+    EXPECT_EQ(iter.second.discarding_policy,
+              GetDatabase()->GetDiscardingPolicy(iter.first));
+    EXPECT_EQ(iter.second.freezing_policy,
+              GetDatabase()->GetFreezingPolicy(iter.first));
+  }
+}
+
+}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_parts.cc b/chrome/browser/resource_coordinator/resource_coordinator_parts.cc
index 577b26d..7273896 100644
--- a/chrome/browser/resource_coordinator/resource_coordinator_parts.cc
+++ b/chrome/browser/resource_coordinator/resource_coordinator_parts.cc
@@ -11,7 +11,8 @@
 ResourceCoordinatorParts::ResourceCoordinatorParts()
 #if !defined(OS_ANDROID)
     : tab_manager_(&tab_load_tracker_),
-      tab_lifecycle_unit_source_(tab_manager_.usage_clock())
+      tab_lifecycle_unit_source_(tab_manager_.intervention_policy_database(),
+                                 tab_manager_.usage_clock())
 #endif
 {
 #if !defined(OS_ANDROID)
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index 9cf5370..18583cd8 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/permissions/permission_manager.h"
 #include "chrome/browser/permissions/permission_result.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h"
 #include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
@@ -572,6 +573,10 @@
   if (web_contents()->GetVisibility() == content::Visibility::VISIBLE)
     decision_details->AddReason(DecisionFailureReason::LIVE_STATE_VISIBLE);
 
+  // Check the freezing intervention policy database. Tabs that have opted-in
+  // will be marked as freezable regardless of the other heuristics.
+  CheckFreezingInterventionPolicyDatabase(decision_details);
+
   // Do not freeze tabs using media, irrespective of any opt-in, as this usually
   // breaks functionality.
   CheckMediaUsage(decision_details);
@@ -1078,6 +1083,26 @@
   }
 }
 
+void TabLifecycleUnitSource::TabLifecycleUnit::
+    CheckFreezingInterventionPolicyDatabase(
+        DecisionDetails* decision_details) const {
+  // Apply intervention database opt-in/opt-out (policy is per origin).
+  auto intervention_policy =
+      GetTabSource()->intervention_policy_database()->GetFreezingPolicy(
+          url::Origin::Create(web_contents()->GetLastCommittedURL()));
+
+  switch (intervention_policy) {
+    case OriginInterventions::OPT_IN:
+      decision_details->AddReason(DecisionSuccessReason::GLOBAL_WHITELIST);
+      break;
+    case OriginInterventions::OPT_OUT:
+      decision_details->AddReason(DecisionFailureReason::GLOBAL_BLACKLIST);
+      break;
+    case OriginInterventions::DEFAULT:
+      break;
+  }
+}
+
 LifecycleUnitDiscardReason
 TabLifecycleUnitSource::TabLifecycleUnit::GetDiscardReason() const {
   return discard_reason_;
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
index cf37c74b..c5f3130 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
@@ -185,6 +185,11 @@
   // for the tab.
   void CheckFreezingOriginTrial(DecisionDetails* decision_details) const;
 
+  // Updates |decision_details| based on the global intervention policy database
+  // freezing data for the tab.
+  void CheckFreezingInterventionPolicyDatabase(
+      DecisionDetails* decision_details) const;
+
   // List of observers to notify when the discarded state or the auto-
   // discardable state of this tab changes.
   base::ObserverList<TabLifecycleObserver>::Unchecked* observers_;
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
index 2afe2ba0..7085f93 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
@@ -173,12 +173,16 @@
 };
 
 TabLifecycleUnitSource::TabLifecycleUnitSource(
+    InterventionPolicyDatabase* intervention_policy_database,
     UsageClock* usage_clock)
     : browser_tab_strip_tracker_(this, nullptr, this),
+      intervention_policy_database_(intervention_policy_database),
       usage_clock_(usage_clock) {
   // In unit tests, tabs might already exist when TabLifecycleUnitSource is
   // instantiated. No TabLifecycleUnit is created for these tabs.
 
+  DCHECK(intervention_policy_database_);
+
   browser_tab_strip_tracker_.Init();
 }
 
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
index a60d2dd..72e1610 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
@@ -28,6 +28,7 @@
 
 namespace resource_coordinator {
 
+class InterventionPolicyDatabase;
 class TabFreezingEnabledPreferenceMonitor;
 class TabLifecycleObserver;
 class TabLifecycleStateObserver;
@@ -43,6 +44,7 @@
   class LifecycleStateObserver;
 
   TabLifecycleUnitSource(
+      InterventionPolicyDatabase* intervention_policy_database,
       UsageClock* usage_clock);
   ~TabLifecycleUnitSource() override;
 
@@ -63,6 +65,10 @@
   // Pretend that |tab_strip| is the TabStripModel of the focused window.
   void SetFocusedTabStripModelForTesting(TabStripModel* tab_strip);
 
+  InterventionPolicyDatabase* intervention_policy_database() const {
+    return intervention_policy_database_;
+  }
+
   // Returns the state of the tab lifecycles feature enterprise control. This
   // returns true if the feature should be enabled, false otherwise.
   bool tab_lifecycles_enterprise_policy() const {
@@ -187,6 +193,10 @@
   // changes.
   base::ObserverList<TabLifecycleObserver>::Unchecked tab_lifecycle_observers_;
 
+  // The intervention policy database used to assist freezing/discarding
+  // decisions.
+  InterventionPolicyDatabase* intervention_policy_database_;
+
   // A clock that advances when Chrome is in use.
   UsageClock* const usage_clock_;
 
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
index ef2d0c5..043caa9 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
 #include "chrome/browser/notifications/notification_permission_context.h"
 #include "chrome/browser/permissions/permission_request_manager.h"
+#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h"
@@ -609,6 +610,47 @@
       DecisionFailureReason::HEURISTIC_INSUFFICIENT_OBSERVATION, nullptr);
 }
 
+TEST_F(TabLifecycleUnitTest, CannotFreezeTabIfOriginOptedOut) {
+  auto* policy_db = GetTabLifecycleUnitSource()->intervention_policy_database();
+  policy_db->AddOriginPoliciesForTesting(
+      url::Origin::Create(web_contents_->GetLastCommittedURL()),
+      InterventionPolicyDatabase::OriginInterventionPolicies(
+          OriginInterventions::DEFAULT, OriginInterventions::OPT_OUT));
+
+  TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
+                                      usage_clock_.get(), web_contents_,
+                                      tab_strip_model_.get());
+  TabLoadTracker::Get()->TransitionStateForTesting(web_contents_,
+                                                   LoadingState::LOADED);
+  DecisionDetails decision_details;
+  EXPECT_FALSE(tab_lifecycle_unit.CanFreeze(&decision_details));
+  EXPECT_FALSE(decision_details.IsPositive());
+  EXPECT_EQ(DecisionFailureReason::GLOBAL_BLACKLIST,
+            decision_details.FailureReason());
+}
+
+TEST_F(TabLifecycleUnitTest, CanFreezeOptedInTabs) {
+  auto* policy_db = GetTabLifecycleUnitSource()->intervention_policy_database();
+  policy_db->AddOriginPoliciesForTesting(
+      url::Origin::Create(web_contents_->GetLastCommittedURL()),
+      {OriginInterventions::DEFAULT, OriginInterventions::OPT_IN});
+
+  TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
+                                      usage_clock_.get(), web_contents_,
+                                      tab_strip_model_.get());
+  TabLoadTracker::Get()->TransitionStateForTesting(web_contents_,
+                                                   LoadingState::LOADED);
+
+  // Mark the tab as recently audible, this should protect it from being frozen.
+  tab_lifecycle_unit.SetRecentlyAudible(true);
+
+  DecisionDetails decision_details;
+  EXPECT_TRUE(tab_lifecycle_unit.CanFreeze(&decision_details));
+  EXPECT_TRUE(decision_details.IsPositive());
+  EXPECT_EQ(DecisionSuccessReason::GLOBAL_WHITELIST,
+            decision_details.SuccessReason());
+}
+
 TEST_F(TabLifecycleUnitTest, CannotFreezeAFrozenTab) {
   TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
                                       usage_clock_.get(), web_contents_,
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc
index 2fa13cd..ee566a8 100644
--- a/chrome/browser/resource_coordinator/tab_manager.cc
+++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -169,6 +169,7 @@
   proactive_freeze_discard_params_ =
       GetStaticProactiveTabFreezeAndDiscardParams();
   tab_load_tracker_->AddObserver(this);
+  intervention_policy_database_.reset(new InterventionPolicyDatabase());
 
   // TabManager works in the absence of DesktopSessionDurationTracker for tests.
   if (metrics::DesktopSessionDurationTracker::IsInitialized())
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h
index 7722635..1ee8f74 100644
--- a/chrome/browser/resource_coordinator/tab_manager.h
+++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -19,6 +19,7 @@
 #include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
+#include "chrome/browser/resource_coordinator/intervention_policy_database.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_source_observer.h"
@@ -152,6 +153,10 @@
   // non-zero only during session restore.
   int restored_tab_count() const { return restored_tab_count_; }
 
+  InterventionPolicyDatabase* intervention_policy_database() {
+    return intervention_policy_database_.get();
+  }
+
   UsageClock* usage_clock() { return &usage_clock_; }
 
   // Returns true if the tab was created by session restore and has not finished
@@ -470,6 +475,10 @@
   // session restore.
   std::unique_ptr<TabManagerStatsCollector> stats_collector_;
 
+  // The intervention policy database, should be initialized by
+  // InterventionPolicyDatabaseComponentInstallerPolicy.
+  std::unique_ptr<InterventionPolicyDatabase> intervention_policy_database_;
+
   // Last time at which a LifecycleUnit was temporarily unfrozen.
   base::TimeTicks last_unfreeze_time_;
 
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn b/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn
index 0d27180..314b9cb 100644
--- a/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn
+++ b/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn
@@ -39,7 +39,5 @@
 }
 
 group("polymer3_elements") {
-  deps = [
-    ":app_module",
-  ]
+  deps = [ ":app_module" ]
 }
diff --git a/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn b/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
index 6d581242..f899962 100644
--- a/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
+++ b/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
@@ -18,9 +18,7 @@
 }
 
 js_type_check("closure_compile") {
-  deps = [
-    ":internet_config_dialog",
-  ]
+  deps = [ ":internet_config_dialog" ]
 }
 
 js_library("internet_config_dialog") {
diff --git a/chrome/browser/resources/conflicts/BUILD.gn b/chrome/browser/resources/conflicts/BUILD.gn
index 3e55232..a993915 100644
--- a/chrome/browser/resources/conflicts/BUILD.gn
+++ b/chrome/browser/resources/conflicts/BUILD.gn
@@ -6,9 +6,7 @@
 
 js_type_check("closure_compile") {
   uses_js_modules = true
-  deps = [
-    ":about_conflicts",
-  ]
+  deps = [ ":about_conflicts" ]
 }
 
 js_library("about_conflicts") {
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn
index 0acf118..5118959 100644
--- a/chrome/browser/resources/pdf/BUILD.gn
+++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -18,9 +18,7 @@
 }
 
 js_library("browser_api") {
-  deps = [
-    "//ui/webui/resources/js:assert.m",
-  ]
+  deps = [ "//ui/webui/resources/js:assert.m" ]
   externs_list = [
     "$externs_path/chrome_extensions.js",
     "$externs_path/mime_handler_private.js",
@@ -34,9 +32,7 @@
 }
 
 js_library("open_pdf_params_parser") {
-  deps = [
-    ":pdf_fitting_type",
-  ]
+  deps = [ ":pdf_fitting_type" ]
 }
 
 js_library("pdf_scripting_api") {
@@ -65,9 +61,7 @@
 }
 
 js_library("metrics") {
-  deps = [
-    ":pdf_fitting_type",
-  ]
+  deps = [ ":pdf_fitting_type" ]
   externs_list = [ "$externs_path/metrics_private.js" ]
 }
 
diff --git a/chrome/browser/resources/pdf/elements/BUILD.gn b/chrome/browser/resources/pdf/elements/BUILD.gn
index 1ffa844..b8841ba4 100644
--- a/chrome/browser/resources/pdf/elements/BUILD.gn
+++ b/chrome/browser/resources/pdf/elements/BUILD.gn
@@ -34,9 +34,7 @@
 }
 
 js_library("viewer-error-screen") {
-  deps = [
-    "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
-  ]
+  deps = [ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m" ]
 }
 
 if (is_chromeos) {
@@ -64,15 +62,11 @@
 }
 
 js_library("viewer-page-selector") {
-  deps = [
-    "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
-  ]
+  deps = [ "//ui/webui/resources/cr_elements/cr_input:cr_input.m" ]
 }
 
 js_library("viewer-password-screen") {
-  deps = [
-    "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
-  ]
+  deps = [ "//ui/webui/resources/cr_elements/cr_input:cr_input.m" ]
 }
 
 js_library("viewer-pdf-toolbar") {
diff --git a/chrome/browser/resources/pdf/ink/BUILD.gn b/chrome/browser/resources/pdf/ink/BUILD.gn
index b1c2be2..ddf46dc4 100644
--- a/chrome/browser/resources/pdf/ink/BUILD.gn
+++ b/chrome/browser/resources/pdf/ink/BUILD.gn
@@ -5,15 +5,11 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":ink_api",
-  ]
+  deps = [ ":ink_api" ]
 }
 
 js_library("ink_api") {
-  deps = [
-    "..:annotation_tool",
-  ]
+  deps = [ "..:annotation_tool" ]
   externs_list = [
     "//third_party/ink/build/ink_lib_externs.js",
     "$externs_path/pending.js",
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 93ccfaba..973a2a6 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -30,18 +30,14 @@
     ]
     excludes = [ "chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html" ]
 
-    deps = [
-      ":unpak",
-    ]
+    deps = [ ":unpak" ]
   }
 
   unpak("unpak") {
     pak_file = settings_pak_file
     out_folder = unpak_folder
 
-    deps = [
-      ":flattened_resources",
-    ]
+    deps = [ ":flattened_resources" ]
   }
 
   grit("flattened_resources") {
@@ -137,16 +133,12 @@
 }
 
 js_library("lifetime_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
 js_library("open_window_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("route") {
diff --git a/chrome/browser/resources/settings/a11y_page/BUILD.gn b/chrome/browser/resources/settings/a11y_page/BUILD.gn
index 4ea0b75..0c60419 100644
--- a/chrome/browser/resources/settings/a11y_page/BUILD.gn
+++ b/chrome/browser/resources/settings/a11y_page/BUILD.gn
@@ -32,7 +32,5 @@
 }
 
 js_library("captions_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
diff --git a/chrome/browser/resources/settings/about_page/BUILD.gn b/chrome/browser/resources/settings/about_page/BUILD.gn
index 783647a..d067447 100644
--- a/chrome/browser/resources/settings/about_page/BUILD.gn
+++ b/chrome/browser/resources/settings/about_page/BUILD.gn
@@ -24,8 +24,6 @@
 }
 
 js_library("about_page_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
diff --git a/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chrome/browser/resources/settings/autofill_page/BUILD.gn
index 1afa9c4..c143705 100644
--- a/chrome/browser/resources/settings/autofill_page/BUILD.gn
+++ b/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -77,9 +77,7 @@
 }
 
 js_library("credit_card_edit_dialog") {
-  deps = [
-    "//ui/webui/resources/js:i18n_behavior",
-  ]
+  deps = [ "//ui/webui/resources/js:i18n_behavior" ]
   externs_list = [ "$externs_path/autofill_private.js" ]
 }
 
@@ -91,9 +89,7 @@
 }
 
 js_library("credit_card_list_entry") {
-  deps = [
-    "//ui/webui/resources/js:i18n_behavior",
-  ]
+  deps = [ "//ui/webui/resources/js:i18n_behavior" ]
 }
 
 js_library("password_list_item") {
@@ -105,9 +101,7 @@
 }
 
 js_library("password_manager_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/passwords_private.js" ]
 }
 
@@ -140,8 +134,6 @@
 }
 
 js_library("show_password_behavior") {
-  deps = [
-    ":blocking_request_manager",
-  ]
+  deps = [ ":blocking_request_manager" ]
   externs_list = [ "$externs_path/passwords_private.js" ]
 }
diff --git a/chrome/browser/resources/settings/basic_page/BUILD.gn b/chrome/browser/resources/settings/basic_page/BUILD.gn
index 9a638da..a2d6e28 100644
--- a/chrome/browser/resources/settings/basic_page/BUILD.gn
+++ b/chrome/browser/resources/settings/basic_page/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":basic_page",
-  ]
+  deps = [ ":basic_page" ]
 }
 
 js_library("basic_page") {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
index 7bd433c..3f12898 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":os_settings_main",
-  ]
+  deps = [ ":os_settings_main" ]
 }
 
 js_library("os_settings_main") {
diff --git a/chrome/browser/resources/settings/controls/BUILD.gn b/chrome/browser/resources/settings/controls/BUILD.gn
index 7baf0b5..b0c95ad 100644
--- a/chrome/browser/resources/settings/controls/BUILD.gn
+++ b/chrome/browser/resources/settings/controls/BUILD.gn
@@ -59,9 +59,7 @@
 }
 
 js_library("pref_control_behavior") {
-  deps = [
-    "../prefs:prefs_types",
-  ]
+  deps = [ "../prefs:prefs_types" ]
 }
 
 js_library("settings_boolean_control_behavior") {
@@ -74,9 +72,7 @@
 }
 
 js_library("settings_checkbox") {
-  deps = [
-    ":settings_boolean_control_behavior",
-  ]
+  deps = [ ":settings_boolean_control_behavior" ]
 }
 
 js_library("settings_dropdown_menu") {
diff --git a/chrome/browser/resources/settings/default_browser_page/BUILD.gn b/chrome/browser/resources/settings/default_browser_page/BUILD.gn
index efe93f1..be47a84 100644
--- a/chrome/browser/resources/settings/default_browser_page/BUILD.gn
+++ b/chrome/browser/resources/settings/default_browser_page/BUILD.gn
@@ -12,9 +12,7 @@
 }
 
 js_library("default_browser_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("default_browser_page") {
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn b/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn
index 78dfe00d..7d974d0 100644
--- a/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn
+++ b/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn
@@ -13,9 +13,7 @@
 }
 
 js_library("incompatible_applications_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("incompatible_applications_page") {
diff --git a/chrome/browser/resources/settings/languages_page/BUILD.gn b/chrome/browser/resources/settings/languages_page/BUILD.gn
index 8bc3523..fc4231d 100644
--- a/chrome/browser/resources/settings/languages_page/BUILD.gn
+++ b/chrome/browser/resources/settings/languages_page/BUILD.gn
@@ -15,9 +15,7 @@
 }
 
 js_library("languages_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [
     "$externs_path/chrome_send.js",
     "$externs_path/input_method_private.js",
diff --git a/chrome/browser/resources/settings/people_page/BUILD.gn b/chrome/browser/resources/settings/people_page/BUILD.gn
index 78ed0b375..901cfd9a 100644
--- a/chrome/browser/resources/settings/people_page/BUILD.gn
+++ b/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -29,15 +29,11 @@
 }
 
 js_library("account_manager_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("import_data_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("manage_profile") {
@@ -79,9 +75,7 @@
 }
 
 js_library("profile_info_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("signout_dialog") {
diff --git a/chrome/browser/resources/settings/prefs/BUILD.gn b/chrome/browser/resources/settings/prefs/BUILD.gn
index 6f61f794..f73bf6a 100644
--- a/chrome/browser/resources/settings/prefs/BUILD.gn
+++ b/chrome/browser/resources/settings/prefs/BUILD.gn
@@ -14,9 +14,7 @@
 }
 
 js_library("pref_util") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/settings_private.js" ]
 }
 
@@ -32,9 +30,7 @@
 }
 
 js_library("prefs_behavior") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
   externs_list = [ "$externs_path/settings_private.js" ]
 }
 
diff --git a/chrome/browser/resources/settings/printing_page/BUILD.gn b/chrome/browser/resources/settings/printing_page/BUILD.gn
index 8382d4b..d035eda 100644
--- a/chrome/browser/resources/settings/printing_page/BUILD.gn
+++ b/chrome/browser/resources/settings/printing_page/BUILD.gn
@@ -16,15 +16,11 @@
 }
 
 js_library("cloud_printers") {
-  deps = [
-    "//ui/webui/resources/js:load_time_data",
-  ]
+  deps = [ "//ui/webui/resources/js:load_time_data" ]
 }
 
 js_library("printing_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("printing_page") {
diff --git a/chrome/browser/resources/settings/privacy_page/BUILD.gn b/chrome/browser/resources/settings/privacy_page/BUILD.gn
index 64f9d06..7a83433 100644
--- a/chrome/browser/resources/settings/privacy_page/BUILD.gn
+++ b/chrome/browser/resources/settings/privacy_page/BUILD.gn
@@ -71,9 +71,7 @@
 }
 
 js_library("security_keys_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
@@ -97,9 +95,7 @@
 }
 
 js_library("security_keys_pin_field") {
-  deps = [
-    "//ui/webui/resources/js:i18n_behavior",
-  ]
+  deps = [ "//ui/webui/resources/js:i18n_behavior" ]
 }
 
 js_library("security_keys_credential_management_dialog") {
diff --git a/chrome/browser/resources/settings/reset_page/BUILD.gn b/chrome/browser/resources/settings/reset_page/BUILD.gn
index 63958580..6cb48806 100644
--- a/chrome/browser/resources/settings/reset_page/BUILD.gn
+++ b/chrome/browser/resources/settings/reset_page/BUILD.gn
@@ -25,9 +25,7 @@
 }
 
 js_library("reset_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
diff --git a/chrome/browser/resources/settings/search_page/BUILD.gn b/chrome/browser/resources/settings/search_page/BUILD.gn
index 6eeb409..2dc01e4 100644
--- a/chrome/browser/resources/settings/search_page/BUILD.gn
+++ b/chrome/browser/resources/settings/search_page/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":search_page",
-  ]
+  deps = [ ":search_page" ]
 }
 
 js_library("search_page") {
diff --git a/chrome/browser/resources/settings/settings_main/BUILD.gn b/chrome/browser/resources/settings/settings_main/BUILD.gn
index c4eddc9..27ab689 100644
--- a/chrome/browser/resources/settings/settings_main/BUILD.gn
+++ b/chrome/browser/resources/settings/settings_main/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":settings_main",
-  ]
+  deps = [ ":settings_main" ]
 }
 
 js_library("settings_main") {
diff --git a/chrome/browser/resources/settings/settings_menu/BUILD.gn b/chrome/browser/resources/settings/settings_menu/BUILD.gn
index d138e44..61674b7 100644
--- a/chrome/browser/resources/settings/settings_menu/BUILD.gn
+++ b/chrome/browser/resources/settings/settings_menu/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":settings_menu",
-  ]
+  deps = [ ":settings_menu" ]
 }
 
 js_library("settings_menu") {
diff --git a/chrome/browser/resources/settings/settings_ui/BUILD.gn b/chrome/browser/resources/settings/settings_ui/BUILD.gn
index 5352040..ec6c264 100644
--- a/chrome/browser/resources/settings/settings_ui/BUILD.gn
+++ b/chrome/browser/resources/settings/settings_ui/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":settings_ui",
-  ]
+  deps = [ ":settings_ui" ]
 }
 
 js_library("settings_ui") {
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn
index 24113bc..17656992 100644
--- a/chrome/browser/resources/settings/site_settings/BUILD.gn
+++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -55,9 +55,7 @@
 }
 
 js_library("android_info_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
@@ -106,9 +104,7 @@
 }
 
 js_library("constants") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("local_data_browser_proxy") {
@@ -131,9 +127,7 @@
 }
 
 js_library("cookie_info") {
-  deps = [
-    "//ui/webui/resources/js:load_time_data",
-  ]
+  deps = [ "//ui/webui/resources/js:load_time_data" ]
 }
 
 js_library("protocol_handlers") {
@@ -281,9 +275,7 @@
 }
 
 js_library("website_usage_private_api") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
diff --git a/chrome/browser/resources/settings/site_settings_page/BUILD.gn b/chrome/browser/resources/settings/site_settings_page/BUILD.gn
index 7467e9e0..ac27ac9 100644
--- a/chrome/browser/resources/settings/site_settings_page/BUILD.gn
+++ b/chrome/browser/resources/settings/site_settings_page/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":site_settings_page",
-  ]
+  deps = [ ":site_settings_page" ]
 }
 
 js_library("site_settings_page") {
diff --git a/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn b/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn
index 1d1d09f0..6b3429d 100644
--- a/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn
+++ b/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn
@@ -16,18 +16,14 @@
   python_path_ssl =
       "$python_path_root/components/security_interstitials/content/"
 
-  inputs = [
-    input_filename,
-  ]
+  inputs = [ input_filename ]
 
   deps = [
     "//components/security_interstitials/content:proto",
     "//third_party/protobuf:py_proto",
   ]
 
-  outputs = [
-    "$output_dir/$output_basename",
-  ]
+  outputs = [ "$output_dir/$output_basename" ]
 
   args = [
     "-w",
diff --git a/chrome/browser/signin/signin_profile_attributes_updater.cc b/chrome/browser/signin/signin_profile_attributes_updater.cc
index 8a4bbea..a2acb3e 100644
--- a/chrome/browser/signin/signin_profile_attributes_updater.cc
+++ b/chrome/browser/signin/signin_profile_attributes_updater.cc
@@ -54,10 +54,7 @@
   CoreAccountInfo account_info =
       identity_manager_->GetUnconsentedPrimaryAccountInfo();
 
-  bool clear_profile =
-      account_info.IsEmpty() ||
-      (!base::FeatureList::IsEnabled(kPersistUPAInProfileInfoCache) &&
-       !identity_manager_->HasPrimaryAccount());
+  bool clear_profile = account_info.IsEmpty();
 
   if (account_info.gaia != entry->GetGAIAId() ||
       !gaia::AreEmailsSame(account_info.email,
@@ -116,10 +113,8 @@
 
 void SigninProfileAttributesUpdater::OnUnconsentedPrimaryAccountChanged(
     const CoreAccountInfo& unconsented_primary_account_info) {
-  if (identity_manager_->HasPrimaryAccount() ||
-      !base::FeatureList::IsEnabled(kPersistUPAInProfileInfoCache)) {
+  if (identity_manager_->HasPrimaryAccount())
     return;
-  }
 
   UpdateProfileAttributes();
 }
diff --git a/chrome/browser/sync/trusted_vault_client_android.cc b/chrome/browser/sync/trusted_vault_client_android.cc
index 6c53226..a8a068d 100644
--- a/chrome/browser/sync/trusted_vault_client_android.cc
+++ b/chrome/browser/sync/trusted_vault_client_android.cc
@@ -12,9 +12,9 @@
 #include "content/public/browser/browser_thread.h"
 
 TrustedVaultClientAndroid::OngoingFetchKeys::OngoingFetchKeys(
-    const std::string& gaia_id,
+    const CoreAccountInfo& account_info,
     base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> callback)
-    : gaia_id(gaia_id), callback(std::move(callback)) {}
+    : account_info(account_info), callback(std::move(callback)) {}
 
 TrustedVaultClientAndroid::OngoingFetchKeys::~OngoingFetchKeys() = default;
 
@@ -35,7 +35,7 @@
     const base::android::JavaParamRef<jobjectArray>& keys) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(ongoing_fetch_keys_) << "No ongoing FetchKeys() request";
-  DCHECK_EQ(ongoing_fetch_keys_->gaia_id,
+  DCHECK_EQ(ongoing_fetch_keys_->account_info.gaia,
             base::android::ConvertJavaStringToUTF8(env, gaia_id))
       << "User mismatch in FetchKeys() response";
 
@@ -73,7 +73,7 @@
 }
 
 void TrustedVaultClientAndroid::FetchKeys(
-    const std::string& gaia_id,
+    const CoreAccountInfo& account_info,
     base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!ongoing_fetch_keys_)
@@ -83,16 +83,16 @@
 
   // Store for later completion when Java invokes FetchKeysCompleted().
   ongoing_fetch_keys_ =
-      std::make_unique<OngoingFetchKeys>(gaia_id, std::move(cb));
+      std::make_unique<OngoingFetchKeys>(account_info, std::move(cb));
 
   JNIEnv* const env = base::android::AttachCurrentThread();
-  const base::android::ScopedJavaLocalRef<jstring> java_gaia_id =
-      base::android::ConvertUTF8ToJavaString(env, gaia_id);
+  const base::android::ScopedJavaLocalRef<jobject> java_account_info =
+      ConvertToJavaCoreAccountInfo(env, account_info);
 
   // Trigger the fetching keys from the implementation in Java, which will
   // eventually call FetchKeysCompleted().
   Java_TrustedVaultClient_fetchKeys(env, reinterpret_cast<intptr_t>(this),
-                                    java_gaia_id);
+                                    java_account_info);
 }
 
 void TrustedVaultClientAndroid::StoreKeys(
@@ -104,7 +104,7 @@
 }
 
 void TrustedVaultClientAndroid::MarkKeysAsStale(
-    const std::string& gaia_id,
+    const CoreAccountInfo& account_info,
     base::OnceCallback<void(bool)> cb) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(cb);
@@ -117,10 +117,10 @@
   ongoing_mark_keys_as_stale_ = std::move(cb);
 
   JNIEnv* const env = base::android::AttachCurrentThread();
-  const base::android::ScopedJavaLocalRef<jstring> java_gaia_id =
-      base::android::ConvertUTF8ToJavaString(env, gaia_id);
+  const base::android::ScopedJavaLocalRef<jobject> java_account_info =
+      ConvertToJavaCoreAccountInfo(env, account_info);
 
   // The Java implementation will eventually call MarkKeysAsStaleCompleted().
   Java_TrustedVaultClient_markKeysAsStale(env, reinterpret_cast<intptr_t>(this),
-                                          java_gaia_id);
+                                          java_account_info);
 }
diff --git a/chrome/browser/sync/trusted_vault_client_android.h b/chrome/browser/sync/trusted_vault_client_android.h
index 6f980d2..9ca98fea 100644
--- a/chrome/browser/sync/trusted_vault_client_android.h
+++ b/chrome/browser/sync/trusted_vault_client_android.h
@@ -13,6 +13,7 @@
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/callback.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/driver/trusted_vault_client.h"
 
 // JNI bridge for a Java implementation of the TrustedVaultClient interface,
@@ -48,25 +49,25 @@
   std::unique_ptr<Subscription> AddKeysChangedObserver(
       const base::RepeatingClosure& cb) override;
   void FetchKeys(
-      const std::string& gaia_id,
+      const CoreAccountInfo& account_info,
       base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb)
       override;
   void StoreKeys(const std::string& gaia_id,
                  const std::vector<std::vector<uint8_t>>& keys,
                  int last_key_version) override;
-  void MarkKeysAsStale(const std::string& gaia_id,
+  void MarkKeysAsStale(const CoreAccountInfo& account_info,
                        base::OnceCallback<void(bool)> cb) override;
 
  private:
   // Struct representing an in-flight FetchKeys() call invoked from C++.
   struct OngoingFetchKeys {
     OngoingFetchKeys(
-        const std::string& gaia_id,
+        const CoreAccountInfo& account_info,
         base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)>
             callback);
     ~OngoingFetchKeys();
 
-    const std::string gaia_id;
+    const CoreAccountInfo account_info;
     base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> callback;
   };
 
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
index 1f7a8a85..4b69a57 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
@@ -260,6 +260,19 @@
 
 void AppServiceAppWindowLauncherController::OnInstanceUpdate(
     const apps::InstanceUpdate& update) {
+  if (update.StateChanged() &&
+      update.State() == apps::InstanceState::kDestroyed) {
+    // For Chrome apps edge case, it could be added for the inactive users, and
+    // then removed. Since it is not registered we don't need to do anything
+    // anyways. As such, all which is left to do here is to get rid of our own
+    // reference.
+    WindowList::iterator it =
+        std::find(window_list_.begin(), window_list_.end(), update.Window());
+    if (it != window_list_.end())
+      window_list_.erase(it);
+    return;
+  }
+
   aura::Window* window = update.Window();
   if (!observed_windows_.IsObserving(window))
     return;
@@ -318,18 +331,6 @@
       aura_window_to_app_window_.erase(app_window_it);
     }
   }
-
-  if (update.StateChanged() &&
-      update.State() == apps::InstanceState::kDestroyed) {
-    // For Chrome apps edge case, it could be added for the inactive users, and
-    // then removed. Since it is not registered we don't need to do anything
-    // anyways. As such, all which is left to do here is to get rid of our own
-    // reference.
-    WindowList::iterator it =
-        std::find(window_list_.begin(), window_list_.end(), update.Window());
-    if (it != window_list_.end())
-      window_list_.erase(it);
-  }
 }
 
 void AppServiceAppWindowLauncherController::OnInstanceRegistryWillBeDestroyed(
diff --git a/chrome/browser/ui/ash/launcher/shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/shelf_context_menu.cc
index 17d59e7..d3e84f8d 100644
--- a/chrome/browser/ui/ash/launcher/shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/shelf_context_menu.cc
@@ -115,8 +115,13 @@
   if (command_id == ash::SWAP_WITH_NEXT ||
       command_id == ash::SWAP_WITH_PREVIOUS) {
     // Only show commands to reorder shelf items when ChromeVox is enabled.
-    return chromeos::AccessibilityManager::Get() &&
-           chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled();
+    if (!chromeos::AccessibilityManager::Get() ||
+        !chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
+      return false;
+    }
+    const ash::ShelfModel* model = controller_->shelf_model();
+    return model->CanSwap(model->ItemIndexByID(item_.id),
+                          /*with_next=*/command_id == ash::SWAP_WITH_NEXT);
   }
 
   DCHECK(command_id < ash::COMMAND_ID_COUNT);
diff --git a/chrome/browser/ui/libgtkui/BUILD.gn b/chrome/browser/ui/libgtkui/BUILD.gn
index b1b8e33..7b20289 100644
--- a/chrome/browser/ui/libgtkui/BUILD.gn
+++ b/chrome/browser/ui/libgtkui/BUILD.gn
@@ -84,9 +84,7 @@
     "//ui/strings",
     "//ui/views",
   ]
-  public_deps = [
-    "//chrome/browser:theme_properties",
-  ]
+  public_deps = [ "//chrome/browser:theme_properties" ]
 
   if (use_x11 || ozone_platform_x11) {
     sources += [
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 9868bf7..fef58eae 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -592,11 +592,11 @@
     history_ui_favicon_request_handler->GetFaviconImageForPageURL(
         url,
         base::BindOnce(&RecentTabsSubMenuModel::OnFaviconDataAvailable,
-                       weak_ptr_factory_.GetWeakPtr(), command_id),
+                       weak_ptr_factory_for_other_devices_tab_.GetWeakPtr(),
+                       command_id),
 
         favicon::HistoryUiFaviconRequestOrigin::kRecentTabs,
-        open_tabs ? open_tabs->GetIconUrlForPageUrl(url) : GURL(),
-        &other_devices_tab_cancelable_task_tracker_);
+        open_tabs ? open_tabs->GetIconUrlForPageUrl(url) : GURL());
   }
 }
 
@@ -650,7 +650,7 @@
   for (int index = count - 1; index > last_local_model_index_; --index)
     RemoveItemAt(index);
 
-  other_devices_tab_cancelable_task_tracker_.TryCancelAll();
+  weak_ptr_factory_for_other_devices_tab_.InvalidateWeakPtrs();
 
   other_devices_tab_navigation_items_.clear();
 }
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index 5a97528..911131f8 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -176,7 +176,6 @@
   int last_local_model_index_ = kHistorySeparatorIndex;
 
   base::CancelableTaskTracker local_tab_cancelable_task_tracker_;
-  base::CancelableTaskTracker other_devices_tab_cancelable_task_tracker_;
 
   // Time the menu is open for until a recent tab is selected.
   base::ElapsedTimer menu_opened_timer_;
@@ -189,6 +188,8 @@
       foreign_session_updated_subscription_;
 
   base::WeakPtrFactory<RecentTabsSubMenuModel> weak_ptr_factory_{this};
+  base::WeakPtrFactory<RecentTabsSubMenuModel>
+      weak_ptr_factory_for_other_devices_tab_{this};
 
   DISALLOW_COPY_AND_ASSIGN(RecentTabsSubMenuModel);
 };
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
index e4c9275..23d8173 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button_delegate.cc
@@ -57,12 +57,11 @@
                                  const gfx::Image& user_identity_image) {
   ProfileAttributesEntry* entry = GetProfileAttributesEntry(profile);
   DCHECK(entry);
-  // TODO(crbug.com/1012179): If kPersistUPAInProfileInfoCache feature is on, it
-  // should suffice to call entry->GetAvatarIcon(). For this to work well, this
-  // class needs to observe ProfileAttributesStorage instead of (or on top of)
-  // IdentityManager. Only then we can rely on |entry| being up to date (as the
-  // storage also observes IdentityManager so there's no guarantee on the order
-  // of notifications).
+  // TODO(crbug.com/1012179): it should suffice to call entry->GetAvatarIcon().
+  // For this to work well, this class needs to observe ProfileAttributesStorage
+  // instead of (or on top of) IdentityManager. Only then we can rely on |entry|
+  // being up to date (as the storage also observes IdentityManager so there's
+  // no guarantee on the order of notifications).
   if (entry->IsUsingGAIAPicture() && entry->GetGAIAPicture())
     return *entry->GetGAIAPicture();
 
diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc
index 0b8e995c..111fed9 100644
--- a/chrome/browser/ui/webui/favicon_source.cc
+++ b/chrome/browser/ui/webui/favicon_source.cc
@@ -165,10 +165,11 @@
     history_ui_favicon_request_handler->GetRawFaviconForPageURL(
         page_url, desired_size_in_pixel,
         base::BindOnce(&FaviconSource::OnFaviconDataAvailable,
-                       base::Unretained(this), std::move(callback), parsed),
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+                       parsed),
         favicon::FaviconRequestPlatform::kDesktop, parsed_history_ui_origin,
         /*icon_url_for_uma=*/
-        GURL(parsed.icon_url), &cancelable_task_tracker_);
+        GURL(parsed.icon_url));
   }
 }
 
diff --git a/chrome/browser/ui/webui/favicon_source.h b/chrome/browser/ui/webui/favicon_source.h
index c359595..b46bf39 100644
--- a/chrome/browser/ui/webui/favicon_source.h
+++ b/chrome/browser/ui/webui/favicon_source.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "components/favicon/core/favicon_service.h"
 #include "content/public/browser/url_data_source.h"
@@ -96,6 +97,8 @@
 
   base::CancelableTaskTracker cancelable_task_tracker_;
 
+  base::WeakPtrFactory<FaviconSource> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(FaviconSource);
 };
 
diff --git a/chrome/browser/ui/webui/favicon_source_unittest.cc b/chrome/browser/ui/webui/favicon_source_unittest.cc
index 43a30679..78f08ca 100644
--- a/chrome/browser/ui/webui/favicon_source_unittest.cc
+++ b/chrome/browser/ui/webui/favicon_source_unittest.cc
@@ -47,23 +47,21 @@
   MockHistoryUiFaviconRequestHandler() = default;
   ~MockHistoryUiFaviconRequestHandler() override = default;
 
-  MOCK_METHOD7(
+  MOCK_METHOD6(
       GetRawFaviconForPageURL,
       void(const GURL& page_url,
            int desired_size_in_pixel,
            favicon_base::FaviconRawBitmapCallback callback,
            favicon::FaviconRequestPlatform request_platform,
            favicon::HistoryUiFaviconRequestOrigin request_origin_for_uma,
-           const GURL& icon_url_for_uma,
-           base::CancelableTaskTracker* tracker));
+           const GURL& icon_url_for_uma));
 
-  MOCK_METHOD5(
+  MOCK_METHOD4(
       GetFaviconImageForPageURL,
       void(const GURL& page_url,
            favicon_base::FaviconImageCallback callback,
            favicon::HistoryUiFaviconRequestOrigin request_origin_for_uma,
-           const GURL& icon_url_for_uma,
-           base::CancelableTaskTracker* tracker));
+           const GURL& icon_url_for_uma));
 };
 
 class TestFaviconSource : public FaviconSource {
@@ -124,10 +122,10 @@
           return kDummyTaskId;
         });
     ON_CALL(*mock_history_ui_favicon_request_handler_,
-            GetRawFaviconForPageURL(_, _, _, _, _, _, _))
+            GetRawFaviconForPageURL(_, _, _, _, _, _))
         .WillByDefault([](auto, auto,
                           favicon_base::FaviconRawBitmapCallback callback, auto,
-                          auto, auto, auto) {
+                          auto, auto) {
           std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
         });
 
@@ -248,7 +246,7 @@
 
   EXPECT_CALL(
       *mock_history_ui_favicon_request_handler_,
-      GetRawFaviconForPageURL(GURL("https://www.google.com"), _, _, _, _, _, _))
+      GetRawFaviconForPageURL(GURL("https://www.google.com"), _, _, _, _, _))
       .Times(1);
 
   source()->StartDataRequest(
diff --git a/chrome/browser/ui/webui/interventions_internals/BUILD.gn b/chrome/browser/ui/webui/interventions_internals/BUILD.gn
index 424c3a9..cf7280f5 100644
--- a/chrome/browser/ui/webui/interventions_internals/BUILD.gn
+++ b/chrome/browser/ui/webui/interventions_internals/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "interventions_internals.mojom",
-  ]
+  sources = [ "interventions_internals.mojom" ]
 
-  public_deps = [
-    "//url/mojom:url_mojom_gurl",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/chrome/browser/ui/webui/new_tab_page/BUILD.gn b/chrome/browser/ui/webui/new_tab_page/BUILD.gn
index a7f3d9d3..e618c3e 100644
--- a/chrome/browser/ui/webui/new_tab_page/BUILD.gn
+++ b/chrome/browser/ui/webui/new_tab_page/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "new_tab_page.mojom",
-  ]
+  sources = [ "new_tab_page.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/chrome/browser/ui/webui/snippets_internals/BUILD.gn b/chrome/browser/ui/webui/snippets_internals/BUILD.gn
index f83f5c2..8981f583 100644
--- a/chrome/browser/ui/webui/snippets_internals/BUILD.gn
+++ b/chrome/browser/ui/webui/snippets_internals/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "snippets_internals.mojom",
-  ]
+  sources = [ "snippets_internals.mojom" ]
 }
diff --git a/chrome/chrome_elf/BUILD.gn b/chrome/chrome_elf/BUILD.gn
index 99ef4560..abd8ceba 100644
--- a/chrome/chrome_elf/BUILD.gn
+++ b/chrome/chrome_elf/BUILD.gn
@@ -15,25 +15,19 @@
 ##------------------------------------------------------------------------------
 
 process_version_rc_template("chrome_elf_resources") {
-  sources = [
-    "chrome_elf.ver",
-  ]
+  sources = [ "chrome_elf.ver" ]
   output = "$target_gen_dir/chrome_elf_version.rc"
 }
 
 # This manifest matches what GYP produces. It may not even be necessary.
 windows_manifest("chrome_elf_manifest") {
-  sources = [
-    as_invoker_manifest,
-  ]
+  sources = [ as_invoker_manifest ]
 }
 
 # Users of chrome_elf exports can depend on this target, which doesn't
 # pin them to linking either chrome_elf.dll or test_stubs.
 source_set("chrome_elf_main_include") {
-  sources = [
-    "chrome_elf_main.h",
-  ]
+  sources = [ "chrome_elf_main.h" ]
 }
 
 # For code that isn't Chrome-the browser, like test binaries, these stubs stand
@@ -130,9 +124,7 @@
 }
 
 source_set("dll_hash") {
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   sources = [
     "dll_hash/dll_hash.cc",
     "dll_hash/dll_hash.h",
@@ -140,9 +132,7 @@
 }
 
 executable("dll_hash_main") {
-  sources = [
-    "dll_hash/dll_hash_main.cc",
-  ]
+  sources = [ "dll_hash/dll_hash_main.cc" ]
   deps = [
     ":dll_hash",
     "//build/win:default_exe_manifest",
@@ -159,9 +149,7 @@
     ":nt_registry",  # utils
     "//base:base_static",  # pe_image
   ]
-  public_deps = [
-    "//sandbox",
-  ]
+  public_deps = [ "//sandbox" ]
 }
 
 # This target contains utility functions which must only depend on
@@ -315,9 +303,7 @@
 
 shared_library("main_unittest_dll_1") {
   testonly = true
-  sources = [
-    "third_party_dlls/main_unittest_dll_1.cc",
-  ]
+  sources = [ "third_party_dlls/main_unittest_dll_1.cc" ]
 
   # Disable sanitizer instrumentation in the test DLLs to avoid unwanted
   # exports.
diff --git a/chrome/chrome_elf/chrome_elf_main.cc b/chrome/chrome_elf/chrome_elf_main.cc
index aedbb30..f1ca45a 100644
--- a/chrome/chrome_elf/chrome_elf_main.cc
+++ b/chrome/chrome_elf/chrome_elf_main.cc
@@ -15,9 +15,10 @@
 #include "chrome/install_static/product_install_details.h"
 #include "chrome/install_static/user_data_dir.h"
 
-// This function is a temporary workaround for https://crbug.com/655788. We
-// need to come up with a better way to initialize crash reporting that can
-// happen inside DllMain().
+// This function is exported from the DLL so that it can be called by WinMain
+// after startup has completed in the browser process. For non-browser processes
+// it will be called inside the DLL loader lock so it should do as little as
+// possible to prevent deadlocks.
 void SignalInitializeCrashReporting() {
   if (!elf_crash::InitializeCrashReporting()) {
 #ifdef _DEBUG
@@ -59,24 +60,23 @@
 BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
   if (reason == DLL_PROCESS_ATTACH) {
     install_static::InitializeProductDetailsForPrimaryModule();
-
-    // CRT on initialization installs an exception filter which calls
-    // TerminateProcess. We need to hook CRT's attempt to set an exception.
-    elf_crash::DisableSetUnhandledExceptionFilter();
-
     install_static::InitializeProcessType();
 
-    // If this is not the browser process, all done.
-    if (install_static::IsNonBrowserProcess())
-      return TRUE;
-
-    __try {
-      // Initialize the blocking of third-party DLLs if the initialization of
-      // the safety beacon succeeds.
-      if (third_party_dlls::LeaveSetupBeacon())
-        third_party_dlls::Init();
-    } __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) {
+    if (!install_static::IsNonBrowserProcess()) {
+      __try {
+        // Initialize the blocking of third-party DLLs if the initialization of
+        // the safety beacon succeeds.
+        if (third_party_dlls::LeaveSetupBeacon())
+          third_party_dlls::Init();
+      } __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) {
+      }
+    } else if (!install_static::IsCrashpadHandlerProcess()) {
+      SignalInitializeCrashReporting();
+      // CRT on initialization installs an exception filter which calls
+      // TerminateProcess. We need to hook CRT's attempt to set an exception.
+      elf_crash::DisableSetUnhandledExceptionFilter();
     }
+
   } else if (reason == DLL_PROCESS_DETACH) {
     elf_crash::ShutdownCrashReporting();
   }
diff --git a/chrome/chrome_elf/crash/crash_helper.cc b/chrome/chrome_elf/crash/crash_helper.cc
index 381322a..a02aa37c 100644
--- a/chrome/chrome_elf/crash/crash_helper.cc
+++ b/chrome/chrome_elf/crash/crash_helper.cc
@@ -64,6 +64,9 @@
 // NOTE: This function will be called from DllMain during DLL_PROCESS_ATTACH
 // (while we have the loader lock), so do not misbehave.
 bool InitializeCrashReporting() {
+  if (g_crash_helper_enabled)
+    return true;
+
 #ifdef _DEBUG
   assert(g_crash_reports == nullptr);
   assert(g_set_unhandled_exception_filter == nullptr);
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 39864fc..a979974 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -33,6 +33,13 @@
                                        base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // defined(OS_CHROMEOS)
 
+#if defined(OS_CHROMEOS)
+// Enables app activity reporting for child user.
+// Requires |kPerAppTimeLimits| to be enabled.
+const base::Feature kAppActivityReporting{"AppActivityReporting",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 #if defined(OS_MACOSX)
 // Enable the new multi-profile-aware app shim mode.
 // TODO(https://crbug.com/982024): Delete this flag when feature is complete.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 90741b5..b3133c2b 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -34,7 +34,12 @@
 #if defined(OS_CHROMEOS)
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::Feature kApkWebAppInstalls;
-#endif  // defined(OS_CHROMEOS)
+#endif
+
+#if defined(OS_CHROMEOS)
+COMPONENT_EXPORT(CHROME_FEATURES)
+extern const base::Feature kAppActivityReporting;
+#endif
 
 #if defined(OS_MACOSX)
 COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/extensions/BUILD.gn b/chrome/common/extensions/BUILD.gn
index 7cefd88..2460787 100644
--- a/chrome/common/extensions/BUILD.gn
+++ b/chrome/common/extensions/BUILD.gn
@@ -17,7 +17,5 @@
 }
 
 group("test_features") {
-  public_deps = [
-    ":extension_features_unittest",
-  ]
+  public_deps = [ ":extension_features_unittest" ]
 }
diff --git a/chrome/common/extensions/api/BUILD.gn b/chrome/common/extensions/api/BUILD.gn
index 87b6f10..c8761d1 100644
--- a/chrome/common/extensions/api/BUILD.gn
+++ b/chrome/common/extensions/api/BUILD.gn
@@ -66,9 +66,7 @@
   }
 
   root_namespace = chrome_extensions_api_root_namespace
-  deps = [
-    "//extensions/common/api",
-  ]
+  deps = [ "//extensions/common/api" ]
 
   visibility = [ ":api" ]
 }
@@ -79,9 +77,7 @@
   schema_include_rules = chrome_extensions_api_schema_include_rules
 
   root_namespace = chrome_extensions_api_root_namespace
-  deps = [
-    "//extensions/common/api",
-  ]
+  deps = [ "//extensions/common/api" ]
 
   visibility = [ ":api" ]
 }
@@ -89,26 +85,20 @@
 json_features("api_features") {
   feature_type = "APIFeature"
   method_name = "AddChromeAPIFeatures"
-  sources = [
-    "_api_features.json",
-  ]
+  sources = [ "_api_features.json" ]
   visibility = [ ":extensions_features" ]
 }
 
 json_features("permission_features") {
   feature_type = "PermissionFeature"
   method_name = "AddChromePermissionFeatures"
-  sources = [
-    "_permission_features.json",
-  ]
+  sources = [ "_permission_features.json" ]
   visibility = [ ":extensions_features" ]
 }
 
 json_features("manifest_features") {
   feature_type = "ManifestFeature"
   method_name = "AddChromeManifestFeatures"
-  sources = [
-    "_manifest_features.json",
-  ]
+  sources = [ "_manifest_features.json" ]
   visibility = [ ":extensions_features" ]
 }
diff --git a/chrome/common/importer/BUILD.gn b/chrome/common/importer/BUILD.gn
index 9dffb6e3..6be16e69 100644
--- a/chrome/common/importer/BUILD.gn
+++ b/chrome/common/importer/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("interfaces") {
-  sources = [
-    "profile_import.mojom",
-  ]
+  sources = [ "profile_import.mojom" ]
 
   public_deps = [
     "//components/autofill/core/common/mojom:mojo_types",
diff --git a/chrome/common/media_router/BUILD.gn b/chrome/common/media_router/BUILD.gn
index 2f253237..1606ee15 100644
--- a/chrome/common/media_router/BUILD.gn
+++ b/chrome/common/media_router/BUILD.gn
@@ -53,9 +53,7 @@
     "//base",
     "//chrome/test:test_support",
   ]
-  public_deps = [
-    ":router",
-  ]
+  public_deps = [ ":router" ]
   sources = [
     "test/test_helper.cc",
     "test/test_helper.h",
diff --git a/chrome/common/media_router/mojom/BUILD.gn b/chrome/common/media_router/mojom/BUILD.gn
index 3a43ecb8..7463f07 100644
--- a/chrome/common/media_router/mojom/BUILD.gn
+++ b/chrome/common/media_router/mojom/BUILD.gn
@@ -18,9 +18,7 @@
 }
 
 mojom("media_router") {
-  sources = [
-    "media_router.mojom",
-  ]
+  sources = [ "media_router.mojom" ]
 
   public_deps = [
     ":media_controller",
@@ -42,13 +40,9 @@
 }
 
 mojom("media_router_test_interfaces") {
-  sources = [
-    "media_router_traits_test_service.mojom",
-  ]
+  sources = [ "media_router_traits_test_service.mojom" ]
 
-  public_deps = [
-    ":media_router",
-  ]
+  public_deps = [ ":media_router" ]
 
   disable_variants = true
 }
diff --git a/chrome/credential_provider/BUILD.gn b/chrome/credential_provider/BUILD.gn
index d65efa9..d171a356 100644
--- a/chrome/credential_provider/BUILD.gn
+++ b/chrome/credential_provider/BUILD.gn
@@ -6,9 +6,7 @@
 action("gcp_installer") {
   script = "build/make_setup.py"
 
-  outputs = [
-    "$root_out_dir/gcp_installer.exe",
-  ]
+  outputs = [ "$root_out_dir/gcp_installer.exe" ]
 
   args = [
     rebase_path("//", root_build_dir),
@@ -26,7 +24,5 @@
 }
 
 group("credential_provider") {
-  deps = [
-    ":gcp_installer",
-  ]
+  deps = [ ":gcp_installer" ]
 }
diff --git a/chrome/credential_provider/common/BUILD.gn b/chrome/credential_provider/common/BUILD.gn
index 1c3689a..ae71a654 100644
--- a/chrome/credential_provider/common/BUILD.gn
+++ b/chrome/credential_provider/common/BUILD.gn
@@ -10,7 +10,5 @@
     "gcp_strings.cc",
     "gcp_strings.h",
   ]
-  deps = [
-    "//build:branding_buildflags",
-  ]
+  deps = [ "//build:branding_buildflags" ]
 }
diff --git a/chrome/credential_provider/eventlog/BUILD.gn b/chrome/credential_provider/eventlog/BUILD.gn
index 7b5f120..6ddc4355 100644
--- a/chrome/credential_provider/eventlog/BUILD.gn
+++ b/chrome/credential_provider/eventlog/BUILD.gn
@@ -7,18 +7,14 @@
 import("//chrome/process_version_rc_template.gni")
 
 message_compiler("gcp_eventlog_messages") {
-  sources = [
-    "gcp_eventlog_messages.mc",
-  ]
+  sources = [ "gcp_eventlog_messages.mc" ]
 
   user_mode_logging = false
   compile_generated_code = false
 }
 
 process_version_rc_template("gcp_eventlog_provider_dll_version") {
-  sources = [
-    "gcp_eventlog_provider.ver",
-  ]
+  sources = [ "gcp_eventlog_provider.ver" ]
   output = "$target_gen_dir/gcp_eventlog_provider_dll_version.rc"
 }
 
diff --git a/chrome/credential_provider/gaiacp/BUILD.gn b/chrome/credential_provider/gaiacp/BUILD.gn
index 89f0947b..85cef508 100644
--- a/chrome/credential_provider/gaiacp/BUILD.gn
+++ b/chrome/credential_provider/gaiacp/BUILD.gn
@@ -33,9 +33,7 @@
     "reg_utils.h",
   ]
   public_configs = [ ":common_config" ]
-  public_deps = [
-    "//chrome/credential_provider/common:common_constants",
-  ]
+  public_deps = [ "//chrome/credential_provider/common:common_constants" ]
   deps = [
     ":string_resources",
     "//base",
@@ -106,9 +104,7 @@
     "win_http_url_fetcher.h",
   ]
   public_configs = [ ":gaiacp_config" ]
-  public_deps = [
-    ":common",
-  ]
+  public_deps = [ ":common" ]
   deps = [
     ":gaia_credential_provider_idl",
     ":static_resources",
@@ -171,12 +167,8 @@
 action("generate_credential_provider_idl_file") {
   script = "//build/util/version.py"
 
-  inputs = [
-    "gaia_credential_provider_idl.templ",
-  ]
-  outputs = [
-    "$target_gen_dir/gaia_credential_provider.idl",
-  ]
+  inputs = [ "gaia_credential_provider_idl.templ" ]
+  outputs = [ "$target_gen_dir/gaia_credential_provider.idl" ]
 
   args = [
     "-e",
@@ -188,9 +180,7 @@
 
 midl("gaia_credential_provider_idl") {
   dynamic_guid = gaia_credential_provider_clsid
-  deps = [
-    ":generate_credential_provider_idl_file",
-  ]
+  deps = [ ":generate_credential_provider_idl_file" ]
   header_file = "gaia_credential_provider_i.h"
   sources = get_target_outputs(":generate_credential_provider_idl_file")
 }
@@ -247,7 +237,5 @@
 # Compile the generated .rc file.
 source_set("string_resources") {
   sources = get_target_outputs(":generate_strings")
-  public_deps = [
-    ":generate_strings",
-  ]
+  public_deps = [ ":generate_strings" ]
 }
diff --git a/chrome/credential_provider/setup/BUILD.gn b/chrome/credential_provider/setup/BUILD.gn
index 1bfacb7..182c87b 100644
--- a/chrome/credential_provider/setup/BUILD.gn
+++ b/chrome/credential_provider/setup/BUILD.gn
@@ -22,9 +22,7 @@
     "setup_lib.cc",
     "setup_lib.h",
   ]
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
   deps = [
     "../gaiacp:common",
     "//chrome/installer/util:with_no_strings",
@@ -33,9 +31,7 @@
 
 grit("setup_resources") {
   source = "gcp_setup_resources.grd"
-  inputs = [
-    "gcp_icon.ico",
-  ]
+  inputs = [ "gcp_icon.ico" ]
   outputs = [
     "grit/gcp_setup_resources.h",
     "grit/gcp_setup_resources.rc",
diff --git a/chrome/install_static/BUILD.gn b/chrome/install_static/BUILD.gn
index 67301b6..86576326f 100644
--- a/chrome/install_static/BUILD.gn
+++ b/chrome/install_static/BUILD.gn
@@ -17,9 +17,7 @@
     "//components/version_info:generate_version_info",
   ]
 
-  public_deps = [
-    "//chrome/chrome_elf:nt_registry",
-  ]
+  public_deps = [ "//chrome/chrome_elf:nt_registry" ]
 
   sources = [
     "../app/chrome_dll_resource.h",
@@ -62,9 +60,7 @@
 # A source set for use by the module in a process that creates the process-wide
 # InstallDetails instance (i.e., chrome_elf.dll).
 source_set("primary_module") {
-  sources = [
-    "get_install_details_payload.cc",
-  ]
+  sources = [ "get_install_details_payload.cc" ]
 }
 
 # A source set for use by modules in a process that fetch the process-wide
@@ -76,9 +72,7 @@
     "initialize_from_primary_module.cc",
     "initialize_from_primary_module.h",
   ]
-  deps = [
-    ":install_static_util",
-  ]
+  deps = [ ":install_static_util" ]
 }
 
 test("install_static_unittests") {
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc
index 07d4542..42380349 100644
--- a/chrome/install_static/install_util.cc
+++ b/chrome/install_static/install_util.cc
@@ -34,6 +34,7 @@
   NACL_BROKER_PROCESS,
   NACL_LOADER_PROCESS,
 #endif
+  CRASHPAD_HANDLER_PROCESS,
 };
 
 // Caches the |ProcessType| of the current process.
@@ -319,6 +320,8 @@
   if (process_type == kNaClLoaderProcess)
     return ProcessType::NACL_LOADER_PROCESS;
 #endif
+  if (process_type == kCrashpadHandler)
+    return ProcessType::CRASHPAD_HANDLER_PROCESS;
   return ProcessType::OTHER_PROCESS;
 }
 
@@ -337,6 +340,8 @@
       return true;
     case ProcessType::OTHER_PROCESS:
       return false;
+    case ProcessType::CRASHPAD_HANDLER_PROCESS:
+      return false;
     case ProcessType::UNINITIALIZED:
       assert(false);
       return false;
@@ -577,6 +582,11 @@
   return g_process_type != ProcessType::BROWSER_PROCESS;
 }
 
+bool IsCrashpadHandlerProcess() {
+  assert(g_process_type != ProcessType::UNINITIALIZED);
+  return g_process_type == ProcessType::CRASHPAD_HANDLER_PROCESS;
+}
+
 bool ProcessNeedsProfileDir(const std::string& process_type) {
   return ProcessNeedsProfileDir(GetProcessType(UTF8ToUTF16(process_type)));
 }
diff --git a/chrome/install_static/install_util.h b/chrome/install_static/install_util.h
index 27a55e3..f3610d31 100644
--- a/chrome/install_static/install_util.h
+++ b/chrome/install_static/install_util.h
@@ -201,6 +201,9 @@
 // process. False otherwise.
 bool IsNonBrowserProcess();
 
+// Returns true if invoked in a Crashpad handler process. False otherwise.
+bool IsCrashpadHandlerProcess();
+
 // Returns true if the |process_type| has the rights to access the profile.
 // False otherwise.
 bool ProcessNeedsProfileDir(const std::string& process_type);
diff --git a/chrome/notification_helper/BUILD.gn b/chrome/notification_helper/BUILD.gn
index 23ab536..aae3153 100644
--- a/chrome/notification_helper/BUILD.gn
+++ b/chrome/notification_helper/BUILD.gn
@@ -61,9 +61,7 @@
 }
 
 process_version_rc_template("version_resources") {
-  sources = [
-    "notification_helper_exe.ver",
-  ]
+  sources = [ "notification_helper_exe.ver" ]
   output = "$target_gen_dir/notification_helper_exe.rc"
 }
 
@@ -85,9 +83,7 @@
     "//testing/gtest",
   ]
 
-  data_deps = [
-    ":notification_helper",
-  ]
+  data_deps = [ ":notification_helper" ]
 
   libs = [ "runtimeobject.lib" ]
 }
diff --git a/chrome/service/OWNERS b/chrome/service/OWNERS
index 8c862b79..ed1bd3ce 100644
--- a/chrome/service/OWNERS
+++ b/chrome/service/OWNERS
@@ -1,6 +1,6 @@
 file://cloud_print/OWNERS
 
-per-file service_utility_process_host_receiver_bindings.cc=set noparent
-per-file service_utility_process_host_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
+per-file service_utility_process_host_receiver_bindings.*=set noparent
+per-file service_utility_process_host_receiver_bindings.*=file://ipc/SECURITY_OWNERS
 
 # COMPONENT: Services>CloudPrint
diff --git a/chrome/services/app_service/BUILD.gn b/chrome/services/app_service/BUILD.gn
index 6ed6ae8..d9363ca 100644
--- a/chrome/services/app_service/BUILD.gn
+++ b/chrome/services/app_service/BUILD.gn
@@ -23,9 +23,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "app_service_impl_unittest.cc",
-  ]
+  sources = [ "app_service_impl_unittest.cc" ]
 
   deps = [
     ":lib",
diff --git a/chrome/services/app_service/public/cpp/BUILD.gn b/chrome/services/app_service/public/cpp/BUILD.gn
index 2f26d2c5..28e4ddb 100644
--- a/chrome/services/app_service/public/cpp/BUILD.gn
+++ b/chrome/services/app_service/public/cpp/BUILD.gn
@@ -10,9 +10,7 @@
     "app_update.h",
   ]
 
-  public_deps = [
-    "//chrome/services/app_service/public/mojom",
-  ]
+  public_deps = [ "//chrome/services/app_service/public/mojom" ]
 }
 
 if (is_chromeos) {
@@ -44,9 +42,7 @@
     "icon_loader.h",
   ]
 
-  public_deps = [
-    "//chrome/services/app_service/public/mojom",
-  ]
+  public_deps = [ "//chrome/services/app_service/public/mojom" ]
 }
 
 source_set("icon_loader_test_support") {
@@ -55,9 +51,7 @@
     "stub_icon_loader.h",
   ]
 
-  deps = [
-    ":icon_loader",
-  ]
+  deps = [ ":icon_loader" ]
 }
 
 source_set("intents") {
diff --git a/chrome/services/app_service/public/mojom/BUILD.gn b/chrome/services/app_service/public/mojom/BUILD.gn
index 39e16e7..9f4c5fa 100644
--- a/chrome/services/app_service/public/mojom/BUILD.gn
+++ b/chrome/services/app_service/public/mojom/BUILD.gn
@@ -5,19 +5,13 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "app_service.mojom",
-  ]
+  sources = [ "app_service.mojom" ]
 
-  public_deps = [
-    ":types",
-  ]
+  public_deps = [ ":types" ]
 }
 
 mojom("types") {
-  sources = [
-    "types.mojom",
-  ]
+  sources = [ "types.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 31d58e8..410e207 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3808,6 +3808,7 @@
       "../browser/download/download_shelf_unittest.cc",
       "../browser/enterprise_reporting/browser_report_generator_unittest.cc",
       "../browser/enterprise_reporting/extension_info_unittest.cc",
+      "../browser/enterprise_reporting/notification/extension_request_notification_unittest.cc",
       "../browser/enterprise_reporting/policy_info_unittest.cc",
       "../browser/enterprise_reporting/profile_report_generator_unittest.cc",
       "../browser/enterprise_reporting/report_generator_unittest.cc",
@@ -3863,6 +3864,7 @@
       "../browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc",
       "../browser/resource_coordinator/decision_details_unittest.cc",
       "../browser/resource_coordinator/discard_metrics_lifecycle_unit_observer_unittest.cc",
+      "../browser/resource_coordinator/intervention_policy_database_unittest.cc",
       "../browser/resource_coordinator/leveldb_site_characteristics_database_unittest.cc",
       "../browser/resource_coordinator/lifecycle_unit_base_unittest.cc",
       "../browser/resource_coordinator/lifecycle_unit_unittest.cc",
diff --git a/chrome/test/base/js2gtest.gni b/chrome/test/base/js2gtest.gni
index 49fa1cb..f529d228 100644
--- a/chrome/test/base/js2gtest.gni
+++ b/chrome/test/base/js2gtest.gni
@@ -107,9 +107,7 @@
       rebase_path(copied_source_pattern, root_build_dir),
     ]
 
-    deps = [
-      "//v8:v8_shell($v8_snapshot_toolchain)",
-    ]
+    deps = [ "//v8:v8_shell($v8_snapshot_toolchain)" ]
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
@@ -120,9 +118,7 @@
     copy(copy_target_name) {
       visibility = [ ":$source_set_name" ]
       sources = invoker.extra_js_files
-      outputs = [
-        copied_source_pattern,
-      ]
+      outputs = [ copied_source_pattern ]
     }
   }
 
@@ -155,9 +151,7 @@
       data += invoker.gen_include_files
     }
     if (defined(invoker.extra_js_files)) {
-      data_deps = [
-        ":$copy_target_name",
-      ]
+      data_deps = [ ":$copy_target_name" ]
     }
   }
 }
diff --git a/chrome/test/data/autofill/captured_sites/testcases.json b/chrome/test/data/autofill/captured_sites/testcases.json
index 1e7bffa..53d295ce 100644
--- a/chrome/test/data/autofill/captured_sites/testcases.json
+++ b/chrome/test/data/autofill/captured_sites/testcases.json
@@ -62,7 +62,7 @@
     { "site_name": "dicks_sporting_goods" },
     { "site_name": "dish" },
     { "site_name": "dsw" },
-    { "site_name": "duluthtrading" },
+    { "site_name": "duluthtrading", "disabled":true, "bug_number":1041744},
     { "site_name": "ebags" },
     { "site_name": "ebay", "disabled":true, "bug_number":984664 },
     { "site_name": "eddiebauer" },
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 529aa99..a4e6e4f4 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -3997,6 +3997,16 @@
     ]
   },
 
+  "AccessibilityShortcutsEnabled": {
+    "os": ["chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": { "AccessibilityShortcutsEnabled": true },
+        "prefs": { "settings.a11y.shortcuts_enabled": {} }
+      }
+    ]
+  },
+
   "SelectToSpeakEnabled": {
     "os": ["chromeos"],
     "policy_pref_mapping_test": [
diff --git a/chrome/tools/build/mac/FILES.cfg b/chrome/tools/build/mac/FILES.cfg
index 2089a89e..8f8abf2 100644
--- a/chrome/tools/build/mac/FILES.cfg
+++ b/chrome/tools/build/mac/FILES.cfg
@@ -129,4 +129,23 @@
     'buildtype': ['dev', 'official'],
     'archive': 'devtools-frontend.zip',
   },
+  # Updater files:
+  {
+    'filename': 'GoogleUpdate.app',
+    'buildtype': ['official'],
+    'archive': 'updater.zip',
+    'optional': ['official'], # TODO(crbug.com/1024318): Make non-optional.
+  },
+  {
+    'filename': 'updater_setup',
+    'buildtype': ['official'],
+    'archive': 'updater.zip',
+    'optional': ['official'], # TODO(crbug.com/1024318): Make non-optional.
+  },
+  {
+    'filename': 'chrome/updater/.install.sh',
+    'buildtype': ['official'],
+    'archive': 'updater.zip',
+    'optional': ['official'], # TODO(crbug.com/1024318): Make non-optional.
+  },
 ]
diff --git a/chromecast/browser/OWNERS b/chromecast/browser/OWNERS
index 63fa768..a1ef4992e 100644
--- a/chromecast/browser/OWNERS
+++ b/chromecast/browser/OWNERS
@@ -1,9 +1,7 @@
 seantopping@chromium.org
 
-per-file cast_overlay_manifests.h=set noparent
-per-file cast_overlay_manifests.h=file://ipc/SECURITY_OWNERS
-per-file cast_overlay_manifests.cc=set noparent
-per-file cast_overlay_manifests.cc=file://ipc/SECURITY_OWNERS
-per-file cast_content_browser_client_receiver_bindings.cc=set noparent
-per-file cast_content_browser_client_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
+per-file cast_overlay_manifests.*=set noparent
+per-file cast_overlay_manifests.*=file://ipc/SECURITY_OWNERS
+per-file cast_content_browser_client_receiver_bindings.*=set noparent
+per-file cast_content_browser_client_receiver_bindings.*=file://ipc/SECURITY_OWNERS
 per-file service_connector.cc=file://ipc/SECURITY_OWNERS
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn
index 438abf09..9ba32b6c 100644
--- a/chromecast/browser/android/BUILD.gn
+++ b/chromecast/browser/android/BUILD.gn
@@ -25,9 +25,7 @@
 }
 
 java_cpp_template("cast_shell_build_config_gen") {
-  sources = [
-    "apk/templates/BuildConfig.template",
-  ]
+  sources = [ "apk/templates/BuildConfig.template" ]
   package_path = "org/chromium/chromecast/shell"
 
   defines = []
@@ -85,18 +83,15 @@
 
 android_library("cast_intents_java") {
   java_src_dir = "//chromecast/browser/android/apk/src"
-  sources = [
-    "$java_src_dir/org/chromium/chromecast/shell/CastIntents.java",
-  ]
+  sources = [ "$java_src_dir/org/chromium/chromecast/shell/CastIntents.java" ]
 }
 android_aidl("logs_provider_aidl") {
   java_src_dir = "//chromecast/browser/android/apk/src"
   interface_file =
       "$java_src_dir/org/chromium/chromecast/shell/logs_provider_service.aidl"
 
-  sources = [
-    "$java_src_dir/org/chromium/chromecast/shell/IDeviceLogsProvider.aidl",
-  ]
+  sources =
+      [ "$java_src_dir/org/chromium/chromecast/shell/IDeviceLogsProvider.aidl" ]
 }
 
 android_library("reactive_android_java") {
@@ -192,9 +187,7 @@
 
 if (is_android_things_non_public && !build_for_android_things_n) {
   android_library("cast_shell_android_things_sys_info_java") {
-    sources = [
-      "//chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastSysInfoAndroidThings.java",
-    ]
+    sources = [ "//chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastSysInfoAndroidThings.java" ]
     deps = [
       "//base:base_java",
       "//chromecast/internal/android/prebuilt/things:support_lib_java",
@@ -202,12 +195,8 @@
   }
 
   generate_jni("cast_shell_android_things_sys_info_jni_headers") {
-    sources = [
-      "//chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastSysInfoAndroidThings.java",
-    ]
-    deps = [
-      "//chromecast/internal/android/prebuilt/things:support_lib_java",
-    ]
+    sources = [ "//chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastSysInfoAndroidThings.java" ]
+    deps = [ "//chromecast/internal/android/prebuilt/things:support_lib_java" ]
   }
 }
 
diff --git a/chromecast/media/cma/backend/android/BUILD.gn b/chromecast/media/cma/backend/android/BUILD.gn
index a9fc4e2..731325c 100644
--- a/chromecast/media/cma/backend/android/BUILD.gn
+++ b/chromecast/media/cma/backend/android/BUILD.gn
@@ -79,16 +79,12 @@
 }
 
 test("cast_android_cma_backend_unittests") {
-  deps = [
-    ":unit_tests",
-  ]
+  deps = [ ":unit_tests" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "volume_cache_test.cc",
-  ]
+  sources = [ "volume_cache_test.cc" ]
 
   deps = [
     ":cast_media_android",
diff --git a/chromecast/renderer/BUILD.gn b/chromecast/renderer/BUILD.gn
index 59a9f184..4a7c427 100644
--- a/chromecast/renderer/BUILD.gn
+++ b/chromecast/renderer/BUILD.gn
@@ -44,9 +44,7 @@
     "queryable_data_store.h",
   ]
 
-  public_deps = [
-    "//chromecast/renderer/media",
-  ]
+  public_deps = [ "//chromecast/renderer/media" ]
 
   if (chromecast_branding == "public") {
     sources += [ "cast_content_renderer_client_simple.cc" ]
diff --git a/chromeos/components/help_app_ui/BUILD.gn b/chromeos/components/help_app_ui/BUILD.gn
index 7a1f3b4d..5601935 100644
--- a/chromeos/components/help_app_ui/BUILD.gn
+++ b/chromeos/components/help_app_ui/BUILD.gn
@@ -30,13 +30,9 @@
 js2gtest("browser_tests_js") {
   test_type = "mojo_lite_webui"
 
-  sources = [
-    "test/help_app_ui_browsertest.js",
-  ]
+  sources = [ "test/help_app_ui_browsertest.js" ]
 
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
-  deps = [
-    "//chromeos/constants",
-  ]
+  deps = [ "//chromeos/constants" ]
 }
diff --git a/chromeos/dbus/shill/BUILD.gn b/chromeos/dbus/shill/BUILD.gn
index 459a179..8a3e32cf 100644
--- a/chromeos/dbus/shill/BUILD.gn
+++ b/chromeos/dbus/shill/BUILD.gn
@@ -61,9 +61,7 @@
 
 source_set("test_support") {
   testonly = true
-  public_deps = [
-    ":shill",
-  ]
+  public_deps = [ ":shill" ]
   deps = [
     "//base",
     "//base/test:test_support",
diff --git a/cloud_print/BUILD.gn b/cloud_print/BUILD.gn
index 0c554c8..6f855cba 100644
--- a/cloud_print/BUILD.gn
+++ b/cloud_print/BUILD.gn
@@ -25,9 +25,7 @@
 }
 
 test("cloud_print_unittests") {
-  sources = [
-    "virtual_driver/win/port_monitor/port_monitor_unittest.cc",
-  ]
+  sources = [ "virtual_driver/win/port_monitor/port_monitor_unittest.cc" ]
 
   deps = [
     "//base",
diff --git a/cloud_print/common/BUILD.gn b/cloud_print/common/BUILD.gn
index ca0b546d..258cc4e 100644
--- a/cloud_print/common/BUILD.gn
+++ b/cloud_print/common/BUILD.gn
@@ -8,9 +8,7 @@
     "win/cloud_print_utils.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("install_utils") {
diff --git a/cloud_print/virtual_driver/win/install/BUILD.gn b/cloud_print/virtual_driver/win/install/BUILD.gn
index 4d25527..3359f20 100644
--- a/cloud_print/virtual_driver/win/install/BUILD.gn
+++ b/cloud_print/virtual_driver/win/install/BUILD.gn
@@ -8,9 +8,7 @@
 assert(is_win)
 
 executable("virtual_driver_setup") {
-  sources = [
-    "setup.cc",
-  ]
+  sources = [ "setup.cc" ]
 
   configs -= [ "//build/config/win:console" ]
   configs += [ "//build/config/win:windowed" ]
@@ -31,27 +29,17 @@
 }
 
 copy("copy_gcp_driver_gpd") {
-  sources = [
-    "inf/gcp_driver.gpd",
-  ]
-  outputs = [
-    "$root_build_dir/gcp_driver.gpd",
-  ]
+  sources = [ "inf/gcp_driver.gpd" ]
+  outputs = [ "$root_build_dir/gcp_driver.gpd" ]
 }
 
 copy("copy_gcp_driver_inf") {
-  sources = [
-    "inf/gcp_driver.inf",
-  ]
-  outputs = [
-    "$root_build_dir/gcp_driver.inf",
-  ]
+  sources = [ "inf/gcp_driver.inf" ]
+  outputs = [ "$root_build_dir/gcp_driver.inf" ]
 }
 
 process_version_rc_template("setup_version") {
-  sources = [
-    "virtual_driver_setup_exe.ver",
-  ]
+  sources = [ "virtual_driver_setup_exe.ver" ]
   output = "$target_gen_dir/virtual_driver_setup.rc"
 }
 
diff --git a/cloud_print/virtual_driver/win/port_monitor/BUILD.gn b/cloud_print/virtual_driver/win/port_monitor/BUILD.gn
index 42fa30c2..cf9bdb9 100644
--- a/cloud_print/virtual_driver/win/port_monitor/BUILD.gn
+++ b/cloud_print/virtual_driver/win/port_monitor/BUILD.gn
@@ -8,9 +8,7 @@
 assert(is_win)
 
 group("port_monitor") {
-  public_deps = [
-    ":port_monitor_dll",
-  ]
+  public_deps = [ ":port_monitor_dll" ]
 }
 
 shared_library("port_monitor_dll") {
@@ -38,9 +36,7 @@
 }
 
 group("copy_gcp_portmon_binaries") {
-  deps = [
-    ":copy_gcp_portmon_dll",
-  ]
+  deps = [ ":copy_gcp_portmon_dll" ]
   # TODO(pastarmovj): Find some way to reference the pdb file for the 64bit dll
   # simply using it in the sources directive causes gn to error when generating
   # the build files.
@@ -48,15 +44,9 @@
 
 if (current_cpu == "x64") {
   copy("copy_gcp_portmon_dll") {
-    sources = [
-      "$root_out_dir/gcp_portmon64.dll",
-    ]
-    outputs = [
-      "$root_out_dir/gcp_portmon.dll",
-    ]
-    deps = [
-      ":port_monitor_dll",
-    ]
+    sources = [ "$root_out_dir/gcp_portmon64.dll" ]
+    outputs = [ "$root_out_dir/gcp_portmon.dll" ]
+    deps = [ ":port_monitor_dll" ]
   }
 } else {
   # Make sure that we have a copy of gcp_portmon64.dll in the root out
@@ -73,27 +63,15 @@
   if (symbol_level > 0) {
     copy("copy_gcp_portmon_pdb") {
       visibility = [ ":copy_gcp_portmon_dll" ]
-      sources = [
-        "$gcp_portmon64_out_dir/gcp_portmon64.dll.pdb",
-      ]
-      outputs = [
-        "$root_out_dir/{{source_file_part}}",
-      ]
-      deps = [
-        gcp_portmon64_label,
-      ]
+      sources = [ "$gcp_portmon64_out_dir/gcp_portmon64.dll.pdb" ]
+      outputs = [ "$root_out_dir/{{source_file_part}}" ]
+      deps = [ gcp_portmon64_label ]
     }
   }
   copy("copy_gcp_portmon_dll") {
-    sources = [
-      "$gcp_portmon64_out_dir/gcp_portmon64.dll",
-    ]
-    outputs = [
-      "$root_out_dir/{{source_file_part}}",
-    ]
-    deps = [
-      gcp_portmon64_label,
-    ]
+    sources = [ "$gcp_portmon64_out_dir/gcp_portmon64.dll" ]
+    outputs = [ "$root_out_dir/{{source_file_part}}" ]
+    deps = [ gcp_portmon64_label ]
     if (symbol_level > 0) {
       deps += [ ":copy_gcp_portmon_pdb" ]
     }
@@ -116,9 +94,7 @@
 }
 
 process_version_rc_template("resources") {
-  sources = [
-    "../gcp_portmon_dll.ver",
-  ]
+  sources = [ "../gcp_portmon_dll.ver" ]
 
   # Note: target_gen_dir will be different for each toolchain so the output
   # name doesn't need mangling.
diff --git a/components/android_system_error_page/BUILD.gn b/components/android_system_error_page/BUILD.gn
new file mode 100644
index 0000000..a623df7
--- /dev/null
+++ b/components/android_system_error_page/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(is_android)
+
+static_library("android_system_error_page") {
+  sources = [
+    "error_page_populator.cc",
+    "error_page_populator.h",
+  ]
+
+  configs += [
+    # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+    "//build/config/compiler:no_size_t_to_int_warning",
+
+    "//build/config/compiler:noshadowing",
+  ]
+
+  deps = [
+    "//base",
+    "//base:i18n",
+    "//components/resources",
+    "//components/strings",
+    "//net",
+    "//third_party/blink/public:blink",
+    "//ui/base",
+    "//url",
+  ]
+}
diff --git a/components/android_system_error_page/DEPS b/components/android_system_error_page/DEPS
new file mode 100644
index 0000000..d3786b0
--- /dev/null
+++ b/components/android_system_error_page/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+  "+components/grit",
+  "+components/strings",
+  "+net",
+  "+third_party/blink/public",
+  "+ui/base",
+]
diff --git a/components/android_system_error_page/README.md b/components/android_system_error_page/README.md
index 2211ed5..259a5f7a 100644
--- a/components/android_system_error_page/README.md
+++ b/components/android_system_error_page/README.md
@@ -1,2 +1,2 @@
 Contains code and resources for displaying network error pages using an Android
-system style.
+system style. The C++ code is intended to be used from the renderer process.
diff --git a/components/android_system_error_page/error_page_populator.cc b/components/android_system_error_page/error_page_populator.cc
new file mode 100644
index 0000000..077a788e
--- /dev/null
+++ b/components/android_system_error_page/error_page_populator.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/android_system_error_page/error_page_populator.h"
+
+#include "base/i18n/rtl.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/grit/components_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "net/base/escape.h"
+#include "net/base/net_errors.h"
+#include "third_party/blink/public/platform/web_url_error.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "url/gurl.h"
+
+namespace android_system_error_page {
+
+namespace {
+constexpr char kThrottledErrorDescription[] =
+    "Request throttled. Visit http://dev.chromium.org/throttling for more "
+    "information.";
+}  // namespace
+
+void PopulateErrorPageHtml(const blink::WebURLError& error,
+                           std::string* error_html) {
+  std::string err;
+  if (error.reason() == net::ERR_TEMPORARILY_THROTTLED)
+    err = kThrottledErrorDescription;
+  else
+    err = net::ErrorToString(error.reason());
+
+  if (!error_html)
+    return;
+
+  // Create the error page based on the error reason.
+  GURL gurl(error.url());
+  std::string url_string = gurl.possibly_invalid_spec();
+  int reason_id = IDS_ANDROID_ERROR_PAGE_WEBPAGE_CAN_NOT_BE_LOADED;
+
+  if (err.empty())
+    reason_id = IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN;
+
+  std::string escaped_url = net::EscapeForHTML(url_string);
+  std::vector<std::string> replacements;
+  replacements.push_back(
+      l10n_util::GetStringUTF8(IDS_ANDROID_ERROR_PAGE_WEBPAGE_NOT_AVAILABLE));
+  replacements.push_back(
+      l10n_util::GetStringFUTF8(reason_id, base::UTF8ToUTF16(escaped_url)));
+
+  // Having chosen the base reason, chose what extra information to add.
+  if (reason_id == IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN) {
+    replacements.push_back(l10n_util::GetStringUTF8(
+        IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN_SUGGESTIONS));
+  } else {
+    replacements.push_back(err);
+  }
+  if (base::i18n::IsRTL())
+    replacements.push_back("direction: rtl;");
+  else
+    replacements.push_back("");
+  *error_html = base::ReplaceStringPlaceholders(
+      ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
+          IDR_ANDROID_ERROR_PAGE_LOAD_ERROR_HTML),
+      replacements, nullptr);
+}
+
+}  // namespace android_system_error_page
diff --git a/components/android_system_error_page/error_page_populator.h b/components/android_system_error_page/error_page_populator.h
new file mode 100644
index 0000000..e1b017e6
--- /dev/null
+++ b/components/android_system_error_page/error_page_populator.h
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ANDROID_SYSTEM_ERROR_PAGE_ERROR_PAGE_POPULATOR_H_
+#define COMPONENTS_ANDROID_SYSTEM_ERROR_PAGE_ERROR_PAGE_POPULATOR_H_
+
+#include <string>
+
+namespace blink {
+struct WebURLError;
+}
+
+namespace android_system_error_page {
+
+// Populates |error_html| to display an error page with an Android system feel
+// for |error|.
+void PopulateErrorPageHtml(const blink::WebURLError& error,
+                           std::string* error_html);
+
+}  // namespace android_system_error_page
+
+#endif  // COMPONENTS_ANDROID_SYSTEM_ERROR_PAGE_ERROR_PAGE_POPULATOR_H_
diff --git a/components/autofill/android/autofill_provider_android.cc b/components/autofill/android/autofill_provider_android.cc
index 238de06..1a6f12c 100644
--- a/components/autofill/android/autofill_provider_android.cc
+++ b/components/autofill/android/autofill_provider_android.cc
@@ -34,10 +34,27 @@
     const JavaRef<jobject>& jcaller,
     content::WebContents* web_contents)
     : id_(kNoQueryId), web_contents_(web_contents), check_submission_(false) {
-  JNIEnv* env = AttachCurrentThread();
+  OnJavaAutofillProviderChanged(AttachCurrentThread(), jcaller);
+}
+
+void AutofillProviderAndroid::OnJavaAutofillProviderChanged(
+    JNIEnv* env,
+    const JavaRef<jobject>& jcaller) {
+  // If the current Java object isn't null (e.g., because it hasn't been
+  // garbage-collected yet), clear its reference to this object.
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (!obj.is_null()) {
+    Java_AutofillProvider_setNativeAutofillProvider(env, obj, 0);
+  }
+
   java_ref_ = JavaObjectWeakGlobalRef(env, jcaller);
-  Java_AutofillProvider_setNativeAutofillProvider(
-      env, jcaller, reinterpret_cast<jlong>(this));
+
+  // If the new Java object isn't null, set its native object to |this|.
+  obj = java_ref_.get(env);
+  if (!obj.is_null()) {
+    Java_AutofillProvider_setNativeAutofillProvider(
+        env, obj, reinterpret_cast<jlong>(this));
+  }
 }
 
 AutofillProviderAndroid::~AutofillProviderAndroid() {
diff --git a/components/autofill/android/autofill_provider_android.h b/components/autofill/android/autofill_provider_android.h
index d99e491..270a05ee 100644
--- a/components/autofill/android/autofill_provider_android.h
+++ b/components/autofill/android/autofill_provider_android.h
@@ -23,6 +23,12 @@
  public:
   AutofillProviderAndroid(const base::android::JavaRef<jobject>& jcaller,
                           content::WebContents* web_contents);
+  // Invoked when the Java-side AutofillProvider counterpart of this object
+  // has been changed (either to null or to a new object).
+  void OnJavaAutofillProviderChanged(
+      JNIEnv* env,
+      const base::android::JavaRef<jobject>& jcaller);
+
   ~AutofillProviderAndroid() override;
 
   // AutofillProvider:
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index 178f307f..2868f4b 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -212,6 +212,12 @@
       base::OnceCallback<void(const ClientStatus&, const std::string&)>
           callback) = 0;
 
+  // Return the tag of the element given by |selector|.
+  virtual void GetElementTag(
+      const Selector& selector,
+      base::OnceCallback<void(const ClientStatus&, const std::string&)>
+          callback) = 0;
+
   // Make the next call to WaitForNavigation to expect a navigation event that
   // started after this call.
   virtual void ExpectNavigation() = 0;
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index 85132a41..843d4e8 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -193,6 +193,12 @@
                void(const Selector& selector,
                     base::OnceCallback<void(const ClientStatus&,
                                             const std::string&)> callback));
+
+  MOCK_METHOD2(GetElementTag,
+               void(const Selector& selector,
+                    base::OnceCallback<void(const ClientStatus&,
+                                            const std::string&)> callback));
+
   MOCK_METHOD0(ExpectNavigation, void());
   MOCK_METHOD0(ExpectedNavigationHasStarted, bool());
   MOCK_METHOD1(WaitForNavigation,
diff --git a/components/autofill_assistant/browser/actions/required_fields_fallback_handler.cc b/components/autofill_assistant/browser/actions/required_fields_fallback_handler.cc
index 6c2b1a77..cd91b4f 100644
--- a/components/autofill_assistant/browser/actions/required_fields_fallback_handler.cc
+++ b/components/autofill_assistant/browser/actions/required_fields_fallback_handler.cc
@@ -159,6 +159,21 @@
 
   // Set the next field to its fallback value.
   const RequiredField& required_field = required_fields_[required_fields_index];
+  DVLOG(3) << "Getting element tag for " << required_field.selector;
+  action_delegate_->GetElementTag(
+      required_field.selector,
+      base::BindOnce(&RequiredFieldsFallbackHandler::OnGetFallbackFieldTag,
+                     weak_ptr_factory_.GetWeakPtr(), required_fields_index,
+                     std::move(fallback_data)));
+}
+
+void RequiredFieldsFallbackHandler::OnGetFallbackFieldTag(
+    size_t required_fields_index,
+    std::unique_ptr<FallbackData> fallback_data,
+    const ClientStatus& element_tag_status,
+    const std::string& element_tag) {
+  // Set the next field to its fallback value.
+  const RequiredField& required_field = required_fields_[required_fields_index];
   auto fallback_value = fallback_data->GetValue(required_field.fallback_key);
   if (!fallback_value.has_value()) {
     DVLOG(3) << "No fallback for " << required_field.selector;
@@ -168,12 +183,21 @@
   }
 
   DVLOG(3) << "Setting fallback value for " << required_field.selector;
-  action_delegate_->SetFieldValue(
-      required_field.selector, fallback_value.value(),
-      required_field.simulate_key_presses, required_field.delay_in_millisecond,
-      base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
-                     weak_ptr_factory_.GetWeakPtr(), required_fields_index,
-                     std::move(fallback_data)));
+  if (element_tag == "SELECT") {
+    action_delegate_->SelectOption(
+        required_field.selector, fallback_value.value(),
+        base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
+                       weak_ptr_factory_.GetWeakPtr(), required_fields_index,
+                       std::move(fallback_data)));
+  } else {
+    action_delegate_->SetFieldValue(
+        required_field.selector, fallback_value.value(),
+        required_field.simulate_key_presses,
+        required_field.delay_in_millisecond,
+        base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
+                       weak_ptr_factory_.GetWeakPtr(), required_fields_index,
+                       std::move(fallback_data)));
+  }
 }
 
 void RequiredFieldsFallbackHandler::OnSetFallbackFieldValue(
diff --git a/components/autofill_assistant/browser/actions/required_fields_fallback_handler.h b/components/autofill_assistant/browser/actions/required_fields_fallback_handler.h
index bd9703e3..e0715592 100644
--- a/components/autofill_assistant/browser/actions/required_fields_fallback_handler.h
+++ b/components/autofill_assistant/browser/actions/required_fields_fallback_handler.h
@@ -100,6 +100,12 @@
       size_t required_fields_index,
       std::unique_ptr<FallbackData> fallback_data);
 
+  // Called after retrieving tag name from a field.
+  void OnGetFallbackFieldTag(size_t required_fields_index,
+                             std::unique_ptr<FallbackData> fallback_data,
+                             const ClientStatus& element_tag_status,
+                             const std::string& element_tag);
+
   // Called after trying to set form values without Autofill in case of fallback
   // after failed validation.
   void OnSetFallbackFieldValue(size_t required_fields_index,
diff --git a/components/autofill_assistant/browser/actions/use_address_action_unittest.cc b/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
index 00de823..3bd6f8e 100644
--- a/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
@@ -201,7 +201,8 @@
 }
 
 TEST_F(UseAddressActionTest, FallbackFails) {
-  InSequence seq;
+  ON_CALL(mock_action_delegate_, GetElementTag(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
 
   ActionProto action_proto = CreateUseAddressAction();
   AddRequiredField(&action_proto, UseAddressProto::RequiredField::FIRST_NAME,
@@ -238,7 +239,8 @@
 }
 
 TEST_F(UseAddressActionTest, FallbackSucceeds) {
-  InSequence seq;
+  ON_CALL(mock_action_delegate_, GetElementTag(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
 
   ActionProto action_proto = CreateUseAddressAction();
   AddRequiredField(&action_proto, UseAddressProto::RequiredField::FIRST_NAME,
@@ -254,29 +256,28 @@
                   NotNull(), Eq(Selector({kFakeSelector}).MustBeVisible()), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
-  {
-    InSequence seq;
+  // Validation fails when getting FIRST_NAME.
+  EXPECT_CALL(mock_web_controller_,
+              OnGetFieldValue(Eq(Selector({"#email"})), _))
+      .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
+  EXPECT_CALL(mock_web_controller_,
+              OnGetFieldValue(Eq(Selector({"#first_name"})), _))
+      .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
+  EXPECT_CALL(mock_web_controller_,
+              OnGetFieldValue(Eq(Selector({"#last_name"})), _))
+      .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
-    // Validation fails when getting FIRST_NAME.
-    EXPECT_CALL(mock_web_controller_,
-                OnGetFieldValue(Eq(Selector({"#email"})), _))
-        .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
-    EXPECT_CALL(mock_web_controller_,
-                OnGetFieldValue(Eq(Selector({"#first_name"})), _))
-        .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
-    EXPECT_CALL(mock_web_controller_,
-                OnGetFieldValue(Eq(Selector({"#last_name"})), _))
-        .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
+  // Fallback succeeds.
+  Expectation set_first_name =
+      EXPECT_CALL(mock_action_delegate_,
+                  OnSetFieldValue(Eq(Selector({"#first_name"})), kFirstName, _))
+          .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
-    // Fallback succeeds.
-    EXPECT_CALL(mock_action_delegate_,
-                OnSetFieldValue(Eq(Selector({"#first_name"})), kFirstName, _))
-        .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+  // Second validation succeeds.
+  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+      .After(set_first_name)
+      .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
-    // Second validation succeeds.
-    EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
-        .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
-  }
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
             ProcessAction(action_proto));
 }
@@ -302,6 +303,9 @@
 
 TEST_F(UseAddressActionTest,
        AutofillFailureWithRequiredFieldsLaunchesFallback) {
+  ON_CALL(mock_action_delegate_, GetElementTag(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
+
   ActionProto action_proto = CreateUseAddressAction();
   AddRequiredField(&action_proto, UseAddressProto::RequiredField::FIRST_NAME,
                    "#first_name");
diff --git a/components/autofill_assistant/browser/actions/use_credit_card_action.cc b/components/autofill_assistant/browser/actions/use_credit_card_action.cc
index 2a2fdb01..6eeecc1 100644
--- a/components/autofill_assistant/browser/actions/use_credit_card_action.cc
+++ b/components/autofill_assistant/browser/actions/use_credit_card_action.cc
@@ -15,6 +15,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/data_model/autofill_profile.h"
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill_assistant/browser/actions/action_delegate.h"
@@ -162,6 +163,10 @@
   fallback_data->field_values.emplace(
       (int)UseCreditCardProto::RequiredField::CREDIT_CARD_NUMBER,
       base::UTF16ToUTF8(card.GetRawInfo(autofill::CREDIT_CARD_NUMBER)));
+  fallback_data->field_values.emplace(
+      (int)UseCreditCardProto::RequiredField::CREDIT_CARD_NETWORK,
+      autofill::data_util::GetPaymentRequestData(card.network())
+          .basic_card_issuer_network);
   return fallback_data;
 }
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc b/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
index e6a2486..53f1df9 100644
--- a/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
@@ -159,6 +159,9 @@
 }
 
 TEST_F(UseCreditCardActionTest, FillCreditCardWithFallback) {
+  ON_CALL(mock_action_delegate_, GetElementTag(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
+
   ActionProto action = CreateUseCreditCardAction();
   AddRequiredField(
       &action, UseCreditCardProto::RequiredField::CREDIT_CARD_VERIFICATION_CODE,
@@ -181,6 +184,9 @@
   AddRequiredField(&action,
                    UseCreditCardProto::RequiredField::CREDIT_CARD_EXP_MM_YY,
                    "#exp_month_year2");
+  AddRequiredField(&action,
+                   UseCreditCardProto::RequiredField::CREDIT_CARD_NETWORK,
+                   "#network");
 
   // First validation fails.
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Selector({"#cvc"}), _))
@@ -200,6 +206,8 @@
   EXPECT_CALL(mock_web_controller_,
               OnGetFieldValue(Selector({"#exp_month_year2"}), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
+  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Selector({"#network"}), _))
+      .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
 
   // Expect fields to be filled
   Expectation set_cvc =
@@ -231,6 +239,10 @@
       EXPECT_CALL(mock_action_delegate_,
                   OnSetFieldValue(Selector({"#exp_month_year2"}), "09/24", _))
           .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+  Expectation set_card_network =
+      EXPECT_CALL(mock_action_delegate_,
+                  OnSetFieldValue(Selector({"#network"}), "visa", _))
+          .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // After fallback, second validation succeeds.
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Selector({"#cvc"}), _))
@@ -257,6 +269,9 @@
               OnGetFieldValue(Selector({"#exp_month_year2"}), _))
       .After(set_expyear4)
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
+  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Selector({"#network"}), _))
+      .After(set_card_network)
+      .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   autofill::CreditCard credit_card;
   credit_card.SetExpirationMonth(9);
@@ -278,6 +293,9 @@
 }
 
 TEST_F(UseCreditCardActionTest, ForcedFallback) {
+  ON_CALL(mock_action_delegate_, GetElementTag(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
+
   ActionProto action = CreateUseCreditCardAction();
   auto* cvc_required = AddRequiredField(
       &action, UseCreditCardProto::RequiredField::CREDIT_CARD_VERIFICATION_CODE,
@@ -335,6 +353,9 @@
 
 TEST_F(UseCreditCardActionTest,
        AutofillFailureWithRequiredFieldsLaunchesFallback) {
+  ON_CALL(mock_action_delegate_, GetElementTag(_, _))
+      .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
+
   ActionProto action_proto = CreateUseCreditCardAction();
   AddRequiredField(
       &action_proto,
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index e1d6040..1d2450a8 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -420,6 +420,13 @@
   delegate_->GetWebController()->GetOuterHtml(selector, std::move(callback));
 }
 
+void ScriptExecutor::GetElementTag(
+    const Selector& selector,
+    base::OnceCallback<void(const ClientStatus&, const std::string&)>
+        callback) {
+  delegate_->GetWebController()->GetElementTag(selector, std::move(callback));
+}
+
 void ScriptExecutor::ExpectNavigation() {
   expected_navigation_step_ = ExpectedNavigationStep::EXPECTED;
 }
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 5b12198..f41f34a 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -174,6 +174,10 @@
       const Selector& selector,
       base::OnceCallback<void(const ClientStatus&, const std::string&)>
           callback) override;
+  void GetElementTag(
+      const Selector& selector,
+      base::OnceCallback<void(const ClientStatus&, const std::string&)>
+          callback) override;
   void ExpectNavigation() override;
   bool ExpectedNavigationHasStarted() override;
   bool WaitForNavigation(base::OnceCallback<void(bool)> callback) override;
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index fd80031..5d06133 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -974,6 +974,7 @@
       CREDIT_CARD_CARD_HOLDER_NAME = 5;
       CREDIT_CARD_NUMBER = 6;
       CREDIT_CARD_EXP_MM_YY = 7;
+      CREDIT_CARD_NETWORK = 8;
     }
 
     optional CardField card_field = 1;
diff --git a/components/autofill_assistant/browser/web/web_controller.cc b/components/autofill_assistant/browser/web/web_controller.cc
index 1e4b695..96a9e806 100644
--- a/components/autofill_assistant/browser/web/web_controller.cc
+++ b/components/autofill_assistant/browser/web/web_controller.cc
@@ -138,6 +138,8 @@
 const char* const kGetOuterHtmlScript =
     "function () { return this.outerHTML; }";
 
+const char* const kGetElementTagScript = "function () { return this.tagName; }";
+
 // Javascript code to query whether the document is ready for interact.
 const char* const kIsDocumentReadyForInteract =
     R"(function () {
@@ -1267,18 +1269,6 @@
                      delay_in_millisecond, std::move(callback)));
 }
 
-void WebController::GetOuterHtml(
-    const Selector& selector,
-    base::OnceCallback<void(const ClientStatus&, const std::string&)>
-        callback) {
-  DVLOG(3) << __func__ << " " << selector;
-  FindElement(
-      selector,
-      /* strict_mode= */ true,
-      base::BindOnce(&WebController::OnFindElementForGetOuterHtml,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
 void WebController::GetVisualViewport(
     base::OnceCallback<void(bool, const RectF&)> callback) {
   devtools_client_->GetRuntime()->Evaluate(
@@ -1384,6 +1374,18 @@
   std::move(callback).Run(true, rect);
 }
 
+void WebController::GetOuterHtml(
+    const Selector& selector,
+    base::OnceCallback<void(const ClientStatus&, const std::string&)>
+        callback) {
+  DVLOG(3) << __func__ << " " << selector;
+  FindElement(
+      selector,
+      /* strict_mode= */ true,
+      base::BindOnce(&WebController::OnFindElementForGetOuterHtml,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
 void WebController::OnFindElementForGetOuterHtml(
     base::OnceCallback<void(const ClientStatus&, const std::string&)> callback,
     const ClientStatus& status,
@@ -1421,6 +1423,55 @@
   std::move(callback).Run(OkClientStatus(), value);
 }
 
+void WebController::GetElementTag(
+    const Selector& selector,
+    base::OnceCallback<void(const ClientStatus&, const std::string&)>
+        callback) {
+  DVLOG(3) << __func__ << " " << selector;
+  FindElement(
+      selector,
+      /* strict_mode= */ true,
+      base::BindOnce(&WebController::OnFindElementForGetElementTag,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void WebController::OnFindElementForGetElementTag(
+    base::OnceCallback<void(const ClientStatus&, const std::string&)> callback,
+    const ClientStatus& status,
+    std::unique_ptr<ElementFinder::Result> element_result) {
+  if (!status.ok()) {
+    DVLOG(2) << __func__ << " Failed to find element for GetElementTag";
+    std::move(callback).Run(status, "");
+    return;
+  }
+
+  devtools_client_->GetRuntime()->CallFunctionOn(
+      runtime::CallFunctionOnParams::Builder()
+          .SetObjectId(element_result->object_id)
+          .SetFunctionDeclaration(std::string(kGetElementTagScript))
+          .SetReturnByValue(true)
+          .Build(),
+      element_result->node_frame_id,
+      base::BindOnce(&WebController::OnGetElementTag,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void WebController::OnGetElementTag(
+    base::OnceCallback<void(const ClientStatus&, const std::string&)> callback,
+    const DevtoolsClient::ReplyStatus& reply_status,
+    std::unique_ptr<runtime::CallFunctionOnResult> result) {
+  ClientStatus status =
+      CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
+  if (!status.ok()) {
+    DVLOG(2) << __func__ << " Failed to get element tag for GetElementTag";
+    std::move(callback).Run(status, "");
+    return;
+  }
+  std::string value;
+  SafeGetStringValue(result->GetResult(), &value);
+  std::move(callback).Run(OkClientStatus(), value);
+}
+
 void WebController::WaitForDocumentToBecomeInteractive(
     int remaining_rounds,
     const std::string& object_id,
diff --git a/components/autofill_assistant/browser/web/web_controller.h b/components/autofill_assistant/browser/web/web_controller.h
index 7131905..acd8deca 100644
--- a/components/autofill_assistant/browser/web/web_controller.h
+++ b/components/autofill_assistant/browser/web/web_controller.h
@@ -159,6 +159,12 @@
       base::OnceCallback<void(const ClientStatus&, const std::string&)>
           callback);
 
+  // Return the tag of |selector|.
+  virtual void GetElementTag(
+      const Selector& selector,
+      base::OnceCallback<void(const ClientStatus&, const std::string&)>
+          callback);
+
   // Gets the visual viewport coordinates and size.
   //
   // The rectangle is expressed in absolute CSS coordinates.
@@ -407,6 +413,15 @@
                                               const std::string&)> callback,
                       const DevtoolsClient::ReplyStatus& reply_status,
                       std::unique_ptr<runtime::CallFunctionOnResult> result);
+  void OnFindElementForGetElementTag(
+      base::OnceCallback<void(const ClientStatus&, const std::string&)>
+          callback,
+      const ClientStatus& status,
+      std::unique_ptr<ElementFinder::Result> element_result);
+  void OnGetElementTag(base::OnceCallback<void(const ClientStatus&,
+                                               const std::string&)> callback,
+                       const DevtoolsClient::ReplyStatus& reply_status,
+                       std::unique_ptr<runtime::CallFunctionOnResult> result);
   void OnFindElementForPosition(
       base::OnceCallback<void(bool, const RectF&)> callback,
       const ClientStatus& status,
diff --git a/components/autofill_assistant/browser/web/web_controller_browsertest.cc b/components/autofill_assistant/browser/web/web_controller_browsertest.cc
index 6229227..4457c76 100644
--- a/components/autofill_assistant/browser/web/web_controller_browsertest.cc
+++ b/components/autofill_assistant/browser/web/web_controller_browsertest.cc
@@ -250,6 +250,29 @@
     done_callback.Run();
   }
 
+  ClientStatus GetElementTag(const Selector& selector,
+                             std::string* element_tag_output) {
+    base::RunLoop run_loop;
+    ClientStatus result;
+    web_controller_->GetElementTag(
+        selector, base::BindOnce(&WebControllerBrowserTest::OnGetElementTag,
+                                 base::Unretained(this), run_loop.QuitClosure(),
+                                 &result, element_tag_output));
+    run_loop.Run();
+    return result;
+  }
+
+  void OnGetElementTag(const base::Closure& done_callback,
+                       ClientStatus* successful_output,
+                       std::string* element_tag_output,
+                       const ClientStatus& status,
+                       const std::string& element_tag) {
+    EXPECT_EQ(ACTION_APPLIED, status.proto_status());
+    *successful_output = status;
+    *element_tag_output = element_tag;
+    done_callback.Run();
+  }
+
   void FindElement(const Selector& selector,
                    ClientStatus* status_out,
                    ElementFinder::Result* result_out) {
@@ -1125,6 +1148,26 @@
   EXPECT_EQ(R"(<div id="divToRemove">Text</div>)", html);
 }
 
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetElementTag) {
+  std::string element_tag;
+
+  // Div.
+  ASSERT_EQ(
+      ACTION_APPLIED,
+      GetElementTag(Selector({"#testOuterHtml"}), &element_tag).proto_status());
+  EXPECT_EQ("DIV", element_tag);
+
+  // Select.
+  ASSERT_EQ(ACTION_APPLIED,
+            GetElementTag(Selector({"#select"}), &element_tag).proto_status());
+  EXPECT_EQ("SELECT", element_tag);
+
+  // Input.
+  ASSERT_EQ(ACTION_APPLIED,
+            GetElementTag(Selector({"#input1"}), &element_tag).proto_status());
+  EXPECT_EQ("INPUT", element_tag);
+}
+
 IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, GetAndSetFieldValue) {
   std::vector<Selector> selectors;
   std::vector<std::string> expected_values;
diff --git a/components/background_task_scheduler/BUILD.gn b/components/background_task_scheduler/BUILD.gn
index d2fa8da..95eb33e 100644
--- a/components/background_task_scheduler/BUILD.gn
+++ b/components/background_task_scheduler/BUILD.gn
@@ -24,9 +24,7 @@
   # related permissions for WebView while still wanting to avoid collision
   # between WebView and Chrome.
   android_library("background_task_scheduler_task_ids_java") {
-    sources = [
-      "android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java",
-    ]
+    sources = [ "android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java" ]
   }
 
   android_library("background_task_scheduler_java") {
@@ -125,8 +123,6 @@
   proto_java_library("scheduled_task_java") {
     proto_path =
         "android/java/src/org/chromium/components/background_task_scheduler"
-    sources = [
-      "$proto_path/scheduled_task.proto",
-    ]
+    sources = [ "$proto_path/scheduled_task.proto" ]
   }
 }
diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn
index 3c5dcada..b9e45ef 100644
--- a/components/bookmarks/browser/BUILD.gn
+++ b/components/bookmarks/browser/BUILD.gn
@@ -52,9 +52,7 @@
     "url_index.h",
   ]
 
-  public_deps = [
-    "//components/bookmarks/common",
-  ]
+  public_deps = [ "//components/bookmarks/common" ]
 
   deps = [
     "//base",
@@ -104,9 +102,7 @@
     "bookmark_test_util.h",
   ]
 
-  deps = [
-    ":browser",
-  ]
+  deps = [ ":browser" ]
 }
 
 bundle_data("unit_tests_bundle_data") {
@@ -116,10 +112,8 @@
     "//components/test/data/bookmarks/meta_info_as_string.json",
     "//components/test/data/bookmarks/model_without_sync.json",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 source_set("unit_tests") {
@@ -159,9 +153,7 @@
 # The fuzzer depends on code that is not built on Mac.
 if (!is_mac) {
   fuzzer_test("bookmark_node_data_read_fuzzer") {
-    sources = [
-      "bookmark_node_data_read_fuzzer.cc",
-    ]
+    sources = [ "bookmark_node_data_read_fuzzer.cc" ]
     deps = [
       ":browser",
       "//base",
diff --git a/components/bookmarks/common/BUILD.gn b/components/bookmarks/common/BUILD.gn
index 8ce4153..5985827a 100644
--- a/components/bookmarks/common/BUILD.gn
+++ b/components/bookmarks/common/BUILD.gn
@@ -10,9 +10,7 @@
     "bookmark_pref_names.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   if (is_android) {
     deps += [ "//components/bookmarks/common/android" ]
   }
diff --git a/components/bookmarks/managed/BUILD.gn b/components/bookmarks/managed/BUILD.gn
index e5b6048b..d7ffa237 100644
--- a/components/bookmarks/managed/BUILD.gn
+++ b/components/bookmarks/managed/BUILD.gn
@@ -26,9 +26,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "managed_bookmarks_tracker_unittest.cc",
-  ]
+  sources = [ "managed_bookmarks_tracker_unittest.cc" ]
 
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
 
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn
index 43073181..d6da1d5f 100644
--- a/components/browser_ui/styles/android/BUILD.gn
+++ b/components/browser_ui/styles/android/BUILD.gn
@@ -6,9 +6,8 @@
 import("//ui/android/features.gni")
 
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/components/browser_ui/styles/ChromeColors.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/components/browser_ui/styles/ChromeColors.java" ]
   deps = [
     ":java_resources",
     "//base:base_java",
diff --git a/components/certificate_matching/BUILD.gn b/components/certificate_matching/BUILD.gn
index aa7e3bf..9d237796 100644
--- a/components/certificate_matching/BUILD.gn
+++ b/components/certificate_matching/BUILD.gn
@@ -18,9 +18,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "certificate_principal_pattern_unittest.cc",
-  ]
+  sources = [ "certificate_principal_pattern_unittest.cc" ]
 
   deps = [
     ":certificate_matching",
diff --git a/components/chrome_cleaner/public/proto/BUILD.gn b/components/chrome_cleaner/public/proto/BUILD.gn
index 0f556a43..e6c873c 100644
--- a/components/chrome_cleaner/public/proto/BUILD.gn
+++ b/components/chrome_cleaner/public/proto/BUILD.gn
@@ -5,15 +5,11 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "chrome_prompt.proto",
-  ]
+  sources = [ "chrome_prompt.proto" ]
 }
 
 proto_library("test_only_proto") {
   testonly = true
   generate_python = false
-  sources = [
-    "chrome_prompt_for_tests.proto",
-  ]
+  sources = [ "chrome_prompt_for_tests.proto" ]
 }
diff --git a/components/chrome_cleaner/test/BUILD.gn b/components/chrome_cleaner/test/BUILD.gn
index 593b2bb..e0d00374 100644
--- a/components/chrome_cleaner/test/BUILD.gn
+++ b/components/chrome_cleaner/test/BUILD.gn
@@ -5,9 +5,7 @@
 source_set("test_name_helper") {
   testonly = true
 
-  sources = [
-    "test_name_helper.h",
-  ]
+  sources = [ "test_name_helper.h" ]
 
   public_deps = [
     "//base:base",
diff --git a/components/contextual_search/content/common/mojom/BUILD.gn b/components/contextual_search/content/common/mojom/BUILD.gn
index 74e032c9..70afab49 100644
--- a/components/contextual_search/content/common/mojom/BUILD.gn
+++ b/components/contextual_search/content/common/mojom/BUILD.gn
@@ -6,10 +6,6 @@
 
 mojom("mojom") {
   generate_java = true
-  sources = [
-    "contextual_search_js_api_service.mojom",
-  ]
-  public_deps = [
-    "//url/mojom:url_mojom_gurl",
-  ]
+  sources = [ "contextual_search_js_api_service.mojom" ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/components/contextual_search/core/BUILD.gn b/components/contextual_search/core/BUILD.gn
index de7b3f32..96ef8db 100644
--- a/components/contextual_search/core/BUILD.gn
+++ b/components/contextual_search/core/BUILD.gn
@@ -20,9 +20,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "browser/ctr_aggregator_unittest.cc",
-  ]
+  sources = [ "browser/ctr_aggregator_unittest.cc" ]
 
   deps = [
     ":browser",
diff --git a/components/device_event_log/BUILD.gn b/components/device_event_log/BUILD.gn
index 593b58b..738bf29 100644
--- a/components/device_event_log/BUILD.gn
+++ b/components/device_event_log/BUILD.gn
@@ -12,16 +12,12 @@
 
   defines = [ "DEVICE_EVENT_LOG_IMPLEMENTATION" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "device_event_log_impl_unittest.cc",
-  ]
+  sources = [ "device_event_log_impl_unittest.cc" ]
 
   deps = [
     ":device_event_log",
diff --git a/components/exo/wayland/fuzzer/BUILD.gn b/components/exo/wayland/fuzzer/BUILD.gn
index 15706168..bc613a4 100644
--- a/components/exo/wayland/fuzzer/BUILD.gn
+++ b/components/exo/wayland/fuzzer/BUILD.gn
@@ -36,62 +36,46 @@
 ]
 
 wayland_templater("protocol_dump") {
-  sources = [
-    "misc/dump.tmpl",
-  ]
+  sources = [ "misc/dump.tmpl" ]
   protocols = kDefaultWaylandProtocols
 }
 
 wayland_templater("protocol_graph") {
-  sources = [
-    "misc/graph.dot.tmpl",
-  ]
+  sources = [ "misc/graph.dot.tmpl" ]
   protocols = kDefaultWaylandProtocols
 }
 
 wayland_templater("protocol_docs") {
-  sources = [
-    "misc/docs.md.tmpl",
-  ]
+  sources = [ "misc/docs.md.tmpl" ]
   protocols = kDefaultWaylandProtocols
 }
 
 wayland_templater("actions_tmpl") {
-  sources = [
-    "actions.proto.tmpl",
-  ]
+  sources = [ "actions.proto.tmpl" ]
   protocols = kDefaultWaylandProtocols
 }
 
 wayland_templater("harness_h_tmpl") {
-  sources = [
-    "harness.h.tmpl",
-  ]
+  sources = [ "harness.h.tmpl" ]
   protocols = kDefaultWaylandProtocols
 }
 
 wayland_templater("harness_cc_tmpl") {
-  sources = [
-    "harness.cc.tmpl",
-  ]
+  sources = [ "harness.cc.tmpl" ]
   protocols = kDefaultWaylandProtocols
 }
 
 # We make the seed corpus by enumerating call sequences to all requests
 # using the wayland_sequencer script.
 wayland_templater("corpus") {
-  sources = [
-    "corpus.tmpl",
-  ]
+  sources = [ "corpus.tmpl" ]
   protocols = kDefaultWaylandProtocols
   script_override = "wayland_sequencer.py"
 }
 
 if (use_libfuzzer) {
   fuzzer_test("wayland_fuzzer") {
-    sources = [
-      "fuzzer.cc",
-    ]
+    sources = [ "fuzzer.cc" ]
 
     deps = [
       ":actions",
@@ -112,9 +96,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "harness_unittest.cc",
-  ]
+  sources = [ "harness_unittest.cc" ]
 
   deps = [
     ":actions",
@@ -191,7 +173,5 @@
   # output directory to rebase under the source root.
   proto_out_dir = rebase_path(".", "//")
 
-  deps = [
-    ":actions_tmpl",
-  ]
+  deps = [ ":actions_tmpl" ]
 }
diff --git a/components/favicon/core/history_ui_favicon_request_handler.h b/components/favicon/core/history_ui_favicon_request_handler.h
index 6654c5d..3aa98881 100644
--- a/components/favicon/core/history_ui_favicon_request_handler.h
+++ b/components/favicon/core/history_ui_favicon_request_handler.h
@@ -8,10 +8,6 @@
 #include "components/favicon_base/favicon_callback.h"
 #include "components/keyed_service/core/keyed_service.h"
 
-namespace base {
-class CancelableTaskTracker;
-}
-
 class GURL;
 
 namespace favicon {
@@ -51,8 +47,7 @@
       favicon_base::FaviconRawBitmapCallback callback,
       FaviconRequestPlatform request_platform,
       HistoryUiFaviconRequestOrigin request_origin_for_uma,
-      const GURL& icon_url_for_uma,
-      base::CancelableTaskTracker* tracker) = 0;
+      const GURL& icon_url_for_uma) = 0;
 
   // Requests favicon image at |page_url|.
   // Tries to fetch the icon from local storage and falls back to sync, or to
@@ -65,8 +60,7 @@
       const GURL& page_url,
       favicon_base::FaviconImageCallback callback,
       HistoryUiFaviconRequestOrigin request_origin_for_uma,
-      const GURL& icon_url_for_uma,
-      base::CancelableTaskTracker* tracker) = 0;
+      const GURL& icon_url_for_uma) = 0;
 };
 
 }  // namespace favicon
diff --git a/components/favicon/core/history_ui_favicon_request_handler_impl.cc b/components/favicon/core/history_ui_favicon_request_handler_impl.cc
index c065351..662d2bb7 100644
--- a/components/favicon/core/history_ui_favicon_request_handler_impl.cc
+++ b/components/favicon/core/history_ui_favicon_request_handler_impl.cc
@@ -11,7 +11,6 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/task/cancelable_task_tracker.h"
 #include "components/favicon/core/favicon_service.h"
 #include "components/favicon/core/features.h"
 #include "components/favicon/core/large_icon_service.h"
@@ -120,8 +119,7 @@
     favicon_base::FaviconRawBitmapCallback callback,
     FaviconRequestPlatform request_platform,
     HistoryUiFaviconRequestOrigin request_origin_for_uma,
-    const GURL& icon_url_for_uma,
-    base::CancelableTaskTracker* tracker) {
+    const GURL& icon_url_for_uma) {
   // First attempt to find the icon locally.
   favicon_service_->GetRawFaviconForPageURL(
       page_url, GetIconTypesForLocalQuery(), desired_size_in_pixel,
@@ -131,16 +129,15 @@
           weak_ptr_factory_.GetWeakPtr(), CanQueryGoogleServer(), page_url,
           desired_size_in_pixel,
           /*response_callback=*/std::move(callback), request_platform,
-          request_origin_for_uma, icon_url_for_uma, base::Time::Now(), tracker),
-      tracker);
+          request_origin_for_uma, icon_url_for_uma, base::Time::Now()),
+      &cancelable_task_tracker_);
 }
 
 void HistoryUiFaviconRequestHandlerImpl::GetFaviconImageForPageURL(
     const GURL& page_url,
     favicon_base::FaviconImageCallback callback,
     HistoryUiFaviconRequestOrigin request_origin_for_uma,
-    const GURL& icon_url_for_uma,
-    base::CancelableTaskTracker* tracker) {
+    const GURL& icon_url_for_uma) {
   // First attempt to find the icon locally.
   favicon_service_->GetFaviconImageForPageURL(
       page_url,
@@ -148,8 +145,8 @@
           &HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable,
           weak_ptr_factory_.GetWeakPtr(), CanQueryGoogleServer(), page_url,
           /*response_callback=*/std::move(callback), request_origin_for_uma,
-          icon_url_for_uma, base::Time::Now(), tracker),
-      tracker);
+          icon_url_for_uma, base::Time::Now()),
+      &cancelable_task_tracker_);
 }
 
 void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
@@ -161,7 +158,6 @@
     HistoryUiFaviconRequestOrigin origin_for_uma,
     const GURL& icon_url_for_uma,
     base::Time request_start_time_for_uma,
-    base::CancelableTaskTracker* tracker,
     const favicon_base::FaviconRawBitmapResult& bitmap_result) {
   if (bitmap_result.is_valid()) {
     // The icon comes from local storage now even though it may have been
@@ -187,9 +183,11 @@
         /*local_lookup_callback=*/
         base::BindOnce(
             base::IgnoreResult(&FaviconService::GetRawFaviconForPageURL),
+            // base::Unretained() is safe here as RequestFromGoogleServer()
+            // doesn't execute the callback if |this| is deleted.
             base::Unretained(favicon_service_), page_url,
             GetIconTypesForLocalQuery(), desired_size_in_pixel, kFallbackToHost,
-            repeating_response_callback, tracker),
+            repeating_response_callback, &cancelable_task_tracker_),
         origin_for_uma, icon_url_for_uma, request_start_time_for_uma);
     return;
   }
@@ -220,7 +218,6 @@
     HistoryUiFaviconRequestOrigin origin_for_uma,
     const GURL& icon_url_for_uma,
     base::Time request_start_time_for_uma,
-    base::CancelableTaskTracker* tracker,
     const favicon_base::FaviconImageResult& image_result) {
   if (!image_result.image.IsEmpty()) {
     // The icon comes from local storage now even though it may have been
@@ -248,8 +245,10 @@
         /*local_lookup_callback=*/
         base::BindOnce(
             base::IgnoreResult(&FaviconService::GetFaviconImageForPageURL),
+            // base::Unretained() is safe here as RequestFromGoogleServer()
+            // doesn't execture the callback if |this| is deleted.
             base::Unretained(favicon_service_), page_url,
-            repeating_response_callback, tracker),
+            repeating_response_callback, &cancelable_task_tracker_),
         origin_for_uma, icon_url_for_uma, request_start_time_for_uma);
     return;
   }
diff --git a/components/favicon/core/history_ui_favicon_request_handler_impl.h b/components/favicon/core/history_ui_favicon_request_handler_impl.h
index 710c807..6ed7ff38 100644
--- a/components/favicon/core/history_ui_favicon_request_handler_impl.h
+++ b/components/favicon/core/history_ui_favicon_request_handler_impl.h
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "base/memory/weak_ptr.h"
+#include "base/task/cancelable_task_tracker.h"
 #include "components/favicon/core/history_ui_favicon_request_handler.h"
 #include "components/favicon_base/favicon_types.h"
 
@@ -56,15 +57,12 @@
       favicon_base::FaviconRawBitmapCallback callback,
       FaviconRequestPlatform request_platform,
       HistoryUiFaviconRequestOrigin request_origin_for_uma,
-      const GURL& icon_url_for_uma,
-      base::CancelableTaskTracker* tracker) override;
-
+      const GURL& icon_url_for_uma) override;
   void GetFaviconImageForPageURL(
       const GURL& page_url,
       favicon_base::FaviconImageCallback callback,
       HistoryUiFaviconRequestOrigin request_origin_for_uma,
-      const GURL& icon_url_for_uma,
-      base::CancelableTaskTracker* tracker) override;
+      const GURL& icon_url_for_uma) override;
 
  private:
   // Called after the first attempt to retrieve the icon bitmap from local
@@ -82,7 +80,6 @@
       HistoryUiFaviconRequestOrigin origin_for_uma,
       const GURL& icon_url_for_uma,
       base::Time request_start_time_for_uma,
-      base::CancelableTaskTracker* tracker,
       const favicon_base::FaviconRawBitmapResult& bitmap_result);
 
   // Called after the first attempt to retrieve the icon image from local
@@ -96,12 +93,12 @@
       HistoryUiFaviconRequestOrigin origin_for_uma,
       const GURL& icon_url_for_uma,
       base::Time request_start_time_for_uma,
-      base::CancelableTaskTracker* tracker,
       const favicon_base::FaviconImageResult& image_result);
 
   // Requests an icon from Google favicon server. Since requests work by
   // populating local storage, a |local_lookup_callback| will be needed in case
-  // of success and an |empty_response_callback| in case of failure.
+  // of success and an |empty_response_callback| in case of failure. Neither
+  // callback is run if |this| is deleted before completion.
   void RequestFromGoogleServer(const GURL& page_url,
                                base::OnceClosure empty_response_callback,
                                base::OnceClosure local_lookup_callback,
@@ -137,6 +134,9 @@
   // benefit of grouping.
   std::map<GURL, int> group_callbacks_count_;
 
+  // Needed for using FaviconService.
+  base::CancelableTaskTracker cancelable_task_tracker_;
+
   base::WeakPtrFactory<HistoryUiFaviconRequestHandlerImpl> weak_ptr_factory_{
       this};
 
diff --git a/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc b/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
index 2653e76..09b02c1f 100644
--- a/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
+++ b/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
@@ -231,7 +231,6 @@
   testing::NiceMock<base::MockCallback<
       HistoryUiFaviconRequestHandlerImpl::CanSendHistoryDataGetter>>
       can_send_history_data_getter_;
-  base::CancelableTaskTracker tracker_;
   base::HistogramTester histogram_tester_;
   base::test::ScopedFeatureList scoped_feature_list_;
   HistoryUiFaviconRequestHandlerImpl history_ui_favicon_request_handler_;
@@ -243,17 +242,16 @@
 TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetEmptyBitmap) {
   scoped_feature_list_.InitAndDisableFeature(
       kEnableHistoryFaviconsGoogleServerQuery);
-  EXPECT_CALL(
-      mock_favicon_service_,
-      GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                              kDefaultDesiredSizeInPixel, _, _, &tracker_));
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
+                                      kDefaultDesiredSizeInPixel, _, _, _));
   EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
       .WillOnce([](auto) { return favicon_base::FaviconRawBitmapResult(); });
   favicon_base::FaviconRawBitmapResult result;
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_FALSE(result.is_valid());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -265,17 +263,16 @@
 TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetSyncBitmap) {
   scoped_feature_list_.InitAndDisableFeature(
       kEnableHistoryFaviconsGoogleServerQuery);
-  EXPECT_CALL(
-      mock_favicon_service_,
-      GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                              kDefaultDesiredSizeInPixel, _, _, &tracker_));
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
+                                      kDefaultDesiredSizeInPixel, _, _, _));
   EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
       .WillOnce([](auto) { return CreateTestBitmapResult(); });
   favicon_base::FaviconRawBitmapResult result;
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -288,10 +285,9 @@
   scoped_feature_list_.InitAndDisableFeature(
       kEnableHistoryFaviconsGoogleServerQuery);
   mock_favicon_service_.StoreMockLocalFavicon(GURL(kDummyPageUrl));
-  EXPECT_CALL(
-      mock_favicon_service_,
-      GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                              kDefaultDesiredSizeInPixel, _, _, &tracker_));
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
+                                      kDefaultDesiredSizeInPixel, _, _, _));
   EXPECT_CALL(mock_large_icon_service_,
               TouchIconFromGoogleServer(GURL(kDummyIconUrl)));
   EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
@@ -299,7 +295,7 @@
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -314,10 +310,9 @@
       kEnableHistoryFaviconsGoogleServerQuery, {{"trim_url_path", "false"}});
   mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
   EXPECT_CALL(can_send_history_data_getter_, Run());
-  EXPECT_CALL(
-      mock_favicon_service_,
-      GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                              kDefaultDesiredSizeInPixel, _, _, &tracker_))
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
+                                      kDefaultDesiredSizeInPixel, _, _, _))
       .Times(2);
   EXPECT_CALL(mock_large_icon_service_,
               GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
@@ -327,7 +322,7 @@
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -344,10 +339,9 @@
       kEnableHistoryFaviconsGoogleServerQuery, {{"trim_url_path", "true"}});
   mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
   EXPECT_CALL(can_send_history_data_getter_, Run());
-  EXPECT_CALL(
-      mock_favicon_service_,
-      GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                              kDefaultDesiredSizeInPixel, _, _, &tracker_))
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
+                                      kDefaultDesiredSizeInPixel, _, _, _))
       .Times(2);
   EXPECT_CALL(mock_large_icon_service_,
               GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
@@ -358,7 +352,7 @@
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -373,13 +367,13 @@
   scoped_feature_list_.InitAndDisableFeature(
       kEnableHistoryFaviconsGoogleServerQuery);
   EXPECT_CALL(mock_favicon_service_,
-              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_));
+              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, _));
   EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
       .WillOnce([](auto) { return favicon_base::FaviconRawBitmapResult(); });
   favicon_base::FaviconImageResult result;
   history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result), kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_TRUE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -392,13 +386,13 @@
   scoped_feature_list_.InitAndDisableFeature(
       kEnableHistoryFaviconsGoogleServerQuery);
   EXPECT_CALL(mock_favicon_service_,
-              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_));
+              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, _));
   EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
       .WillOnce([](auto) { return CreateTestBitmapResult(); });
   favicon_base::FaviconImageResult result;
   history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result), kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -412,14 +406,14 @@
       kEnableHistoryFaviconsGoogleServerQuery);
   mock_favicon_service_.StoreMockLocalFavicon(GURL(kDummyPageUrl));
   EXPECT_CALL(mock_favicon_service_,
-              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_));
+              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, _));
   EXPECT_CALL(mock_large_icon_service_,
               TouchIconFromGoogleServer(GURL(kDummyIconUrl)));
   EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
   favicon_base::FaviconImageResult result;
   history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result), kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -435,7 +429,7 @@
   mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
   EXPECT_CALL(can_send_history_data_getter_, Run());
   EXPECT_CALL(mock_favicon_service_,
-              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
+              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, _))
       .Times(2);
   EXPECT_CALL(mock_large_icon_service_,
               GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
@@ -445,7 +439,7 @@
   favicon_base::FaviconImageResult result;
   history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result), kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -463,7 +457,7 @@
   mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
   EXPECT_CALL(can_send_history_data_getter_, Run());
   EXPECT_CALL(mock_favicon_service_,
-              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
+              GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, _))
       .Times(2);
   EXPECT_CALL(mock_large_icon_service_,
               GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
@@ -473,7 +467,7 @@
   favicon_base::FaviconImageResult result;
   history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result), kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
@@ -491,10 +485,9 @@
   EXPECT_CALL(can_send_history_data_getter_, Run()).WillOnce([]() {
     return false;
   });
-  EXPECT_CALL(
-      mock_favicon_service_,
-      GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                              kDefaultDesiredSizeInPixel, _, _, &tracker_))
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
+                                      kDefaultDesiredSizeInPixel, _, _, _))
       .WillOnce([](auto, auto, auto, auto,
                    favicon_base::FaviconRawBitmapCallback callback, auto) {
         std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
@@ -508,7 +501,7 @@
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
 }
 
 TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldResizeSyncBitmap) {
@@ -518,7 +511,7 @@
       kEnableHistoryFaviconsGoogleServerQuery);
   EXPECT_CALL(mock_favicon_service_,
               GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
-                                      kDesiredSizeInPixel, _, _, &tracker_))
+                                      kDesiredSizeInPixel, _, _, _))
       .WillOnce([](auto, auto, auto, auto,
                    favicon_base::FaviconRawBitmapCallback callback, auto) {
         std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
@@ -531,7 +524,7 @@
   history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), kDummyPlatform, kDummyOrigin,
-      /*icon_url_for_uma=*/GURL(), &tracker_);
+      /*icon_url_for_uma=*/GURL());
   EXPECT_TRUE(result.is_valid());
   EXPECT_EQ(gfx::Size(kDesiredSizeInPixel, kDesiredSizeInPixel),
             result.pixel_size);
diff --git a/components/google/core/common/BUILD.gn b/components/google/core/common/BUILD.gn
index 1f7b4cb..a758f5c 100644
--- a/components/google/core/common/BUILD.gn
+++ b/components/google/core/common/BUILD.gn
@@ -25,9 +25,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "google_util_unittest.cc",
-  ]
+  sources = [ "google_util_unittest.cc" ]
 
   deps = [
     ":common",
diff --git a/components/grpc_support/BUILD.gn b/components/grpc_support/BUILD.gn
index d7f8d1a..133aa3015 100644
--- a/components/grpc_support/BUILD.gn
+++ b/components/grpc_support/BUILD.gn
@@ -1,7 +1,5 @@
 source_set("headers") {
-  public = [
-    "include/bidirectional_stream_c.h",
-  ]
+  public = [ "include/bidirectional_stream_c.h" ]
 }
 
 source_set("grpc_support") {
@@ -23,9 +21,7 @@
 # Depends on ":grpc_support" implementation.
 source_set("bidirectional_stream_unittest") {
   testonly = true
-  sources = [
-    "bidirectional_stream_unittest.cc",
-  ]
+  sources = [ "bidirectional_stream_unittest.cc" ]
 
   deps = [
     ":grpc_support",
@@ -34,17 +30,13 @@
     "//net:test_support",
   ]
 
-  public_deps = [
-    "//components/grpc_support/test:get_stream_engine_header",
-  ]
+  public_deps = [ "//components/grpc_support/test:get_stream_engine_header" ]
 }
 
 # Depends on ":headers" to avoid ":grpc_support" implementation.
 source_set("bidirectional_stream_test") {
   testonly = true
-  sources = [
-    "bidirectional_stream_unittest.cc",
-  ]
+  sources = [ "bidirectional_stream_unittest.cc" ]
 
   deps = [
     ":headers",
@@ -53,7 +45,5 @@
     "//net:test_support",
   ]
 
-  public_deps = [
-    "//components/grpc_support/test:get_stream_engine_header",
-  ]
+  public_deps = [ "//components/grpc_support/test:get_stream_engine_header" ]
 }
diff --git a/components/grpc_support/test/BUILD.gn b/components/grpc_support/test/BUILD.gn
index d0b39f6..62b72d2 100644
--- a/components/grpc_support/test/BUILD.gn
+++ b/components/grpc_support/test/BUILD.gn
@@ -1,8 +1,6 @@
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "get_stream_engine.cc",
-  ]
+  sources = [ "get_stream_engine.cc" ]
 
   deps = [
     "//base",
@@ -15,9 +13,7 @@
 
 source_set("get_stream_engine_header") {
   testonly = true
-  sources = [
-    "get_stream_engine.h",
-  ]
+  sources = [ "get_stream_engine.h" ]
 
   deps = [
     "//base",
diff --git a/components/heap_profiling/BUILD.gn b/components/heap_profiling/BUILD.gn
index cc8281c6..506f6f8 100644
--- a/components/heap_profiling/BUILD.gn
+++ b/components/heap_profiling/BUILD.gn
@@ -26,21 +26,15 @@
 if (is_android) {
   generate_jni("jni_headers") {
     testonly = true
-    sources = [
-      "javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java",
-    ]
+    sources = [ "javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java" ]
   }
 
   # This library must be included by the apk_under_test in order for the JNI
   # shim to function correctly.
   android_library("heap_profiling_java_test_support") {
     testonly = true
-    sources = [
-      "javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java",
-    ]
-    deps = [
-      "//base:base_java",
-    ]
+    sources = [ "javatests/src/org/chromium/components/heap_profiling/HeapProfilingTestShim.java" ]
+    deps = [ "//base:base_java" ]
   }
 }
 
diff --git a/components/history/core/browser/BUILD.gn b/components/history/core/browser/BUILD.gn
index f02b61b..877daac 100644
--- a/components/history/core/browser/BUILD.gn
+++ b/components/history/core/browser/BUILD.gn
@@ -181,10 +181,8 @@
     "//components/test/data/history/thumbnail_wild/Favicons.v5.sizes.sql",
     "//components/test/data/history/thumbnail_wild/Favicons.v6.init.sql",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 source_set("unit_tests") {
diff --git a/components/history/core/common/BUILD.gn b/components/history/core/common/BUILD.gn
index d2f7a71..51fed02 100644
--- a/components/history/core/common/BUILD.gn
+++ b/components/history/core/common/BUILD.gn
@@ -10,16 +10,12 @@
     "thumbnail_score.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "thumbnail_score_unittest.cc",
-  ]
+  sources = [ "thumbnail_score_unittest.cc" ]
   deps = [
     ":common",
     "//testing/gtest",
diff --git a/components/language/content/browser/BUILD.gn b/components/language/content/browser/BUILD.gn
index ec73d42..e80814d9a 100644
--- a/components/language/content/browser/BUILD.gn
+++ b/components/language/content/browser/BUILD.gn
@@ -5,12 +5,8 @@
 import("//build/config/compiler/compiler.gni")
 
 source_set("language_code_locator") {
-  sources = [
-    "language_code_locator.h",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "language_code_locator.h" ]
+  deps = [ "//base" ]
 }
 
 static_library("browser") {
diff --git a/components/language/content/browser/ulp_language_code_locator/BUILD.gn b/components/language/content/browser/ulp_language_code_locator/BUILD.gn
index 99c5985..15547fe 100644
--- a/components/language/content/browser/ulp_language_code_locator/BUILD.gn
+++ b/components/language/content/browser/ulp_language_code_locator/BUILD.gn
@@ -12,12 +12,8 @@
     "geolanguage-data_rank1.bin",
     "geolanguage-data_rank2.bin",
   ]
-  sources = [
-    "ulp_language_code_locator_helper.h.tmpl",
-  ]
-  outputs = [
-    "$target_gen_dir/ulp_language_code_locator_helper.h",
-  ]
+  sources = [ "ulp_language_code_locator_helper.h.tmpl" ]
+  outputs = [ "$target_gen_dir/ulp_language_code_locator_helper.h" ]
 
   args = [
     "--data",
diff --git a/components/language/ios/browser/BUILD.gn b/components/language/ios/browser/BUILD.gn
index aeb5cd3d..c07c701 100644
--- a/components/language/ios/browser/BUILD.gn
+++ b/components/language/ios/browser/BUILD.gn
@@ -23,9 +23,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "ios_language_detection_tab_helper_observer_bridge_unittest.mm",
-  ]
+  sources = [ "ios_language_detection_tab_helper_observer_bridge_unittest.mm" ]
   deps = [
     ":browser",
     "//components/translate/core/common",
diff --git a/components/leveldb_proto/BUILD.gn b/components/leveldb_proto/BUILD.gn
index 6dae43b..cdef4cdfb 100644
--- a/components/leveldb_proto/BUILD.gn
+++ b/components/leveldb_proto/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "internal/proto/shared_db_metadata.proto",
-  ]
+  sources = [ "internal/proto/shared_db_metadata.proto" ]
 }
 
 component("leveldb_proto") {
@@ -42,9 +40,7 @@
     "public/shared_proto_database_client_list.h",
   ]
   defines = [ "IS_LEVELDB_PROTO_IMPL" ]
-  deps = [
-    ":proto",
-  ]
+  deps = [ ":proto" ]
 
   public_deps = [
     "//base",
@@ -55,9 +51,7 @@
 
 source_set("test_support") {
   testonly = true
-  sources = [
-    "testing/fake_db.h",
-  ]
+  sources = [ "testing/fake_db.h" ]
 
   public_deps = [
     ":leveldb_proto",
diff --git a/components/leveldb_proto/testing/proto/BUILD.gn b/components/leveldb_proto/testing/proto/BUILD.gn
index 52c7233..21a9c9e 100644
--- a/components/leveldb_proto/testing/proto/BUILD.gn
+++ b/components/leveldb_proto/testing/proto/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "test_db.proto",
-  ]
+  sources = [ "test_db.proto" ]
 }
diff --git a/components/minidump_uploader/BUILD.gn b/components/minidump_uploader/BUILD.gn
index a0f823b7..f8e9301 100644
--- a/components/minidump_uploader/BUILD.gn
+++ b/components/minidump_uploader/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/android/rules.gni")
 
 generate_jni("minidump_uploader_jni_headers") {
-  sources = [
-    "android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java",
-  ]
+  sources = [ "android/java/src/org/chromium/components/minidump_uploader/CrashReportMimeWriter.java" ]
 }
 
 static_library("minidump_uploader") {
diff --git a/components/open_from_clipboard/BUILD.gn b/components/open_from_clipboard/BUILD.gn
index 0b05b9d..451ed147 100644
--- a/components/open_from_clipboard/BUILD.gn
+++ b/components/open_from_clipboard/BUILD.gn
@@ -34,9 +34,7 @@
     "clipboard_recent_content_features.cc",
     "clipboard_recent_content_features.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 # Helper classes used by "open_from_clipboard" target. These classes must have
@@ -46,9 +44,7 @@
     "clipboard_recent_content_impl_ios.h",
     "clipboard_recent_content_impl_ios.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   assert_no_deps = [ "//base:i18n" ]
   if (is_ios) {
     configs += [ "//build/config/compiler:enable_arc" ]
@@ -74,9 +70,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "clipboard_recent_content_ios_unittest.mm",
-  ]
+  sources = [ "clipboard_recent_content_ios_unittest.mm" ]
 
   deps = [
     ":open_from_clipboard",
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index c0e023c..65e268c 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -367,12 +367,8 @@
     "generation/password_generator.cc",
     "generation/password_generator.h",
   ]
-  public_deps = [
-    "//components/autofill/core/browser/proto",
-  ]
-  deps = [
-    "//base",
-  ]
+  public_deps = [ "//components/autofill/core/browser/proto" ]
+  deps = [ "//base" ]
 }
 
 if (is_android) {
@@ -385,9 +381,7 @@
 }
 
 fuzzable_proto_library("proto") {
-  sources = [
-    "android_affiliation/affiliation_api.proto",
-  ]
+  sources = [ "android_affiliation/affiliation_api.proto" ]
 }
 
 jumbo_static_library("password_hash_data") {
@@ -506,10 +500,8 @@
     "//components/test/data/password_manager/login_db_v9.sql",
     "//components/test/data/password_manager/login_db_v9_without_use_additional_auth_field.sql",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 source_set("unit_tests") {
@@ -660,9 +652,7 @@
 }
 
 fuzzer_test("csv_reader_fuzzer") {
-  sources = [
-    "import/password_csv_reader_fuzzer.cc",
-  ]
+  sources = [ "import/password_csv_reader_fuzzer.cc" ]
   deps = [
     ":browser",
     ":csv",
@@ -675,9 +665,8 @@
 
 if (use_libfuzzer) {
   fuzzer_test("lookup_affiliation_response_parser_fuzzer") {
-    sources = [
-      "android_affiliation/lookup_affiliation_response_parser_fuzzer.cc",
-    ]
+    sources =
+        [ "android_affiliation/lookup_affiliation_response_parser_fuzzer.cc" ]
     deps = [
       ":browser",
       ":proto",
@@ -688,9 +677,7 @@
   }
 
   fuzzer_test("password_generator_proto_fuzzer") {
-    sources = [
-      "generation/password_generator_proto_fuzzer.cc",
-    ]
+    sources = [ "generation/password_generator_proto_fuzzer.cc" ]
     deps = [
       ":password_generator",
       "//components/autofill/core/browser/proto",
@@ -720,9 +707,7 @@
 
 source_set("affiliation_unittests") {
   testonly = true
-  sources = [
-    "android_affiliation/affiliation_utils_unittest.cc",
-  ]
+  sources = [ "android_affiliation/affiliation_utils_unittest.cc" ]
   deps = [
     ":affiliation",
     "//base",
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn b/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn
index 9f24aff..038e99da 100644
--- a/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn
+++ b/components/password_manager/core/browser/form_parsing/fuzzer/BUILD.gn
@@ -44,9 +44,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "data_accessor_unittest.cc",
-  ]
+  sources = [ "data_accessor_unittest.cc" ]
 
   deps = [
     ":fuzzer_support",
@@ -68,9 +66,7 @@
 # new fuzzer has the "_generic" suffix on its target name.
 
 fuzzer_test("password_manager_form_parser_fuzzer") {
-  sources = [
-    "form_parser_fuzzer.cc",
-  ]
+  sources = [ "form_parser_fuzzer.cc" ]
 
   deps = [
     ":fuzzer_support",
@@ -84,9 +80,7 @@
 }
 
 fuzzer_test("password_manager_form_parser_proto_fuzzer") {
-  sources = [
-    "form_parser_proto_fuzzer.cc",
-  ]
+  sources = [ "form_parser_proto_fuzzer.cc" ]
 
   deps = [
     ":form_data_essentials_proto",
@@ -103,7 +97,5 @@
 }
 
 proto_library("form_data_essentials_proto") {
-  sources = [
-    "form_data_essentials.proto",
-  ]
+  sources = [ "form_data_essentials.proto" ]
 }
diff --git a/components/password_manager/core/browser/leak_detection/BUILD.gn b/components/password_manager/core/browser/leak_detection/BUILD.gn
index 7c3dc53..608e98d 100644
--- a/components/password_manager/core/browser/leak_detection/BUILD.gn
+++ b/components/password_manager/core/browser/leak_detection/BUILD.gn
@@ -6,9 +6,7 @@
 import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
 
 fuzzable_proto_library("proto") {
-  sources = [
-    "leak_detection_api.proto",
-  ]
+  sources = [ "leak_detection_api.proto" ]
 }
 
 source_set("leak_detection_interface_headers") {
@@ -97,7 +95,5 @@
 }
 
 group("fuzzers") {
-  deps = [
-    "//components/password_manager/core/browser/leak_detection/fuzzer",
-  ]
+  deps = [ "//components/password_manager/core/browser/leak_detection/fuzzer" ]
 }
diff --git a/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn b/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn
index 323b1db..0b09d14a 100644
--- a/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn
+++ b/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn
@@ -5,18 +5,12 @@
 }
 
 fuzzer_test("cipher_encrypt_fuzzer") {
-  sources = [
-    "cipher_encrypt_fuzzer.cc",
-  ]
-  deps = [
-    "//components/password_manager/core/browser/leak_detection",
-  ]
+  sources = [ "cipher_encrypt_fuzzer.cc" ]
+  deps = [ "//components/password_manager/core/browser/leak_detection" ]
 }
 
 fuzzer_test("cypher_encrypt_with_key_fuzzer") {
-  sources = [
-    "cypher_encrypt_with_key_fuzzer.cc",
-  ]
+  sources = [ "cypher_encrypt_with_key_fuzzer.cc" ]
   deps = [
     "//components/password_manager/core/browser/leak_detection",
     "//third_party/private-join-and-compute/src:ec_commutative_cipher",
@@ -24,18 +18,12 @@
 }
 
 fuzzer_test("cypher_reencrypt_fuzzer") {
-  sources = [
-    "cypher_reencrypt_fuzzer.cc",
-  ]
-  deps = [
-    "//components/password_manager/core/browser/leak_detection",
-  ]
+  sources = [ "cypher_reencrypt_fuzzer.cc" ]
+  deps = [ "//components/password_manager/core/browser/leak_detection" ]
 }
 
 fuzzer_test("cypher_decrypt_fuzzer") {
-  sources = [
-    "cypher_decrypt_fuzzer.cc",
-  ]
+  sources = [ "cypher_decrypt_fuzzer.cc" ]
   deps = [
     "//components/password_manager/core/browser/leak_detection",
     "//third_party/private-join-and-compute/src:ec_commutative_cipher",
diff --git a/components/password_manager/core/common/BUILD.gn b/components/password_manager/core/common/BUILD.gn
index 3aadb38..426e51d 100644
--- a/components/password_manager/core/common/BUILD.gn
+++ b/components/password_manager/core/common/BUILD.gn
@@ -32,9 +32,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "credential_manager_types_unittest.cc",
-  ]
+  sources = [ "credential_manager_types_unittest.cc" ]
 
   if (is_ios) {
     sources += [ "passwords_directory_util_ios_unittest.cc" ]
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 1a04f59..400069f 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -643,6 +643,7 @@
         'CursorHighlightEnabled',
         'CaretHighlightEnabled',
         'MonoAudioEnabled',
+        'AccessibilityShortcutsEnabled',
         'AutoclickEnabled',
         'DeviceLoginScreenDefaultLargeCursorEnabled',
         'DeviceLoginScreenDefaultSpokenFeedbackEnabled',
@@ -10302,6 +10303,31 @@
           If this policy is left unset, high contrast mode is disabled initially but can be enabled by the user anytime.'''
     },
     {
+      'name': 'AccessibilityShortcutsEnabled',
+      'owners': ['amraboelkher@chromium.org', 'emaxx@chromium.org'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome_os:81-'],
+      'features': {
+        'can_be_recommended': True,
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': True,
+      'id': 659,
+      'caption': '''Enable accessibility features shortcuts''',
+      'tags': [],
+      'desc': '''Enable accessibility features shortcuts.
+
+          If this policy is set to true, accessibility features shortcuts will always be enabled.
+
+          If this policy is set to false, accessibility features shortcuts will always be disabled.
+
+          If you set this policy, users cannot change or override it.
+
+          If this policy is left unset, accessibility features shortcuts will be enabled by default.'''
+    },
+    {
       'name': 'VirtualKeyboardEnabled',
       'owners': ['file://components/policy/resources/OWNERS'],
       'type': 'main',
@@ -20243,6 +20269,6 @@
   ],
   'placeholders': [],
   'deleted_policy_ids': [412, 546, 562, 569, 578],
-  'highest_id_currently_used': 658,
+  'highest_id_currently_used': 659,
   'highest_atomic_group_id_currently_used': 38
 }
diff --git a/components/search_provider_logos/BUILD.gn b/components/search_provider_logos/BUILD.gn
index 5895f9b1..b5653a1 100644
--- a/components/search_provider_logos/BUILD.gn
+++ b/components/search_provider_logos/BUILD.gn
@@ -76,10 +76,8 @@
     "//components/test/data/search_provider_logos/ddljson_ios4.json",
     "//components/test/data/search_provider_logos/ddljson_ios4_fp.json",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 source_set("unit_tests") {
diff --git a/components/send_tab_to_self/BUILD.gn b/components/send_tab_to_self/BUILD.gn
index d00fedc..8fc934e 100644
--- a/components/send_tab_to_self/BUILD.gn
+++ b/components/send_tab_to_self/BUILD.gn
@@ -35,9 +35,7 @@
     "//ui/base",
     "//url",
   ]
-  public_deps = [
-    "//components/send_tab_to_self/proto:send_tab_to_self_proto",
-  ]
+  public_deps = [ "//components/send_tab_to_self/proto:send_tab_to_self_proto" ]
   if (is_android) {
     sources += [
       "send_tab_to_self_infobar_delegate.cc",
diff --git a/components/send_tab_to_self/proto/BUILD.gn b/components/send_tab_to_self/proto/BUILD.gn
index afe1e55..52848e85 100644
--- a/components/send_tab_to_self/proto/BUILD.gn
+++ b/components/send_tab_to_self/proto/BUILD.gn
@@ -6,8 +6,6 @@
 
 proto_library("send_tab_to_self_proto") {
   import_dirs = [ "//components/sync/protocol" ]
-  sources = [
-    "send_tab_to_self.proto",
-  ]
+  sources = [ "send_tab_to_self.proto" ]
   link_deps = [ "//components/sync/protocol:protocol" ]
 }
diff --git a/components/services/heap_profiling/BUILD.gn b/components/services/heap_profiling/BUILD.gn
index 8dcbe7d..9b5f6a09 100644
--- a/components/services/heap_profiling/BUILD.gn
+++ b/components/services/heap_profiling/BUILD.gn
@@ -29,9 +29,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "json_exporter_unittest.cc",
-  ]
+  sources = [ "json_exporter_unittest.cc" ]
   deps = [
     ":heap_profiling",
     "//base",
diff --git a/components/services/heap_profiling/public/cpp/BUILD.gn b/components/services/heap_profiling/public/cpp/BUILD.gn
index e016a91..4ca629d5b 100644
--- a/components/services/heap_profiling/public/cpp/BUILD.gn
+++ b/components/services/heap_profiling/public/cpp/BUILD.gn
@@ -28,9 +28,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "switches_unittest.cc",
-  ]
+  sources = [ "switches_unittest.cc" ]
   deps = [
     ":cpp",
     "//base",
diff --git a/components/services/heap_profiling/public/mojom/BUILD.gn b/components/services/heap_profiling/public/mojom/BUILD.gn
index bc27caa3..ff36fda 100644
--- a/components/services/heap_profiling/public/mojom/BUILD.gn
+++ b/components/services/heap_profiling/public/mojom/BUILD.gn
@@ -9,7 +9,5 @@
     "heap_profiling_client.mojom",
     "heap_profiling_service.mojom",
   ]
-  deps = [
-    "//mojo/public/mojom/base",
-  ]
+  deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc b/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
index 5c769973..dbfd1bc7 100644
--- a/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
+++ b/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
@@ -10,21 +10,35 @@
 #include "components/signin/internal/identity_manager/account_tracker_service.h"
 #include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
 #include "components/signin/public/base/multilogin_parameters.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
 #include "google_apis/gaia/core_account_id.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
 namespace signin {
 
+AccountsCookieMutatorImpl::MultiloginHelperWrapper::MultiloginHelperWrapper(
+    std::unique_ptr<OAuthMultiloginHelper> helper)
+    : helper_(std::move(helper)) {}
+
+AccountsCookieMutatorImpl::MultiloginHelperWrapper::~MultiloginHelperWrapper() =
+    default;
+
 AccountsCookieMutatorImpl::AccountsCookieMutatorImpl(
+    SigninClient* signin_client,
+    ProfileOAuth2TokenService* token_service,
     GaiaCookieManagerService* gaia_cookie_manager_service,
     AccountTrackerService* account_tracker_service)
-    : gaia_cookie_manager_service_(gaia_cookie_manager_service),
+    : signin_client_(signin_client),
+      token_service_(token_service),
+      gaia_cookie_manager_service_(gaia_cookie_manager_service),
       account_tracker_service_(account_tracker_service) {
+  DCHECK(signin_client_);
+  DCHECK(token_service_);
   DCHECK(gaia_cookie_manager_service_);
   DCHECK(account_tracker_service_);
 }
 
-AccountsCookieMutatorImpl::~AccountsCookieMutatorImpl() {}
+AccountsCookieMutatorImpl::~AccountsCookieMutatorImpl() = default;
 
 void AccountsCookieMutatorImpl::AddAccountToCookie(
     const CoreAccountId& account_id,
@@ -58,6 +72,32 @@
       std::move(set_accounts_in_cookies_completed_callback));
 }
 
+std::unique_ptr<AccountsCookieMutator::SetAccountsInCookieTask>
+AccountsCookieMutatorImpl::SetAccountsInCookieForPartition(
+    PartitionDelegate* partition_delegate,
+    const MultiloginParameters& parameters,
+    base::OnceCallback<void(SetAccountsInCookieResult)>
+        set_accounts_in_cookies_completed_callback) {
+  // The default partition must go through the GaiaCookieManagerService.
+  DCHECK_NE(signin_client_->GetCookieManager(),
+            partition_delegate->GetCookieManagerForPartition())
+      << "The default partition is passed to "
+      << "SetAccountsInCookieForPartition(). Use SetAccountsInCookie() "
+      << "instead.";
+
+  std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> accounts;
+  for (const auto& account_id : parameters.accounts_to_send) {
+    accounts.push_back(make_pair(
+        account_id, account_tracker_service_->GetAccountInfo(account_id).gaia));
+  }
+
+  return std::make_unique<MultiloginHelperWrapper>(
+      std::make_unique<OAuthMultiloginHelper>(
+          signin_client_, partition_delegate, token_service_, parameters.mode,
+          accounts, /*external_cc_result=*/std::string(),
+          std::move(set_accounts_in_cookies_completed_callback)));
+}
+
 void AccountsCookieMutatorImpl::TriggerCookieJarUpdate() {
   gaia_cookie_manager_service_->TriggerListAccounts();
 }
diff --git a/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h b/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
index f363638..d62c176 100644
--- a/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
+++ b/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
@@ -8,12 +8,16 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "components/signin/internal/identity_manager/oauth_multilogin_helper.h"
 #include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
 
 class AccountTrackerService;
 class GaiaCookieManagerService;
+class ProfileOAuth2TokenService;
+class SigninClient;
 
 namespace gaia {
 class GaiaSource;
@@ -25,6 +29,8 @@
 class AccountsCookieMutatorImpl : public AccountsCookieMutator {
  public:
   explicit AccountsCookieMutatorImpl(
+      SigninClient* signin_client,
+      ProfileOAuth2TokenService* token_service,
       GaiaCookieManagerService* gaia_cookie_manager_service,
       AccountTrackerService* account_tracker_service);
   ~AccountsCookieMutatorImpl() override;
@@ -46,6 +52,12 @@
       base::OnceCallback<void(SetAccountsInCookieResult)>
           set_accounts_in_cookies_completed_callback) override;
 
+  std::unique_ptr<SetAccountsInCookieTask> SetAccountsInCookieForPartition(
+      PartitionDelegate* partition_delegate,
+      const MultiloginParameters& parameters,
+      base::OnceCallback<void(SetAccountsInCookieResult)>
+          set_accounts_in_cookies_completed_callback) override;
+
   void TriggerCookieJarUpdate() override;
 
 #if defined(OS_IOS)
@@ -55,6 +67,17 @@
   void LogOutAllAccounts(gaia::GaiaSource source) override;
 
  private:
+  class MultiloginHelperWrapper : public SetAccountsInCookieTask {
+   public:
+    MultiloginHelperWrapper(std::unique_ptr<OAuthMultiloginHelper> helper);
+    ~MultiloginHelperWrapper() override;
+
+   private:
+    std::unique_ptr<OAuthMultiloginHelper> helper_;
+  };
+
+  SigninClient* signin_client_;
+  ProfileOAuth2TokenService* token_service_;
   GaiaCookieManagerService* gaia_cookie_manager_service_;
   AccountTrackerService* account_tracker_service_;
 
diff --git a/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc b/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
index 726c6b74..d0cef277 100644
--- a/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
+++ b/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
@@ -928,6 +928,18 @@
   HandleNextRequest();
 }
 
+std::unique_ptr<GaiaAuthFetcher>
+GaiaCookieManagerService::CreateGaiaAuthFetcherForPartition(
+    GaiaAuthConsumer* consumer) {
+  return signin_client_->CreateGaiaAuthFetcher(consumer,
+                                               gaia::GaiaSource::kChrome);
+}
+
+network::mojom::CookieManager*
+GaiaCookieManagerService::GetCookieManagerForPartition() {
+  return signin_client_->GetCookieManager();
+}
+
 void GaiaCookieManagerService::InitializeListedAccountsIds() {
   for (gaia::ListedAccount& account : listed_accounts_) {
     DCHECK(account.id.empty());
@@ -1000,8 +1012,8 @@
   }
 
   oauth_multilogin_helper_ = std::make_unique<signin::OAuthMultiloginHelper>(
-      signin_client_, token_service_, requests_.front().GetMultiloginMode(),
-      requests_.front().GetAccounts(),
+      signin_client_, this, token_service_,
+      requests_.front().GetMultiloginMode(), requests_.front().GetAccounts(),
       external_cc_result_fetcher_.GetExternalCcResult(),
       base::BindOnce(&GaiaCookieManagerService::OnSetAccountsFinished,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/signin/internal/identity_manager/gaia_cookie_manager_service.h b/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
index ca91666..ee59624 100644
--- a/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
+++ b/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
@@ -21,6 +21,7 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
 #include "components/signin/public/base/signin_client.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_auth_util.h"
@@ -54,8 +55,10 @@
 // Also checks the External CC result to ensure no services that consume the
 // GAIA cookie are blocked (such as youtube). This is executed once for the
 // lifetime of this object, when the first call is made to AddAccountToCookie.
-class GaiaCookieManagerService : public GaiaAuthConsumer,
-                                 public network::mojom::CookieChangeListener {
+class GaiaCookieManagerService
+    : public GaiaAuthConsumer,
+      public signin::AccountsCookieMutator::PartitionDelegate,
+      public network::mojom::CookieChangeListener {
  public:
   using AccountIdGaiaIdPair = std::pair<CoreAccountId, std::string>;
 
@@ -331,6 +334,11 @@
   void OnLogOutSuccess() override;
   void OnLogOutFailure(const GoogleServiceAuthError& error) override;
 
+  // Overridden from signin::AccountsCookieMutator::PartitionDelegate.
+  std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition(
+      GaiaAuthConsumer* consumer) override;
+  network::mojom::CookieManager* GetCookieManagerForPartition() override;
+
   // Helper method to initialize listed accounts ids.
   void InitializeListedAccountsIds();
 
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
index 068076f..f796f320 100644
--- a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
+++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
 #include "components/signin/public/base/signin_client.h"
 #include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -20,6 +21,8 @@
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
+namespace signin {
+
 namespace {
 
 constexpr int kMaxFetcherRetries = 3;
@@ -36,7 +39,7 @@
 }
 
 CoreAccountId FindAccountIdForGaiaId(
-    const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& accounts,
+    const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair>& accounts,
     const std::string& gaia_id) {
   for (const auto& account : accounts) {
     if (gaia_id == account.second)
@@ -47,30 +50,31 @@
 
 }  // namespace
 
-namespace signin {
-
 OAuthMultiloginHelper::OAuthMultiloginHelper(
     SigninClient* signin_client,
+    AccountsCookieMutator::PartitionDelegate* partition_delegate,
     ProfileOAuth2TokenService* token_service,
     gaia::MultiloginMode mode,
-    const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>& accounts,
+    const std::vector<AccountIdGaiaIdPair>& accounts,
     const std::string& external_cc_result,
     base::OnceCallback<void(SetAccountsInCookieResult)> callback)
     : signin_client_(signin_client),
+      partition_delegate_(partition_delegate),
       token_service_(token_service),
       mode_(mode),
       accounts_(accounts),
       external_cc_result_(external_cc_result),
       callback_(std::move(callback)) {
   DCHECK(signin_client_);
+  DCHECK(partition_delegate_);
   DCHECK(token_service_);
   DCHECK(!accounts_.empty());
   DCHECK(callback_);
 
 #ifndef NDEBUG
   // Check that there is no duplicate accounts.
-  std::set<GaiaCookieManagerService::AccountIdGaiaIdPair>
-      accounts_no_duplicates(accounts_.begin(), accounts_.end());
+  std::set<AccountIdGaiaIdPair> accounts_no_duplicates(accounts_.begin(),
+                                                       accounts_.end());
   DCHECK_EQ(accounts_.size(), accounts_no_duplicates.size());
 #endif
 
@@ -125,7 +129,7 @@
 void OAuthMultiloginHelper::StartFetchingMultiLogin() {
   DCHECK_EQ(gaia_id_token_pairs_.size(), accounts_.size());
   gaia_auth_fetcher_ =
-      signin_client_->CreateGaiaAuthFetcher(this, gaia::GaiaSource::kChrome);
+      partition_delegate_->CreateGaiaAuthFetcherForPartition(this);
   gaia_auth_fetcher_->StartOAuthMultilogin(mode_, gaia_id_token_pairs_,
                                            external_cc_result_);
 }
@@ -179,7 +183,7 @@
     const OAuthMultiloginResult& result) {
   DCHECK(cookies_to_set_.empty());
   network::mojom::CookieManager* cookie_manager =
-      signin_client_->GetCookieManager();
+      partition_delegate_->GetCookieManagerForPartition();
   const std::vector<net::CanonicalCookie>& cookies = result.cookies();
 
   for (const net::CanonicalCookie& cookie : cookies) {
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.h b/components/signin/internal/identity_manager/oauth_multilogin_helper.h
index 3e88ae58..ab3e5d9 100644
--- a/components/signin/internal/identity_manager/oauth_multilogin_helper.h
+++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.h
@@ -13,8 +13,8 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "components/signin/internal/identity_manager/gaia_cookie_manager_service.h"
 #include "components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
 #include "google_apis/gaia/core_account_id.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
@@ -23,7 +23,6 @@
 class GaiaAuthFetcher;
 class GoogleServiceAuthError;
 class ProfileOAuth2TokenService;
-class SigninClient;
 
 namespace signin {
 
@@ -37,12 +36,14 @@
 // It is safe to delete this object from within the callbacks.
 class OAuthMultiloginHelper : public GaiaAuthConsumer {
  public:
+  using AccountIdGaiaIdPair = std::pair<CoreAccountId, std::string>;
+
   OAuthMultiloginHelper(
       SigninClient* signin_client,
+      AccountsCookieMutator::PartitionDelegate* partition_delegate,
       ProfileOAuth2TokenService* token_service,
       gaia::MultiloginMode mode,
-      const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>&
-          accounts,
+      const std::vector<AccountIdGaiaIdPair>& accounts,
       const std::string& external_cc_result,
       base::OnceCallback<void(SetAccountsInCookieResult)> callback);
 
@@ -73,13 +74,14 @@
                    net::CanonicalCookie::CookieInclusionStatus status);
 
   SigninClient* signin_client_;
+  AccountsCookieMutator::PartitionDelegate* partition_delegate_;
   ProfileOAuth2TokenService* token_service_;
 
   int fetcher_retries_ = 0;
 
   gaia::MultiloginMode mode_;
   // Account ids to set in the cookie.
-  const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair> accounts_;
+  const std::vector<AccountIdGaiaIdPair> accounts_;
   // See GaiaCookieManagerService::ExternalCcResultFetcher for details.
   const std::string external_cc_result_;
   // Access tokens, in the same order as the account ids.
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
index 70fe65f0..3df6e75 100644
--- a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
+++ b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
@@ -11,6 +11,7 @@
 #include "components/prefs/testing_pref_service.h"
 #include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
 #include "components/signin/public/base/test_signin_client.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
 #include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "services/network/test/test_cookie_manager.h"
@@ -162,24 +163,21 @@
 
 }  // namespace
 
-class OAuthMultiloginHelperTest : public testing::Test {
+class OAuthMultiloginHelperTest
+    : public testing::Test,
+      public AccountsCookieMutator::PartitionDelegate {
  public:
   OAuthMultiloginHelperTest()
       : test_signin_client_(&pref_service_),
         mock_token_service_(&pref_service_) {
-    std::unique_ptr<MockCookieManager> cookie_manager =
-        std::make_unique<MockCookieManager>();
-    mock_cookie_manager_ = cookie_manager.get();
-    test_signin_client_.set_cookie_manager(std::move(cookie_manager));
   }
 
   ~OAuthMultiloginHelperTest() override = default;
 
   std::unique_ptr<OAuthMultiloginHelper> CreateHelper(
-      const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>
-          accounts) {
+      const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair> accounts) {
     return std::make_unique<OAuthMultiloginHelper>(
-        &test_signin_client_, token_service(),
+        &test_signin_client_, this, token_service(),
         gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, accounts,
         std::string(),
         base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished,
@@ -187,10 +185,9 @@
   }
 
   std::unique_ptr<OAuthMultiloginHelper> CreateHelperWithExternalCcResult(
-      const std::vector<GaiaCookieManagerService::AccountIdGaiaIdPair>
-          accounts) {
+      const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair> accounts) {
     return std::make_unique<OAuthMultiloginHelper>(
-        &test_signin_client_, token_service(),
+        &test_signin_client_, this, token_service(),
         gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, accounts,
         kExternalCcResult,
         base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished,
@@ -212,7 +209,7 @@
            kExternalCcResult;
   }
 
-  MockCookieManager* cookie_manager() { return mock_cookie_manager_; }
+  MockCookieManager* cookie_manager() { return &mock_cookie_manager_; }
   MockTokenService* token_service() { return &mock_token_service_; }
 
  protected:
@@ -222,13 +219,24 @@
     result_ = result;
   }
 
+  // AccountsCookieMuator::PartitionDelegate:
+  std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition(
+      GaiaAuthConsumer* consumer) override {
+    return test_signin_client_.CreateGaiaAuthFetcher(consumer,
+                                                     gaia::GaiaSource::kChrome);
+  }
+
+  network::mojom::CookieManager* GetCookieManagerForPartition() override {
+    return &mock_cookie_manager_;
+  }
+
   base::test::TaskEnvironment task_environment_;
 
   bool callback_called_ = false;
   SetAccountsInCookieResult result_;
 
   TestingPrefServiceSimple pref_service_;
-  MockCookieManager* mock_cookie_manager_;  // Owned by test_signin_client_
+  MockCookieManager mock_cookie_manager_;
   TestSigninClient test_signin_client_;
   MockTokenService mock_token_service_;
 };
diff --git a/components/signin/public/identity_manager/accounts_cookie_mutator.h b/components/signin/public/identity_manager/accounts_cookie_mutator.h
index b60720e0..9ae192b 100644
--- a/components/signin/public/identity_manager/accounts_cookie_mutator.h
+++ b/components/signin/public/identity_manager/accounts_cookie_mutator.h
@@ -15,6 +15,12 @@
 struct CoreAccountId;
 class GoogleServiceAuthError;
 
+namespace network {
+namespace mojom {
+class CookieManager;
+}
+}  // namespace network
+
 namespace signin {
 
 struct MultiloginParameters;
@@ -24,6 +30,25 @@
 // accounts into the cookie jar tracking the list of logged-in Google sessions.
 class AccountsCookieMutator {
  public:
+  // Delegate class used to interact with storage partitions other than the
+  // default one. The default storage partition is managed by the SigninClient.
+  class PartitionDelegate {
+   public:
+    // Creates a new GaiaAuthFetcher for the partition.
+    virtual std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition(
+        GaiaAuthConsumer* consumer) = 0;
+
+    // Returns the CookieManager for the partition.
+    virtual network::mojom::CookieManager* GetCookieManagerForPartition() = 0;
+  };
+
+  // Task handle for SetAccountsInCookieForPartition. Deleting this object
+  // cancels the task. Must not outlive the AccountsInCookieMutator.
+  class SetAccountsInCookieTask {
+   public:
+    virtual ~SetAccountsInCookieTask() = default;
+  };
+
   AccountsCookieMutator() = default;
   virtual ~AccountsCookieMutator() = default;
 
@@ -67,6 +92,20 @@
       base::OnceCallback<void(SetAccountsInCookieResult)>
           set_accounts_in_cookies_completed_callback) = 0;
 
+  // This is similar to SetAccountsInCookie, but allow specifying the partition
+  // where the cookies are set. This function must not be used with the default
+  // partition (use SetAccountsInCookie instead).
+  //
+  // The returned SetAccountsInCookieTask must not outlive the
+  // AccountsCookieMutator. If the task is deleted, all network requests are
+  // cancelled; the partition delegate and the callback will not be called.
+  virtual std::unique_ptr<SetAccountsInCookieTask>
+  SetAccountsInCookieForPartition(
+      PartitionDelegate* partition_delegate,
+      const MultiloginParameters& parameters,
+      base::OnceCallback<void(SetAccountsInCookieResult)>
+          set_accounts_in_cookies_completed_callback) = 0;
+
   // Triggers a ListAccounts fetch. Can be used in circumstances where clients
   // know that the contents of the Gaia cookie might have changed.
   virtual void TriggerCookieJarUpdate() = 0;
diff --git a/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc b/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
index 42dc77d..cb4534e 100644
--- a/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
+++ b/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
@@ -26,6 +26,7 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/test/test_cookie_manager.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -59,7 +60,9 @@
 }  // namespace
 
 namespace signin {
-class AccountsCookieMutatorTest : public testing::Test {
+class AccountsCookieMutatorTest
+    : public testing::Test,
+      public AccountsCookieMutator::PartitionDelegate {
  public:
   const CoreAccountId kTestUnavailableAccountId;
   const CoreAccountId kTestOtherUnavailableAccountId;
@@ -146,10 +149,22 @@
   }
 
  private:
+  // AccountsCookieMutator::PartitionDelegate
+  std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition(
+      GaiaAuthConsumer* consumer) override {
+    return test_signin_client_.CreateGaiaAuthFetcher(consumer,
+                                                     gaia::GaiaSource::kChrome);
+  }
+
+  network::mojom::CookieManager* GetCookieManagerForPartition() override {
+    return &cookie_manager_for_partition_;
+  }
+
   base::test::TaskEnvironment task_environment_;
   sync_preferences::TestingPrefServiceSyncable prefs_;
   TestSigninClient test_signin_client_;
   IdentityTestEnvironment identity_test_env_;
+  network::TestCookieManager cookie_manager_for_partition_;
 
   DISALLOW_COPY_AND_ASSIGN(AccountsCookieMutatorTest);
 };
@@ -360,6 +375,64 @@
   run_loop.Run();
 }
 
+// Test that trying to set a list of accounts in a partitionned cookie jar where
+// all of those accounts have refresh tokens in IdentityManager results in them
+// being successfully set.
+TEST_F(AccountsCookieMutatorTest,
+       SetAccountsInCookieForPartition_AllExistingAccounts) {
+  PrepareURLLoaderResponsesForAction(
+      AccountsCookiesMutatorAction::kSetAccountsInCookie);
+  PrepareURLLoaderResponsesForAction(
+      AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+  CoreAccountId account_id = AddAcountWithRefreshToken(kTestAccountEmail);
+  CoreAccountId other_account_id =
+      AddAcountWithRefreshToken(kTestOtherAccountEmail);
+  base::RunLoop run_loop;
+  MultiloginParameters parameters = {
+      gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+      {account_id, other_account_id}};
+  std::unique_ptr<AccountsCookieMutator::SetAccountsInCookieTask> task =
+      accounts_cookie_mutator()->SetAccountsInCookieForPartition(
+          this, parameters,
+          base::BindOnce(
+              [](base::OnceClosure quit_closure,
+                 SetAccountsInCookieResult result) {
+                EXPECT_EQ(result, SetAccountsInCookieResult::kSuccess);
+                std::move(quit_closure).Run();
+              },
+              run_loop.QuitClosure()));
+
+  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      account_id, kTestAccessToken,
+      base::Time::Now() + base::TimeDelta::FromHours(1));
+  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      other_account_id, kTestAccessToken,
+      base::Time::Now() + base::TimeDelta::FromHours(1));
+
+  run_loop.Run();
+}
+
+// Test that setting accounts in a partition can be cancelled.
+TEST_F(AccountsCookieMutatorTest, SetAccountsInCookieForPartition_Cancel) {
+  PrepareURLLoaderResponsesForAction(
+      AccountsCookiesMutatorAction::kSetAccountsInCookie);
+  PrepareURLLoaderResponsesForAction(
+      AccountsCookiesMutatorAction::kTriggerCookieJarUpdateNoAccounts);
+
+  CoreAccountId account_id = AddAcountWithRefreshToken(kTestAccountEmail);
+  CoreAccountId other_account_id =
+      AddAcountWithRefreshToken(kTestOtherAccountEmail);
+  MultiloginParameters parameters = {
+      gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+      {account_id, other_account_id}};
+  std::unique_ptr<AccountsCookieMutator::SetAccountsInCookieTask> task =
+      accounts_cookie_mutator()->SetAccountsInCookieForPartition(
+          this, parameters,
+          base::BindOnce([](SetAccountsInCookieResult) { NOTREACHED(); }));
+  task.reset();
+}
+
 // Test triggering the update of a cookie jar with no accounts works.
 TEST_F(AccountsCookieMutatorTest, TriggerCookieJarUpdate_NoListedAccounts) {
   PrepareURLLoaderResponsesForAction(
diff --git a/components/signin/public/identity_manager/identity_manager_builder.cc b/components/signin/public/identity_manager/identity_manager_builder.cc
index da11364..1e95cac5 100644
--- a/components/signin/public/identity_manager/identity_manager_builder.cc
+++ b/components/signin/public/identity_manager/identity_manager_builder.cc
@@ -147,6 +147,7 @@
                            token_service.get(), primary_account_manager.get());
 
   auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
+      params->signin_client, token_service.get(),
       gaia_cookie_manager_service.get(), account_tracker_service.get());
 
   auto diagnostics_provider = std::make_unique<DiagnosticsProviderImpl>(
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc
index eb1ad60..1d278bf1 100644
--- a/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -356,7 +356,8 @@
     }
 
     auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
-        gaia_cookie_manager_service.get(), account_tracker_service.get());
+        &signin_client_, token_service.get(), gaia_cookie_manager_service.get(),
+        account_tracker_service.get());
 
     auto diagnostics_provider = std::make_unique<DiagnosticsProviderImpl>(
         token_service.get(), gaia_cookie_manager_service.get());
diff --git a/components/signin/public/identity_manager/identity_test_environment.cc b/components/signin/public/identity_manager/identity_test_environment.cc
index 088157de..b5639ba 100644
--- a/components/signin/public/identity_manager/identity_test_environment.cc
+++ b/components/signin/public/identity_manager/identity_test_environment.cc
@@ -209,7 +209,8 @@
       token_service.get(), gaia_cookie_manager_service.get());
 
   auto accounts_cookie_mutator = std::make_unique<AccountsCookieMutatorImpl>(
-      gaia_cookie_manager_service.get(), account_tracker_service.get());
+      signin_client, token_service.get(), gaia_cookie_manager_service.get(),
+      account_tracker_service.get());
 
   std::unique_ptr<DeviceAccountsSynchronizer> device_accounts_synchronizer;
 #if defined(OS_IOS)
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn
index e479470..1f751190 100644
--- a/components/subresource_filter/content/browser/BUILD.gn
+++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -120,7 +120,5 @@
     "//ipc:test_support",
     "//testing/gtest",
   ]
-  public_deps = [
-    "//components/subresource_filter/content/mojom",
-  ]
+  public_deps = [ "//components/subresource_filter/content/mojom" ]
 }
diff --git a/components/subresource_filter/content/common/BUILD.gn b/components/subresource_filter/content/common/BUILD.gn
index a2e6e5f..4918083 100644
--- a/components/subresource_filter/content/common/BUILD.gn
+++ b/components/subresource_filter/content/common/BUILD.gn
@@ -24,9 +24,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "ruleset_dealer_unittest.cc",
-  ]
+  sources = [ "ruleset_dealer_unittest.cc" ]
   deps = [
     ":common",
     "//base",
diff --git a/components/subresource_filter/content/mojom/BUILD.gn b/components/subresource_filter/content/mojom/BUILD.gn
index 025e259a..f06d037d 100644
--- a/components/subresource_filter/content/mojom/BUILD.gn
+++ b/components/subresource_filter/content/mojom/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "subresource_filter_agent.mojom",
-  ]
+  sources = [ "subresource_filter_agent.mojom" ]
   deps = [
     "//components/subresource_filter/core/mojom",
     "//mojo/public/mojom/base",
diff --git a/components/subresource_filter/content/renderer/BUILD.gn b/components/subresource_filter/content/renderer/BUILD.gn
index 64b6b08a..5c5b289 100644
--- a/components/subresource_filter/content/renderer/BUILD.gn
+++ b/components/subresource_filter/content/renderer/BUILD.gn
@@ -23,16 +23,12 @@
     "//third_party/blink/public:blink",
     "//url",
   ]
-  public_deps = [
-    "//ipc",
-  ]
+  public_deps = [ "//ipc" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "subresource_filter_agent_unittest.cc",
-  ]
+  sources = [ "subresource_filter_agent_unittest.cc" ]
   deps = [
     ":renderer",
     "//base",
diff --git a/components/subresource_filter/core/browser/BUILD.gn b/components/subresource_filter/core/browser/BUILD.gn
index 35cf2446..bd3aca9 100644
--- a/components/subresource_filter/core/browser/BUILD.gn
+++ b/components/subresource_filter/core/browser/BUILD.gn
@@ -37,9 +37,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "subresource_filter_features_unittest.cc",
-  ]
+  sources = [ "subresource_filter_features_unittest.cc" ]
   deps = [
     ":browser",
     ":test_support",
diff --git a/components/subresource_filter/core/common/BUILD.gn b/components/subresource_filter/core/common/BUILD.gn
index 066fd90..44b98ef 100644
--- a/components/subresource_filter/core/common/BUILD.gn
+++ b/components/subresource_filter/core/common/BUILD.gn
@@ -84,9 +84,7 @@
 }
 
 fuzzer_test("indexed_ruleset_fuzzer") {
-  sources = [
-    "indexed_ruleset_fuzzer.cc",
-  ]
+  sources = [ "indexed_ruleset_fuzzer.cc" ]
   deps = [
     ":common",
     "//base",
diff --git a/components/subresource_filter/core/common/flat/BUILD.gn b/components/subresource_filter/core/common/flat/BUILD.gn
index d46e71c..2989b3e 100644
--- a/components/subresource_filter/core/common/flat/BUILD.gn
+++ b/components/subresource_filter/core/common/flat/BUILD.gn
@@ -5,10 +5,6 @@
 import("//third_party/flatbuffers/flatbuffer.gni")
 
 flatbuffer("indexed_ruleset") {
-  sources = [
-    "indexed_ruleset.fbs",
-  ]
-  public_deps = [
-    "//components/url_pattern_index/flat:url_pattern_index",
-  ]
+  sources = [ "indexed_ruleset.fbs" ]
+  public_deps = [ "//components/url_pattern_index/flat:url_pattern_index" ]
 }
diff --git a/components/subresource_filter/core/mojom/BUILD.gn b/components/subresource_filter/core/mojom/BUILD.gn
index 7968564..60debf6 100644
--- a/components/subresource_filter/core/mojom/BUILD.gn
+++ b/components/subresource_filter/core/mojom/BUILD.gn
@@ -5,10 +5,6 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "subresource_filter.mojom",
-  ]
-  deps = [
-    "//mojo/public/mojom/base",
-  ]
+  sources = [ "subresource_filter.mojom" ]
+  deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/components/subresource_filter/tools/BUILD.gn b/components/subresource_filter/tools/BUILD.gn
index f3451ef9..0586f7c 100644
--- a/components/subresource_filter/tools/BUILD.gn
+++ b/components/subresource_filter/tools/BUILD.gn
@@ -46,9 +46,7 @@
   executable("subresource_filter_tool") {
     # Production code should not depend on this.
     testonly = true
-    sources = [
-      "filter_tool_main.cc",
-    ]
+    sources = [ "filter_tool_main.cc" ]
     deps = [
       ":tools_lib",
       "//base",
@@ -58,9 +56,7 @@
   executable("subresource_indexing_tool") {
     # Production code should not depend on this.
     testonly = true
-    sources = [
-      "indexing_tool_main.cc",
-    ]
+    sources = [ "indexing_tool_main.cc" ]
     deps = [
       ":tools_lib",
       "../core/common",
@@ -69,9 +65,7 @@
   }
 
   executable("ruleset_converter") {
-    sources = [
-      "ruleset_converter/main.cc",
-    ]
+    sources = [ "ruleset_converter/main.cc" ]
     deps = [
       "ruleset_converter:support",
       "//base",
@@ -101,12 +95,8 @@
       "$target_gen_dir/default_local_state.json",
     ]
 
-    inputs = [
-      "//third_party/subresource-filter-ruleset/data/UnindexedRules",
-    ]
-    deps = [
-      ":subresource_indexing_tool",
-    ]
+    inputs = [ "//third_party/subresource-filter-ruleset/data/UnindexedRules" ]
+    deps = [ ":subresource_indexing_tool" ]
 
     args = [
       rebase_path(inputs[0], root_build_dir),
diff --git a/components/subresource_filter/tools/rule_parser/BUILD.gn b/components/subresource_filter/tools/rule_parser/BUILD.gn
index 7a2ff52..8044d11 100644
--- a/components/subresource_filter/tools/rule_parser/BUILD.gn
+++ b/components/subresource_filter/tools/rule_parser/BUILD.gn
@@ -10,9 +10,7 @@
     "rule_parser.cc",
     "rule_parser.h",
   ]
-  public_deps = [
-    "//components/url_pattern_index",
-  ]
+  public_deps = [ "//components/url_pattern_index" ]
   deps = [
     "//base",
     "//third_party/protobuf:protobuf_lite",
diff --git a/components/subresource_filter/tools/ruleset_converter/BUILD.gn b/components/subresource_filter/tools/ruleset_converter/BUILD.gn
index e82c5377..c776db2e 100644
--- a/components/subresource_filter/tools/ruleset_converter/BUILD.gn
+++ b/components/subresource_filter/tools/ruleset_converter/BUILD.gn
@@ -12,9 +12,7 @@
     "ruleset_format.h",
   ]
 
-  public_deps = [
-    "//components/url_pattern_index/proto:url_pattern_index",
-  ]
+  public_deps = [ "//components/url_pattern_index/proto:url_pattern_index" ]
 
   deps = [
     "../rule_parser",
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 340fedf..d64c7030 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -505,9 +505,7 @@
     "test/test_transaction_observer.h",
   ]
 
-  public_deps = [
-    "//components/sync/base:test_support",
-  ]
+  public_deps = [ "//components/sync/base:test_support" ]
 
   deps = [
     ":sync",
@@ -550,13 +548,9 @@
     "model/test_model_type_store_service.h",
   ]
 
-  public_deps = [
-    "//components/sync/base:test_support",
-  ]
+  public_deps = [ "//components/sync/base:test_support" ]
 
-  deps = [
-    ":sync",
-  ]
+  deps = [ ":sync" ]
 }
 
 source_set("unit_tests") {
@@ -744,8 +738,6 @@
       "//base:base_java",
       "//third_party/junit",
     ]
-    sources = [
-      "test/android/javatests/src/org/chromium/components/sync/test/util/MockSyncContentResolverDelegate.java",
-    ]
+    sources = [ "test/android/javatests/src/org/chromium/components/sync/test/util/MockSyncContentResolverDelegate.java" ]
   }
 }
diff --git a/components/sync/android/BUILD.gn b/components/sync/android/BUILD.gn
index dd9ceaa..fba93d0a 100644
--- a/components/sync/android/BUILD.gn
+++ b/components/sync/android/BUILD.gn
@@ -66,7 +66,5 @@
 }
 
 generate_jni("jni_headers") {
-  sources = [
-    "java/src/org/chromium/components/sync/ModelTypeHelper.java",
-  ]
+  sources = [ "java/src/org/chromium/components/sync/ModelTypeHelper.java" ]
 }
diff --git a/components/sync/driver/BUILD.gn b/components/sync/driver/BUILD.gn
index aaad9aa5..a7ae6cd 100644
--- a/components/sync/driver/BUILD.gn
+++ b/components/sync/driver/BUILD.gn
@@ -192,9 +192,7 @@
     "test_sync_user_settings.h",
   ]
 
-  public_deps = [
-    "//components/sync/base:test_support",
-  ]
+  public_deps = [ "//components/sync/base:test_support" ]
 
   deps = [
     "//components/invalidation/impl:test_support",
diff --git a/components/sync/driver/file_based_trusted_vault_client.cc b/components/sync/driver/file_based_trusted_vault_client.cc
index a77f53f..e8373ec 100644
--- a/components/sync/driver/file_based_trusted_vault_client.cc
+++ b/components/sync/driver/file_based_trusted_vault_client.cc
@@ -15,6 +15,7 @@
 #include "base/task/task_traits.h"
 #include "base/task_runner_util.h"
 #include "components/os_crypt/os_crypt.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/protocol/local_trusted_vault.pb.h"
 
 namespace syncer {
@@ -61,9 +62,10 @@
 
   void ReadDataFromDisk() { data_ = ReadEncryptedFile(file_path_); }
 
-  std::vector<std::vector<uint8_t>> FetchKeys(const std::string& gaia_id) {
+  std::vector<std::vector<uint8_t>> FetchKeys(
+      const CoreAccountInfo& account_info) {
     const sync_pb::LocalTrustedVaultPerUser* per_user_vault =
-        FindUserVault(gaia_id);
+        FindUserVault(account_info.gaia);
 
     std::vector<std::vector<uint8_t>> keys;
     if (per_user_vault) {
@@ -133,12 +135,13 @@
 }
 
 void FileBasedTrustedVaultClient::FetchKeys(
-    const std::string& gaia_id,
+    const CoreAccountInfo& account_info,
     base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb) {
   TriggerLazyInitializationIfNeeded();
   base::PostTaskAndReplyWithResult(
       backend_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&Backend::FetchKeys, backend_, gaia_id), std::move(cb));
+      base::BindOnce(&Backend::FetchKeys, backend_, account_info),
+      std::move(cb));
 }
 
 void FileBasedTrustedVaultClient::StoreKeys(
@@ -153,7 +156,7 @@
 }
 
 void FileBasedTrustedVaultClient::MarkKeysAsStale(
-    const std::string& gaia_id,
+    const CoreAccountInfo& account_info,
     base::OnceCallback<void(bool)> cb) {
   // Not really supported and not useful for this particular implementation.
   std::move(cb).Run(false);
diff --git a/components/sync/driver/file_based_trusted_vault_client.h b/components/sync/driver/file_based_trusted_vault_client.h
index 03c0a6c6..edab496 100644
--- a/components/sync/driver/file_based_trusted_vault_client.h
+++ b/components/sync/driver/file_based_trusted_vault_client.h
@@ -32,13 +32,13 @@
   std::unique_ptr<Subscription> AddKeysChangedObserver(
       const base::RepeatingClosure& cb) override;
   void FetchKeys(
-      const std::string& gaia_id,
+      const CoreAccountInfo& account_info,
       base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb)
       override;
   void StoreKeys(const std::string& gaia_id,
                  const std::vector<std::vector<uint8_t>>& keys,
                  int last_key_version) override;
-  void MarkKeysAsStale(const std::string& gaia_id,
+  void MarkKeysAsStale(const CoreAccountInfo& account_info,
                        base::OnceCallback<void(bool)> cb) override;
 
   // Runs |cb| when all requests have completed.
diff --git a/components/sync/driver/file_based_trusted_vault_client_unittest.cc b/components/sync/driver/file_based_trusted_vault_client_unittest.cc
index fbf91d0a..cfa297c 100644
--- a/components/sync/driver/file_based_trusted_vault_client_unittest.cc
+++ b/components/sync/driver/file_based_trusted_vault_client_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/task_environment.h"
 #include "components/os_crypt/os_crypt.h"
 #include "components/os_crypt/os_crypt_mocker.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/protocol/local_trusted_vault.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -44,9 +45,12 @@
     FileBasedTrustedVaultClient* client) {
   DCHECK(client);
 
+  CoreAccountInfo account_info;
+  account_info.gaia = gaia_id;
+
   base::RunLoop loop;
   std::vector<std::vector<uint8_t>> fetched_keys;
-  client->FetchKeys(gaia_id,
+  client->FetchKeys(account_info,
                     base::BindLambdaForTesting(
                         [&](const std::vector<std::vector<uint8_t>>& keys) {
                           fetched_keys = keys;
diff --git a/components/sync/driver/sync_service_crypto.cc b/components/sync/driver/sync_service_crypto.cc
index 7e1f7cf..403669f 100644
--- a/components/sync/driver/sync_service_crypto.cc
+++ b/components/sync/driver/sync_service_crypto.cc
@@ -37,7 +37,7 @@
   }
 
   void FetchKeys(
-      const std::string& gaia_id,
+      const CoreAccountInfo& account_info,
       base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb)
       override {
     std::move(cb).Run({});
@@ -50,7 +50,7 @@
     NOTREACHED();
   }
 
-  void MarkKeysAsStale(const std::string& gaia_id,
+  void MarkKeysAsStale(const CoreAccountInfo& account_info,
                        base::OnceCallback<void(bool)> cb) override {
     std::move(cb).Run(false);
   }
@@ -583,7 +583,7 @@
   state_.deferred_trusted_vault_fetch_keys_pending = false;
 
   trusted_vault_client_->FetchKeys(
-      state_.account_info.gaia,
+      state_.account_info,
       base::BindOnce(&SyncServiceCrypto::TrustedVaultKeysFetchedFromClient,
                      weak_factory_.GetWeakPtr()));
 }
@@ -624,7 +624,7 @@
   // triggered, so the fetched trusted vault keys were insufficient. Let the
   // trusted vault client know.
   trusted_vault_client_->MarkKeysAsStale(
-      state_.account_info.gaia,
+      state_.account_info,
       base::BindOnce(&SyncServiceCrypto::TrustedVaultKeysMarkedAsStale,
                      weak_factory_.GetWeakPtr()));
 }
diff --git a/components/sync/driver/sync_service_crypto_unittest.cc b/components/sync/driver/sync_service_crypto_unittest.cc
index cd928df..e5139f3a 100644
--- a/components/sync/driver/sync_service_crypto_unittest.cc
+++ b/components/sync/driver/sync_service_crypto_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
+#include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/base/sync_prefs.h"
 #include "components/sync/driver/trusted_vault_client.h"
 #include "components/sync/engine/mock_sync_engine.h"
@@ -91,13 +92,13 @@
   }
 
   void FetchKeys(
-      const std::string& gaia_id,
+      const CoreAccountInfo& account_info,
       base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb)
       override {
     ++fetch_count_;
     keys_marked_as_stale_ = false;
     pending_responses_.push_back(
-        base::BindOnce(std::move(cb), gaia_id_to_keys_[gaia_id]));
+        base::BindOnce(std::move(cb), gaia_id_to_keys_[account_info.gaia]));
   }
 
   void StoreKeys(const std::string& gaia_id,
@@ -107,7 +108,7 @@
     observer_list_.Notify();
   }
 
-  void MarkKeysAsStale(const std::string& gaia_id,
+  void MarkKeysAsStale(const CoreAccountInfo& account_info,
                        base::OnceCallback<void(bool)> cb) override {
     keys_marked_as_stale_ = true;
     std::move(cb).Run(false);
diff --git a/components/sync/driver/trusted_vault_client.h b/components/sync/driver/trusted_vault_client.h
index c94abdf2f..bc10282 100644
--- a/components/sync/driver/trusted_vault_client.h
+++ b/components/sync/driver/trusted_vault_client.h
@@ -13,6 +13,8 @@
 #include "base/callback_list.h"
 #include "base/macros.h"
 
+struct CoreAccountInfo;
+
 namespace syncer {
 
 // Interface that allows platform-specific logic related to accessing locally
@@ -37,7 +39,7 @@
   // Concurrent calls to FetchKeys() must not be issued since implementations
   // may not support them.
   virtual void FetchKeys(
-      const std::string& gaia_id,
+      const CoreAccountInfo& account_info,
       base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)>
           cb) = 0;
 
@@ -48,7 +50,7 @@
   // is unsupported) or true if some change may have occurred (which indicates a
   // second FetchKeys() attempt is worth). Concurrent calls to MarkKeysAsStale()
   // must not be issued since implementations may not support them.
-  virtual void MarkKeysAsStale(const std::string& gaia_id,
+  virtual void MarkKeysAsStale(const CoreAccountInfo& account_info,
                                base::OnceCallback<void(bool)> cb) = 0;
 
   // Allows implementations to store encryption keys fetched by other means such
diff --git a/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc b/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc
index 9d5a4a78..ee6db92 100644
--- a/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc
+++ b/components/sync/engine_impl/loopback_server/loopback_connection_manager.cc
@@ -16,31 +16,33 @@
 LoopbackConnectionManager::~LoopbackConnectionManager() {}
 
 bool LoopbackConnectionManager::PostBufferToPath(
-    PostBufferParams* params,
+    const std::string& buffer_in,
     const std::string& path,
-    const std::string& access_token) {
-  params->buffer_out.clear();
+    const std::string& access_token,
+    std::string* buffer_out,
+    HttpResponse* http_response) {
+  buffer_out->clear();
 
   sync_pb::ClientToServerMessage message;
-  bool parsed = message.ParseFromString(params->buffer_in);
+  bool parsed = message.ParseFromString(buffer_in);
   DCHECK(parsed) << "Unable to parse the ClientToServerMessage.";
 
-  sync_pb::ClientToServerResponse response;
-  params->response.http_status_code =
-      loopback_server_.HandleCommand(message, &response);
+  sync_pb::ClientToServerResponse client_to_server_response;
+  http_response->http_status_code =
+      loopback_server_.HandleCommand(message, &client_to_server_response);
 
-  if (response.IsInitialized()) {
-    params->buffer_out = response.SerializeAsString();
+  if (client_to_server_response.IsInitialized()) {
+    *buffer_out = client_to_server_response.SerializeAsString();
   }
 
-  DCHECK_GE(params->response.http_status_code, 0);
+  DCHECK_GE(http_response->http_status_code, 0);
 
-  if (params->response.http_status_code != net::HTTP_OK) {
-    params->response.server_status = HttpResponse::SYNC_SERVER_ERROR;
+  if (http_response->http_status_code != net::HTTP_OK) {
+    http_response->server_status = HttpResponse::SYNC_SERVER_ERROR;
     return false;
   }
 
-  params->response.server_status = HttpResponse::SERVER_CONNECTION_OK;
+  http_response->server_status = HttpResponse::SERVER_CONNECTION_OK;
   return true;
 }
 
diff --git a/components/sync/engine_impl/loopback_server/loopback_connection_manager.h b/components/sync/engine_impl/loopback_server/loopback_connection_manager.h
index 7928f621..e354114 100644
--- a/components/sync/engine_impl/loopback_server/loopback_connection_manager.h
+++ b/components/sync/engine_impl/loopback_server/loopback_connection_manager.h
@@ -23,9 +23,11 @@
 
  private:
   // Overridden ServerConnectionManager functions.
-  bool PostBufferToPath(PostBufferParams* params,
+  bool PostBufferToPath(const std::string& buffer_in,
                         const std::string& path,
-                        const std::string& access_token) override;
+                        const std::string& access_token,
+                        std::string* buffer_out,
+                        HttpResponse* http_response) override;
 
   // The loopback server that will handle the requests locally.
   LoopbackServer loopback_server_;
diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc
index 383f60d..324c1c0b 100644
--- a/components/sync/engine_impl/model_type_worker.cc
+++ b/components/sync/engine_impl/model_type_worker.cc
@@ -397,7 +397,9 @@
   DCHECK(response.size() <= max_entries);
   return std::make_unique<NonBlockingTypeCommitContribution>(
       GetModelType(), model_type_state_.type_context(), std::move(response),
-      this, cryptographer_.get(), passphrase_type_, debug_info_emitter_,
+      base::BindOnce(&ModelTypeWorker::OnCommitResponse,
+                     weak_ptr_factory_.GetWeakPtr()),
+      cryptographer_.get(), passphrase_type_, debug_info_emitter_,
       CommitOnlyTypes().Has(GetModelType()));
 }
 
@@ -405,13 +407,14 @@
   return has_local_changes_;
 }
 
-void ModelTypeWorker::OnCommitResponse(CommitResponseDataList* response_list) {
+void ModelTypeWorker::OnCommitResponse(
+    const CommitResponseDataList& response_list) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Send the responses back to the model thread. It needs to know which
   // items have been successfully committed so it can save that information in
   // permanent storage.
-  model_type_processor_->OnCommitCompleted(model_type_state_, *response_list);
+  model_type_processor_->OnCommitCompleted(model_type_state_, response_list);
 }
 
 void ModelTypeWorker::AbortMigration() {
diff --git a/components/sync/engine_impl/model_type_worker.h b/components/sync/engine_impl/model_type_worker.h
index aba6a23..af26d95 100644
--- a/components/sync/engine_impl/model_type_worker.h
+++ b/components/sync/engine_impl/model_type_worker.h
@@ -123,9 +123,6 @@
   // called when a new encryption mechanism is ready.
   void EncryptionAcceptedMaybeApplyUpdates();
 
-  // Callback for when our contribution gets a response.
-  void OnCommitResponse(CommitResponseDataList* response_list);
-
   // If migration the directory encounters an error partway through, we need to
   // clear the update data that has been added so far.
   void AbortMigration();
@@ -210,6 +207,9 @@
   // of them except the last one.
   void DeduplicatePendingUpdatesBasedOnOriginatorClientItemId();
 
+  // Callback for when our contribution gets a response.
+  void OnCommitResponse(const CommitResponseDataList& committed_response_list);
+
   ModelType type_;
   DataTypeDebugInfoEmitter* debug_info_emitter_;
 
diff --git a/components/sync/engine_impl/net/server_connection_manager.cc b/components/sync/engine_impl/net/server_connection_manager.cc
index 23fd388..bfcbef3 100644
--- a/components/sync/engine_impl/net/server_connection_manager.cc
+++ b/components/sync/engine_impl/net/server_connection_manager.cc
@@ -142,12 +142,15 @@
 }
 
 bool ServerConnectionManager::PostBufferWithCachedAuth(
-    PostBufferParams* params) {
+    const std::string& buffer_in,
+    std::string* buffer_out,
+    HttpResponse* http_response) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::string path =
       MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_));
-  bool result = PostBufferToPath(params, path, access_token_);
-  SetServerResponse(params->response);
+  bool result = PostBufferToPath(buffer_in, path, access_token_, buffer_out,
+                                 http_response);
+  SetServerResponse(*http_response);
   return result;
 }
 
diff --git a/components/sync/engine_impl/net/server_connection_manager.h b/components/sync/engine_impl/net/server_connection_manager.h
index 6b2b966..4414c570 100644
--- a/components/sync/engine_impl/net/server_connection_manager.h
+++ b/components/sync/engine_impl/net/server_connection_manager.h
@@ -93,22 +93,16 @@
 //
 class ServerConnectionManager {
  public:
-  // buffer_in - will be POSTed
-  // buffer_out - string will be overwritten with response
-  struct PostBufferParams {
-    std::string buffer_in;
-    std::string buffer_out;
-    HttpResponse response = HttpResponse::Uninitialized();
-  };
-
   ServerConnectionManager();
   virtual ~ServerConnectionManager();
 
-  // POSTS buffer_in and reads a response into buffer_out. Uses our currently
-  // set access token in our headers.
+  // POSTS buffer_in and reads a http_response into buffer_out.
+  // Uses our currently set access token in our headers.
   //
   // Returns true if executed successfully.
-  bool PostBufferWithCachedAuth(PostBufferParams* params);
+  bool PostBufferWithCachedAuth(const std::string& buffer_in,
+                                std::string* buffer_out,
+                                HttpResponse* http_response);
 
   void AddListener(ServerConnectionEventListener* listener);
   void RemoveListener(ServerConnectionEventListener* listener);
@@ -152,9 +146,11 @@
 
   // Internal PostBuffer base function which subclasses are expected to
   // implement.
-  virtual bool PostBufferToPath(PostBufferParams*,
+  virtual bool PostBufferToPath(const std::string& buffer_in,
                                 const std::string& path,
-                                const std::string& access_token) = 0;
+                                const std::string& access_token,
+                                std::string* buffer_out,
+                                HttpResponse* http_response) = 0;
 
   void ClearAccessToken();
 
diff --git a/components/sync/engine_impl/net/sync_server_connection_manager.cc b/components/sync/engine_impl/net/sync_server_connection_manager.cc
index c210064..21cf90f5 100644
--- a/components/sync/engine_impl/net/sync_server_connection_manager.cc
+++ b/components/sync/engine_impl/net/sync_server_connection_manager.cc
@@ -222,11 +222,13 @@
 SyncServerConnectionManager::~SyncServerConnectionManager() = default;
 
 bool SyncServerConnectionManager::PostBufferToPath(
-    PostBufferParams* params,
+    const std::string& buffer_in,
     const std::string& path,
-    const std::string& access_token) {
+    const std::string& access_token,
+    std::string* buffer_out,
+    HttpResponse* http_response) {
   if (access_token.empty()) {
-    params->response.server_status = HttpResponse::SYNC_AUTH_ERROR;
+    http_response->server_status = HttpResponse::SYNC_AUTH_ERROR;
     // Print a log to distinguish this "known failure" from others.
     DVLOG(1) << "ServerConnectionManager forcing SYNC_AUTH_ERROR due to missing"
                 " access token";
@@ -234,7 +236,7 @@
   }
 
   if (cancelation_signal_->IsSignalled()) {
-    params->response.server_status = HttpResponse::CONNECTION_UNAVAILABLE;
+    http_response->server_status = HttpResponse::CONNECTION_UNAVAILABLE;
     return false;
   }
 
@@ -245,18 +247,17 @@
   // Note that |post| may be aborted by now, which will just cause Init to fail
   // with CONNECTION_UNAVAILABLE.
   bool ok = connection->Init(connection_url, sync_server_port_, access_token,
-                             params->buffer_in, &params->response);
+                             buffer_in, http_response);
 
-  if (params->response.server_status == HttpResponse::SYNC_AUTH_ERROR) {
+  if (http_response->server_status == HttpResponse::SYNC_AUTH_ERROR) {
     ClearAccessToken();
   }
 
-  if (!ok || net::HTTP_OK != params->response.http_status_code)
+  if (!ok || net::HTTP_OK != http_response->http_status_code)
     return false;
 
-  if (connection->ReadBufferResponse(&params->buffer_out, &params->response,
-                                     true)) {
-    params->response.server_status = HttpResponse::SERVER_CONNECTION_OK;
+  if (connection->ReadBufferResponse(buffer_out, http_response, true)) {
+    http_response->server_status = HttpResponse::SERVER_CONNECTION_OK;
     return true;
   }
   return false;
diff --git a/components/sync/engine_impl/net/sync_server_connection_manager.h b/components/sync/engine_impl/net/sync_server_connection_manager.h
index 27eca2fa..1e436fa1 100644
--- a/components/sync/engine_impl/net/sync_server_connection_manager.h
+++ b/components/sync/engine_impl/net/sync_server_connection_manager.h
@@ -32,9 +32,11 @@
   ~SyncServerConnectionManager() override;
 
  protected:
-  bool PostBufferToPath(PostBufferParams* params,
+  bool PostBufferToPath(const std::string& buffer_in,
                         const std::string& path,
-                        const std::string& access_token) override;
+                        const std::string& access_token,
+                        std::string* buffer_out,
+                        HttpResponse* http_response) override;
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SyncServerConnectionManagerTest, VeryEarlyAbortPost);
diff --git a/components/sync/engine_impl/net/sync_server_connection_manager_unittest.cc b/components/sync/engine_impl/net/sync_server_connection_manager_unittest.cc
index 8ea71e6c..423fa827 100644
--- a/components/sync/engine_impl/net/sync_server_connection_manager_unittest.cc
+++ b/components/sync/engine_impl/net/sync_server_connection_manager_unittest.cc
@@ -73,13 +73,14 @@
   SyncServerConnectionManager server(
       "server", 0, true, std::make_unique<BlockingHttpPostFactory>(), &signal);
 
-  ServerConnectionManager::PostBufferParams params;
+  std::string buffer_out;
+  HttpResponse http_response = HttpResponse::Uninitialized();
 
-  bool result = server.PostBufferToPath(&params, "/testpath", "testauth");
+  bool result = server.PostBufferToPath("", "/testpath", "testauth",
+                                        &buffer_out, &http_response);
 
   EXPECT_FALSE(result);
-  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE,
-            params.response.server_status);
+  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE, http_response.server_status);
 }
 
 // Ask the ServerConnectionManager to stop before its first request is made.
@@ -88,14 +89,15 @@
   SyncServerConnectionManager server(
       "server", 0, true, std::make_unique<BlockingHttpPostFactory>(), &signal);
 
-  ServerConnectionManager::PostBufferParams params;
+  std::string buffer_out;
+  HttpResponse http_response = HttpResponse::Uninitialized();
 
   signal.Signal();
-  bool result = server.PostBufferToPath(&params, "/testpath", "testauth");
+  bool result = server.PostBufferToPath("", "/testpath", "testauth",
+                                        &buffer_out, &http_response);
 
   EXPECT_FALSE(result);
-  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE,
-            params.response.server_status);
+  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE, http_response.server_status);
 }
 
 // Ask the ServerConnectionManager to stop during a request.
@@ -104,8 +106,6 @@
   SyncServerConnectionManager server(
       "server", 0, true, std::make_unique<BlockingHttpPostFactory>(), &signal);
 
-  ServerConnectionManager::PostBufferParams params;
-
   base::Thread abort_thread("Test_AbortThread");
   ASSERT_TRUE(abort_thread.Start());
   abort_thread.task_runner()->PostDelayedTask(
@@ -113,11 +113,14 @@
       base::BindOnce(&CancelationSignal::Signal, base::Unretained(&signal)),
       TestTimeouts::tiny_timeout());
 
-  bool result = server.PostBufferToPath(&params, "/testpath", "testauth");
+  std::string buffer_out;
+  HttpResponse http_response = HttpResponse::Uninitialized();
+
+  bool result = server.PostBufferToPath("", "/testpath", "testauth",
+                                        &buffer_out, &http_response);
 
   EXPECT_FALSE(result);
-  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE,
-            params.response.server_status);
+  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE, http_response.server_status);
   abort_thread.Stop();
 }
 
@@ -179,13 +182,14 @@
       "server", 0, true,
       std::make_unique<FailingHttpPostFactory>(net::ERR_TIMED_OUT), &signal);
 
-  ServerConnectionManager::PostBufferParams params;
+  std::string buffer_out;
+  HttpResponse http_response = HttpResponse::Uninitialized();
 
-  bool result = server.PostBufferToPath(&params, "/testpath", "testauth");
+  bool result = server.PostBufferToPath("", "/testpath", "testauth",
+                                        &buffer_out, &http_response);
 
   EXPECT_FALSE(result);
-  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE,
-            params.response.server_status);
+  EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE, http_response.server_status);
 }
 
 }  // namespace syncer
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
index 49900af..f597fd8 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
+++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
@@ -21,13 +21,14 @@
     ModelType type,
     const sync_pb::DataTypeContext& context,
     CommitRequestDataList commit_requests,
-    ModelTypeWorker* worker,
+    base::OnceCallback<void(const CommitResponseDataList&)>
+        on_commit_response_callback,
     Cryptographer* cryptographer,
     PassphraseType passphrase_type,
     DataTypeDebugInfoEmitter* debug_info_emitter,
     bool only_commit_specifics)
     : type_(type),
-      worker_(worker),
+      on_commit_response_callback_(std::move(on_commit_response_callback)),
       cryptographer_(cryptographer),
       passphrase_type_(passphrase_type),
       context_(context),
@@ -151,7 +152,7 @@
 
   // Send whatever successful responses we did get back to our parent.
   // It's the schedulers job to handle the failures.
-  worker_->OnCommitResponse(&response_list);
+  std::move(on_commit_response_callback_).Run(response_list);
 
   // Let the scheduler know about the failures.
   if (unknown_error) {
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.h b/components/sync/engine_impl/non_blocking_type_commit_contribution.h
index c6bdb0c..c29f3c84 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution.h
+++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.h
@@ -32,7 +32,8 @@
       ModelType type,
       const sync_pb::DataTypeContext& context,
       CommitRequestDataList commit_requests,
-      ModelTypeWorker* worker,
+      base::OnceCallback<void(const CommitResponseDataList&)>
+          on_commit_response_callback,
       Cryptographer* cryptographer,
       PassphraseType passphrase_type,
       DataTypeDebugInfoEmitter* debug_info_emitter,
@@ -59,8 +60,10 @@
 
   const ModelType type_;
 
-  // A non-owned pointer back to the object that created this contribution.
-  ModelTypeWorker* const worker_;
+  // A callback to inform the object that created this contribution about commit
+  // result.
+  base::OnceCallback<void(const CommitResponseDataList&)>
+      on_commit_response_callback_;
 
   // A non-owned pointer to cryptographer to encrypt entities.
   Cryptographer* const cryptographer_;
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc
index 4f333d94..263e789d 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc
+++ b/components/sync/engine_impl/non_blocking_type_commit_contribution_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/base64.h"
+#include "base/bind_helpers.h"
 #include "base/hash/sha1.h"
 #include "components/sync/base/client_tag_hash.h"
 #include "components/sync/base/model_type.h"
@@ -172,8 +173,8 @@
   requests_data.push_back(std::move(request_data));
   NonBlockingTypeCommitContribution contribution(
       PASSWORDS, sync_pb::DataTypeContext(), std::move(requests_data),
-      /*worker=*/nullptr, &cryptographer, PassphraseType::kImplicitPassphrase,
-      &debug_info_emitter,
+      /*on_commit_response_callback=*/base::NullCallback(), &cryptographer,
+      PassphraseType::kImplicitPassphrase, &debug_info_emitter,
       /*only_commit_specifics=*/false);
 
   sync_pb::ClientToServerMessage msg;
@@ -233,8 +234,8 @@
   requests_data.push_back(std::move(request_data));
   NonBlockingTypeCommitContribution contribution(
       PASSWORDS, sync_pb::DataTypeContext(), std::move(requests_data),
-      /*worker=*/nullptr, &cryptographer, PassphraseType::kCustomPassphrase,
-      &debug_info_emitter,
+      /*on_commit_response_callback=*/base::NullCallback(), &cryptographer,
+      PassphraseType::kCustomPassphrase, &debug_info_emitter,
       /*only_commit_specifics=*/false);
 
   sync_pb::ClientToServerMessage msg;
diff --git a/components/sync/engine_impl/syncer_proto_util.cc b/components/sync/engine_impl/syncer_proto_util.cc
index 8e6646a..25d7768 100644
--- a/components/sync/engine_impl/syncer_proto_util.cc
+++ b/components/sync/engine_impl/syncer_proto_util.cc
@@ -323,11 +323,11 @@
                                             SyncCycle* cycle,
                                             const ClientToServerMessage& msg,
                                             ClientToServerResponse* response) {
-  ServerConnectionManager::PostBufferParams params;
   DCHECK(msg.has_protocol_version());
   DCHECK_EQ(msg.protocol_version(),
             ClientToServerMessage::default_instance().protocol_version());
-  msg.SerializeToString(&params.buffer_in);
+  std::string buffer_in;
+  msg.SerializeToString(&buffer_in);
 
   UMA_HISTOGRAM_ENUMERATION("Sync.PostedClientToServerMessage",
                             msg.message_contents(),
@@ -353,13 +353,16 @@
 
   const base::Time start_time = base::Time::Now();
 
-  // Fills in params.buffer_out and params.response.
-  if (!scm->PostBufferWithCachedAuth(&params)) {
-    LOG(WARNING) << "Error posting from syncer:" << params.response;
+  std::string buffer_out;
+  HttpResponse http_response = HttpResponse::Uninitialized();
+
+  // Fills in buffer_out and http_response.
+  if (!scm->PostBufferWithCachedAuth(buffer_in, &buffer_out, &http_response)) {
+    LOG(WARNING) << "Error posting from syncer:" << http_response;
     return false;
   }
 
-  if (!response->ParseFromString(params.buffer_out)) {
+  if (!response->ParseFromString(buffer_out)) {
     DLOG(WARNING) << "Error parsing response from sync server";
     return false;
   }
diff --git a/components/sync/engine_impl/syncer_proto_util_unittest.cc b/components/sync/engine_impl/syncer_proto_util_unittest.cc
index cd019f3..55aaebb 100644
--- a/components/sync/engine_impl/syncer_proto_util_unittest.cc
+++ b/components/sync/engine_impl/syncer_proto_util_unittest.cc
@@ -210,15 +210,17 @@
  public:
   DummyConnectionManager() : send_error_(false) {}
 
-  bool PostBufferToPath(PostBufferParams* params,
+  bool PostBufferToPath(const std::string& buffer_in,
                         const std::string& path,
-                        const std::string& access_token) override {
+                        const std::string& access_token,
+                        std::string* buffer_out,
+                        HttpResponse* response) override {
     if (send_error_) {
       return false;
     }
 
-    sync_pb::ClientToServerResponse response;
-    response.SerializeToString(&params->buffer_out);
+    sync_pb::ClientToServerResponse client_to_server_response;
+    client_to_server_response.SerializeToString(buffer_out);
 
     return true;
   }
diff --git a/components/sync/js/BUILD.gn b/components/sync/js/BUILD.gn
index c5610a8..53422e2 100644
--- a/components/sync/js/BUILD.gn
+++ b/components/sync/js/BUILD.gn
@@ -16,9 +16,7 @@
     "sync_js_controller.h",
   ]
 
-  public_deps = [
-    "//components/sync/base",
-  ]
+  public_deps = [ "//components/sync/base" ]
 }
 
 static_library("test_support") {
diff --git a/components/sync/mojom/BUILD.gn b/components/sync/mojom/BUILD.gn
index c25e87a3..2e22f09c5 100644
--- a/components/sync/mojom/BUILD.gn
+++ b/components/sync/mojom/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "syncer.mojom",
-  ]
+  sources = [ "syncer.mojom" ]
 }
diff --git a/components/sync/test/engine/mock_connection_manager.cc b/components/sync/test/engine/mock_connection_manager.cc
index 6fcd474..1fbe5ad 100644
--- a/components/sync/test/engine/mock_connection_manager.cc
+++ b/components/sync/test/engine/mock_connection_manager.cc
@@ -68,11 +68,13 @@
   mid_commit_observer_ = observer;
 }
 
-bool MockConnectionManager::PostBufferToPath(PostBufferParams* params,
-                                             const string& path,
-                                             const string& access_token) {
+bool MockConnectionManager::PostBufferToPath(const std::string& buffer_in,
+                                             const std::string& path,
+                                             const std::string& access_token,
+                                             std::string* buffer_out,
+                                             HttpResponse* http_response) {
   ClientToServerMessage post;
-  if (!post.ParseFromString(params->buffer_in)) {
+  if (!post.ParseFromString(buffer_in)) {
     ADD_FAILURE();
     return false;
   }
@@ -91,8 +93,8 @@
 
   requests_.push_back(post);
   client_stuck_ = post.sync_problem_detected();
-  sync_pb::ClientToServerResponse response;
-  response.Clear();
+  sync_pb::ClientToServerResponse client_to_server_response;
+  client_to_server_response.Clear();
 
   if (directory_) {
     // If the Directory's locked when we do this, it's a problem as in normal
@@ -107,37 +109,37 @@
   }
 
   if (access_token.empty()) {
-    params->response.server_status = HttpResponse::SYNC_AUTH_ERROR;
+    http_response->server_status = HttpResponse::SYNC_AUTH_ERROR;
     return false;
   }
 
   if (access_token != kValidAccessToken) {
     // Simulate server-side auth failure.
-    params->response.server_status = HttpResponse::SYNC_AUTH_ERROR;
+    http_response->server_status = HttpResponse::SYNC_AUTH_ERROR;
     ClearAccessToken();
   }
 
   if (--countdown_to_postbuffer_fail_ == 0) {
     // Fail as countdown hits zero.
-    params->response.server_status = HttpResponse::SYNC_SERVER_ERROR;
+    http_response->server_status = HttpResponse::SYNC_SERVER_ERROR;
     return false;
   }
 
   if (!server_reachable_) {
-    params->response.server_status = HttpResponse::CONNECTION_UNAVAILABLE;
+    http_response->server_status = HttpResponse::CONNECTION_UNAVAILABLE;
     return false;
   }
 
   // Default to an ok connection.
-  params->response.server_status = HttpResponse::SERVER_CONNECTION_OK;
-  response.set_error_code(SyncEnums::SUCCESS);
+  http_response->server_status = HttpResponse::SERVER_CONNECTION_OK;
+  client_to_server_response.set_error_code(SyncEnums::SUCCESS);
   const string current_store_birthday = store_birthday();
-  response.set_store_birthday(current_store_birthday);
+  client_to_server_response.set_store_birthday(current_store_birthday);
   if (post.has_store_birthday() &&
       post.store_birthday() != current_store_birthday) {
-    response.set_error_code(SyncEnums::NOT_MY_BIRTHDAY);
-    response.set_error_message("Merry Unbirthday!");
-    response.SerializeToString(&params->buffer_out);
+    client_to_server_response.set_error_code(SyncEnums::NOT_MY_BIRTHDAY);
+    client_to_server_response.set_error_message("Merry Unbirthday!");
+    client_to_server_response.SerializeToString(buffer_out);
     store_birthday_sent_ = true;
     return true;
   }
@@ -148,17 +150,17 @@
   store_birthday_sent_ = true;
 
   if (post.message_contents() == ClientToServerMessage::COMMIT) {
-    if (!ProcessCommit(&post, &response)) {
+    if (!ProcessCommit(&post, &client_to_server_response)) {
       return false;
     }
 
   } else if (post.message_contents() == ClientToServerMessage::GET_UPDATES) {
-    if (!ProcessGetUpdates(&post, &response)) {
+    if (!ProcessGetUpdates(&post, &client_to_server_response)) {
       return false;
     }
   } else if (post.message_contents() ==
              ClientToServerMessage::CLEAR_SERVER_DATA) {
-    if (!ProcessClearServerData(&post, &response)) {
+    if (!ProcessClearServerData(&post, &client_to_server_response)) {
       return false;
     }
   } else {
@@ -170,7 +172,7 @@
     base::AutoLock lock(response_code_override_lock_);
     if (throttling_) {
       sync_pb::ClientToServerResponse_Error* response_error =
-          response.mutable_error();
+          client_to_server_response.mutable_error();
       response_error->set_error_type(SyncEnums::THROTTLED);
       for (ModelType type : partial_failure_type_) {
         response_error->add_error_data_type_ids(
@@ -181,7 +183,7 @@
 
     if (partial_failure_) {
       sync_pb::ClientToServerResponse_Error* response_error =
-          response.mutable_error();
+          client_to_server_response.mutable_error();
       response_error->set_error_type(SyncEnums::PARTIAL_FAILURE);
       for (ModelType type : partial_failure_type_) {
         response_error->add_error_data_type_ids(
@@ -191,7 +193,7 @@
     }
   }
 
-  response.SerializeToString(&params->buffer_out);
+  client_to_server_response.SerializeToString(buffer_out);
   if (post.message_contents() == ClientToServerMessage::COMMIT &&
       !mid_commit_callback_.is_null()) {
     std::move(mid_commit_callback_).Run();
diff --git a/components/sync/test/engine/mock_connection_manager.h b/components/sync/test/engine/mock_connection_manager.h
index e3fca08..1fb9273 100644
--- a/components/sync/test/engine/mock_connection_manager.h
+++ b/components/sync/test/engine/mock_connection_manager.h
@@ -43,9 +43,11 @@
   ~MockConnectionManager() override;
 
   // Overridden ServerConnectionManager functions.
-  bool PostBufferToPath(PostBufferParams*,
+  bool PostBufferToPath(const std::string& buffer_in,
                         const std::string& path,
-                        const std::string& access_token) override;
+                        const std::string& access_token,
+                        std::string* buffer_out,
+                        HttpResponse* http_response) override;
 
   // Control of commit response.
   // NOTE: Commit callback is invoked only once then reset.
diff --git a/components/sync/test/fake_server/BUILD.gn b/components/sync/test/fake_server/BUILD.gn
index bbfebb4..399ce5b0 100644
--- a/components/sync/test/fake_server/BUILD.gn
+++ b/components/sync/test/fake_server/BUILD.gn
@@ -44,9 +44,7 @@
 if (is_android) {
   generate_jni("fake_server_jni") {
     testonly = true
-    sources = [
-      "//chrome/android/javatests/src/org/chromium/chrome/browser/sync/FakeServerHelper.java",
-    ]
+    sources = [ "//chrome/android/javatests/src/org/chromium/chrome/browser/sync/FakeServerHelper.java" ]
   }
 
   static_library("fake_server_android") {
diff --git a/components/tab_count_metrics/BUILD.gn b/components/tab_count_metrics/BUILD.gn
index 84b24ff..b197775e 100644
--- a/components/tab_count_metrics/BUILD.gn
+++ b/components/tab_count_metrics/BUILD.gn
@@ -10,16 +10,12 @@
 
   defines = [ "IS_TAB_COUNT_METRICS_IMPL" ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "tab_count_metrics_unittest.cc",
-  ]
+  sources = [ "tab_count_metrics_unittest.cc" ]
 
   deps = [
     ":tab_count_metrics",
diff --git a/components/ui_devtools/viz/BUILD.gn b/components/ui_devtools/viz/BUILD.gn
index 3242bedf..296acf1a 100644
--- a/components/ui_devtools/viz/BUILD.gn
+++ b/components/ui_devtools/viz/BUILD.gn
@@ -27,9 +27,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "viz_devtools_unittest.cc",
-  ]
+  sources = [ "viz_devtools_unittest.cc" ]
 
   deps = [
     ":viz",
diff --git a/components/web_cache/browser/BUILD.gn b/components/web_cache/browser/BUILD.gn
index 0c09f07..17468f8 100644
--- a/components/web_cache/browser/BUILD.gn
+++ b/components/web_cache/browser/BUILD.gn
@@ -23,9 +23,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "web_cache_manager_unittest.cc",
-  ]
+  sources = [ "web_cache_manager_unittest.cc" ]
   deps = [
     ":browser",
     "//base",
diff --git a/components/web_cache/public/mojom/BUILD.gn b/components/web_cache/public/mojom/BUILD.gn
index 239dffa..d4af5b8 100644
--- a/components/web_cache/public/mojom/BUILD.gn
+++ b/components/web_cache/public/mojom/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "web_cache.mojom",
-  ]
+  sources = [ "web_cache.mojom" ]
 }
diff --git a/components/web_modal/BUILD.gn b/components/web_modal/BUILD.gn
index 13b631e..2b71f89 100644
--- a/components/web_modal/BUILD.gn
+++ b/components/web_modal/BUILD.gn
@@ -42,9 +42,7 @@
     "test_web_contents_modal_dialog_manager_delegate.h",
   ]
 
-  public_deps = [
-    ":web_modal",
-  ]
+  public_deps = [ ":web_modal" ]
   deps = [
     "//base",
     "//ui/gfx",
@@ -55,9 +53,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "web_contents_modal_dialog_manager_unittest.cc",
-  ]
+  sources = [ "web_contents_modal_dialog_manager_unittest.cc" ]
 
   deps = [
     ":test_support",
diff --git a/components/webdata/common/BUILD.gn b/components/webdata/common/BUILD.gn
index ae00fbf..58c6079 100644
--- a/components/webdata/common/BUILD.gn
+++ b/components/webdata/common/BUILD.gn
@@ -70,17 +70,13 @@
     "//components/test/data/web_database/version_80.sql",
     "//components/test/data/web_database/version_81.sql",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "web_database_migration_unittest.cc",
-  ]
+  sources = [ "web_database_migration_unittest.cc" ]
 
   deps = [
     ":common",
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn
index 48144dd..c34b696 100644
--- a/content/app/BUILD.gn
+++ b/content/app/BUILD.gn
@@ -179,9 +179,7 @@
 group("both_for_content_tests") {
   visibility = [ "//content/test/*" ]
   if (!is_component_build) {
-    public_deps = [
-      ":both",
-    ]
+    public_deps = [ ":both" ]
   }
 }
 
@@ -192,17 +190,13 @@
   implement_content_app("browser") {
     visibility = [ "//content/public/app:browser" ]
     defines = [ "CHROME_MULTIPLE_DLL_BROWSER" ]
-    deps = [
-      ":content_app_browser_deps",
-    ]
+    deps = [ ":content_app_browser_deps" ]
     include_browser_sources = true
   }
 
   implement_content_app("child") {
     visibility = [ "//content/public/app:child" ]
     defines = [ "CHROME_MULTIPLE_DLL_CHILD" ]
-    deps = [
-      ":content_app_child_deps",
-    ]
+    deps = [ ":content_app_child_deps" ]
   }
 }
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
index 01159a8..9f97200 100644
--- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
+++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -640,9 +640,6 @@
     return YES;
   }
 
-  // Use hitTest to check whether the mouse is over a nonWebContentView - in
-  // which case the mouse event should not be handled by the render host.
-  const SEL nonWebContentViewSelector = @selector(nonWebContentView);
   NSView* contentView = [window contentView];
   NSView* view = [contentView hitTest:[theEvent locationInWindow]];
   // Traverse the superview hierarchy as the hitTest will return the frontmost
@@ -652,11 +649,6 @@
   while (view) {
     if (view == self)
       hitSelf = YES;
-    if ([view respondsToSelector:nonWebContentViewSelector] &&
-        [view performSelector:nonWebContentViewSelector]) {
-      // The cursor is over a nonWebContentView - ignore this mouse event.
-      return YES;
-    }
     if ([view isKindOfClass:[self class]] && ![view isEqual:self] &&
         !_hasOpenMouseDown) {
       // The cursor is over an overlapping render widget. This check is done by
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 209829f3..dc2cbe0 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1981,10 +1981,6 @@
     ]
   }
 
-  if (is_chromeos || is_android || is_chromecast || is_fuchsia) {
-    defines += [ "ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION" ]
-  }
-
   if (is_chromecast && is_linux) {
     sources += [
       "tracing/cast_tracing_agent.cc",
diff --git a/content/browser/OWNERS b/content/browser/OWNERS
index a331c52d..e4b3a70 100644
--- a/content/browser/OWNERS
+++ b/content/browser/OWNERS
@@ -10,14 +10,14 @@
 per-file child_process_security_policy_impl.*=file://content/browser/SITE_ISOLATION_OWNERS
 per-file child_process_security_policy_unittest.cc=set noparent
 per-file child_process_security_policy_unittest.cc=file://content/browser/SITE_ISOLATION_OWNERS
-per-file browser_interface_binders.cc=set noparent
-per-file browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
-per-file ppapi_plugin_process_host_receiver_bindings.cc=set noparent
-per-file ppapi_plugin_process_host_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
-per-file browser_child_process_host_impl_receiver_bindings.cc=set noparent
-per-file browser_child_process_host_impl_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
-per-file utility_process_host_receiver_bindings.cc=set noparent
-per-file utility_process_host_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
+per-file browser_interface_binders.*=set noparent
+per-file browser_interface_binders.*=file://ipc/SECURITY_OWNERS
+per-file ppapi_plugin_process_host_receiver_bindings.*=set noparent
+per-file ppapi_plugin_process_host_receiver_bindings.*=file://ipc/SECURITY_OWNERS
+per-file browser_child_process_host_impl_receiver_bindings.*=set noparent
+per-file browser_child_process_host_impl_receiver_bindings.*=file://ipc/SECURITY_OWNERS
+per-file utility_process_host_receiver_bindings.*=set noparent
+per-file utility_process_host_receiver_bindings.*=file://ipc/SECURITY_OWNERS
 
 per-file host_zoom_*=wjmaclean@chromium.org
 per-file find_request_manager*=paulmeyer@chromium.org
@@ -32,10 +32,8 @@
 per-file sandbox_ipc_linux.*=file://sandbox/linux/OWNERS
 
 # Service manifests provided by content require security review
-per-file builtin_service_manifests.cc=set noparent
-per-file builtin_service_manifests.cc=file://ipc/SECURITY_OWNERS
-per-file builtin_service_manifests.h=set noparent
-per-file builtin_service_manifests.h=file://ipc/SECURITY_OWNERS
+per-file builtin_service_manifests.*=set noparent
+per-file builtin_service_manifests.*=file://ipc/SECURITY_OWNERS
 
 # BackForwardCache
 per-file back_forward_cache_browsertest.cc=arthursonzogni@chromium.org
diff --git a/content/browser/background_fetch/BUILD.gn b/content/browser/background_fetch/BUILD.gn
index 07c7108..79d9776dd 100644
--- a/content/browser/background_fetch/BUILD.gn
+++ b/content/browser/background_fetch/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("background_fetch_proto") {
-  sources = [
-    "background_fetch.proto",
-  ]
+  sources = [ "background_fetch.proto" ]
 }
diff --git a/content/browser/bluetooth/tools/BUILD.gn b/content/browser/bluetooth/tools/BUILD.gn
index 5b5556b0..1883569 100644
--- a/content/browser/bluetooth/tools/BUILD.gn
+++ b/content/browser/bluetooth/tools/BUILD.gn
@@ -3,9 +3,7 @@
 # found in the LICENSE file.
 
 executable("bluetooth_metrics_hash") {
-  sources = [
-    "bluetooth_metrics_hash.cc",
-  ]
+  sources = [ "bluetooth_metrics_hash.cc" ]
 
   deps = [
     "//base",
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc
index 4874d01..0bf47f15 100644
--- a/content/browser/cross_origin_opener_policy_browsertest.cc
+++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -160,4 +160,44 @@
       &success));
   EXPECT_TRUE(success) << "window.opener is set";
 }
+
+IN_PROC_BROWSER_TEST_F(CrossOriginOpenerPolicyBrowserTest,
+                       NetworkErrorOnSandboxedPopups) {
+  GURL starting_page(embedded_test_server()->GetURL(
+      "a.com", "/cross-origin-opener-policy_sandbox_popup.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), starting_page));
+
+  ShellAddedObserver shell_observer;
+  RenderFrameHostImpl* iframe =
+      current_frame_host()->child_at(0)->current_frame_host();
+
+  EXPECT_TRUE(ExecJs(
+      iframe, "window.open('/cross-origin-opener-policy_same-origin.html')"));
+
+  auto* popup_webcontents =
+      static_cast<WebContentsImpl*>(shell_observer.GetShell()->web_contents());
+  WaitForLoadStop(popup_webcontents);
+
+  EXPECT_EQ(
+      popup_webcontents->GetController().GetLastCommittedEntry()->GetPageType(),
+      PAGE_TYPE_ERROR);
+}
+
+IN_PROC_BROWSER_TEST_F(CrossOriginOpenerPolicyBrowserTest,
+                       NoNetworkErrorOnSandboxedDocuments) {
+  GURL starting_page(embedded_test_server()->GetURL(
+      "a.com", "/cross-origin-opener-policy_csp_sandboxed.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), starting_page));
+  EXPECT_NE(current_frame_host()->active_sandbox_flags(),
+            blink::WebSandboxFlags::kNone)
+      << "Document should be sandboxed.";
+
+  GURL next_page(embedded_test_server()->GetURL(
+      "a.com", "/cross-origin-opener-policy_same-origin.html"));
+
+  EXPECT_TRUE(NavigateToURL(shell(), next_page));
+  EXPECT_EQ(
+      web_contents()->GetController().GetLastCommittedEntry()->GetPageType(),
+      PAGE_TYPE_NORMAL);
+}
 }  // namespace content
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 087edf5..d97fd26 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -1659,6 +1659,24 @@
         return;
       }
     }
+
+    // Popups with a sandboxing flag, inherited from their opener, are not
+    // allowed to navigate to a document with a Cross-Origin-Opener-Policy that
+    // is not "unsafe-none". This ensures a COOP document does not inherit any
+    // property from an opener.
+    // https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
+    if (response_head_->cross_origin_opener_policy !=
+            network::mojom::CrossOriginOpenerPolicy::kUnsafeNone &&
+        (frame_tree_node_->pending_frame_policy().sandbox_flags !=
+         blink::WebSandboxFlags::kNone)) {
+      OnRequestFailedInternal(
+          network::URLLoaderCompletionStatus(net::ERR_FAILED),
+          false /* skip_throttles */, base::nullopt /* error_page_content */,
+          false /* collapse_frame */);
+      // DO NOT ADD CODE after this. The previous call to
+      // OnRequestFailedInternal has destroyed the NavigationRequest.
+      return;
+    }
   }
 
   // Select an appropriate renderer to commit the navigation.
diff --git a/content/browser/gpu/OWNERS b/content/browser/gpu/OWNERS
index 02ff9e8..44ee3a7 100644
--- a/content/browser/gpu/OWNERS
+++ b/content/browser/gpu/OWNERS
@@ -3,8 +3,8 @@
 backer@chromium.org
 
 # For security review.
-per-file gpu_process_host_receiver_bindings.cc=set noparent
-per-file gpu_process_host_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
+per-file gpu_process_host_receiver_bindings.*=set noparent
+per-file gpu_process_host_receiver_bindings.*=file://ipc/SECURITY_OWNERS
 
 # COMPONENT: Internals>GPU>Internals
 # TEAM: graphics-dev@chromium.org
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc
index c4d217db..9a653bdf 100644
--- a/content/browser/permissions/permission_service_impl.cc
+++ b/content/browser/permissions/permission_service_impl.cc
@@ -12,7 +12,6 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "build/build_config.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/permissions/permission_controller_impl.h"
 #include "content/public/browser/browser_context.h"
@@ -28,100 +27,6 @@
 
 namespace {
 
-bool PermissionDescriptorToPermissionType(
-    const PermissionDescriptorPtr& descriptor,
-    PermissionType* permission_type) {
-  switch (descriptor->name) {
-    case PermissionName::GEOLOCATION:
-      *permission_type = PermissionType::GEOLOCATION;
-      return true;
-    case PermissionName::NOTIFICATIONS:
-      *permission_type = PermissionType::NOTIFICATIONS;
-      return true;
-    case PermissionName::MIDI: {
-      if (descriptor->extension && descriptor->extension->is_midi() &&
-          descriptor->extension->get_midi()->sysex) {
-        *permission_type = PermissionType::MIDI_SYSEX;
-        return true;
-      }
-      *permission_type = PermissionType::MIDI;
-      return true;
-    }
-    case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
-#if defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
-      *permission_type = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
-      return true;
-#else
-      NOTIMPLEMENTED();
-      return false;
-#endif  // defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
-    case PermissionName::DURABLE_STORAGE:
-      *permission_type = PermissionType::DURABLE_STORAGE;
-      return true;
-    case PermissionName::AUDIO_CAPTURE:
-      *permission_type = PermissionType::AUDIO_CAPTURE;
-      return true;
-    case PermissionName::VIDEO_CAPTURE:
-      *permission_type = PermissionType::VIDEO_CAPTURE;
-      return true;
-    case PermissionName::BACKGROUND_SYNC:
-      *permission_type = PermissionType::BACKGROUND_SYNC;
-      return true;
-    case PermissionName::SENSORS:
-      *permission_type = PermissionType::SENSORS;
-      return true;
-    case PermissionName::ACCESSIBILITY_EVENTS:
-      *permission_type = PermissionType::ACCESSIBILITY_EVENTS;
-      return true;
-    case PermissionName::CLIPBOARD_READ:
-      *permission_type = PermissionType::CLIPBOARD_READ_WRITE;
-      return true;
-    case PermissionName::CLIPBOARD_WRITE: {
-      if (descriptor->extension && descriptor->extension->is_clipboard() &&
-          descriptor->extension->get_clipboard()->allowWithoutSanitization) {
-        *permission_type = PermissionType::CLIPBOARD_READ_WRITE;
-      } else {
-        *permission_type = PermissionType::CLIPBOARD_SANITIZED_WRITE;
-      }
-      return true;
-    }
-    case PermissionName::PAYMENT_HANDLER:
-      *permission_type = PermissionType::PAYMENT_HANDLER;
-      return true;
-    case PermissionName::BACKGROUND_FETCH:
-      *permission_type = PermissionType::BACKGROUND_FETCH;
-      return true;
-    case PermissionName::IDLE_DETECTION:
-      *permission_type = PermissionType::IDLE_DETECTION;
-      return true;
-    case PermissionName::PERIODIC_BACKGROUND_SYNC:
-      *permission_type = PermissionType::PERIODIC_BACKGROUND_SYNC;
-      return true;
-    case PermissionName::WAKE_LOCK:
-      if (descriptor->extension && descriptor->extension->is_wake_lock()) {
-        switch (descriptor->extension->get_wake_lock()->type) {
-          case blink::mojom::WakeLockType::kScreen:
-            *permission_type = PermissionType::WAKE_LOCK_SCREEN;
-            break;
-          case blink::mojom::WakeLockType::kSystem:
-            *permission_type = PermissionType::WAKE_LOCK_SYSTEM;
-            break;
-          default:
-            NOTREACHED();
-            return false;
-        }
-        return true;
-      }
-      break;
-    case PermissionName::NFC:
-      *permission_type = PermissionType::NFC;
-      return true;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
 // This function allows the usage of the the multiple request map with single
 // requests.
 void PermissionRequestResponseCallbackWrapper(
@@ -204,10 +109,14 @@
   std::vector<PermissionType> types(permissions.size());
   std::set<PermissionType> duplicates_check;
   for (size_t i = 0; i < types.size(); ++i) {
-    if (!PermissionDescriptorToPermissionType(permissions[i], &types[i])) {
+    auto type = PermissionDescriptorToPermissionType(permissions[i]);
+    if (!type) {
       ReceivedBadMessage();
       return;
     }
+
+    types[i] = *type;
+
     // Each permission should appear at most once in the message.
     bool inserted = duplicates_check.insert(types[i]).second;
     if (!inserted) {
@@ -253,12 +162,12 @@
 void PermissionServiceImpl::RevokePermission(
     PermissionDescriptorPtr permission,
     PermissionStatusCallback callback) {
-  PermissionType permission_type;
-  if (!PermissionDescriptorToPermissionType(permission, &permission_type)) {
+  auto permission_type = PermissionDescriptorToPermissionType(permission);
+  if (!permission_type) {
     ReceivedBadMessage();
     return;
   }
-  PermissionStatus status = GetPermissionStatusFromType(permission_type);
+  PermissionStatus status = GetPermissionStatusFromType(*permission_type);
 
   // Resetting the permission should only be possible if the permission is
   // already granted.
@@ -267,33 +176,33 @@
     return;
   }
 
-  ResetPermissionStatus(permission_type);
+  ResetPermissionStatus(*permission_type);
 
-  std::move(callback).Run(GetPermissionStatusFromType(permission_type));
+  std::move(callback).Run(GetPermissionStatusFromType(*permission_type));
 }
 
 void PermissionServiceImpl::AddPermissionObserver(
     PermissionDescriptorPtr permission,
     PermissionStatus last_known_status,
     mojo::PendingRemote<blink::mojom::PermissionObserver> observer) {
-  PermissionType type;
-  if (!PermissionDescriptorToPermissionType(permission, &type)) {
+  auto type = PermissionDescriptorToPermissionType(permission);
+  if (!type) {
     ReceivedBadMessage();
     return;
   }
 
-  context_->CreateSubscription(type, origin_, GetPermissionStatus(permission),
+  context_->CreateSubscription(*type, origin_, GetPermissionStatus(permission),
                                last_known_status, std::move(observer));
 }
 
 PermissionStatus PermissionServiceImpl::GetPermissionStatus(
     const PermissionDescriptorPtr& permission) {
-  PermissionType type;
-  if (!PermissionDescriptorToPermissionType(permission, &type)) {
+  auto type = PermissionDescriptorToPermissionType(permission);
+  if (!type) {
     ReceivedBadMessage();
     return PermissionStatus::DENIED;
   }
-  return GetPermissionStatusFromType(type);
+  return GetPermissionStatusFromType(*type);
 }
 
 PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index ad39a957..195b0f2 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -396,11 +396,8 @@
 }
 
 void RenderViewHostImpl::SetMainFrameRoutingId(int routing_id) {
-  bool was_active = is_active();
   main_frame_routing_id_ = routing_id;
   GetWidget()->UpdatePriority();
-  if (was_active && !is_active())
-    GetWidget()->DidDestroyRenderWidget();
 }
 
 void RenderViewHostImpl::EnterBackForwardCache() {
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 4058979..8bbf0457 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -718,10 +718,10 @@
 VisualProperties RenderWidgetHostImpl::GetInitialVisualProperties() {
   VisualProperties initial_props = GetVisualProperties();
 
-  old_visual_properties_ = nullptr;
-  visual_properties_ack_pending_ =
-      DoesVisualPropertiesNeedAck(old_visual_properties_, initial_props);
-  old_visual_properties_ = std::make_unique<VisualProperties>(initial_props);
+  // A RenderWidget being created in the renderer means the browser should
+  // reset any state that may be set for the previous RenderWidget but which
+  // will be incorrect with a fresh RenderWidget.
+  ResetStateForCreatedRenderWidget(initial_props);
 
   return initial_props;
 }
@@ -1833,8 +1833,6 @@
   // from a crashed renderer.
   renderer_initialized_ = false;
 
-  waiting_for_screen_rects_ack_ = false;
-
   // After the renderer crashes, the view is destroyed and so the
   // RenderWidgetHost cannot track its visibility anymore. We assume such
   // RenderWidgetHost to be invisible for the sake of internal accounting - be
@@ -1854,20 +1852,17 @@
     view_->RenderProcessGone();
     SetView(nullptr);  // The View should be deleted by RenderProcessGone.
   }
-
-  ResetRenderWidgetState();
 }
 
-void RenderWidgetHostImpl::DidDestroyRenderWidget() {
-  if (owner_delegate_)
-    DCHECK(!owner_delegate_->IsMainFrameActive());
-  ResetRenderWidgetState();
-}
+void RenderWidgetHostImpl::ResetStateForCreatedRenderWidget(
+    const VisualProperties& initial_props) {
+  // When the RenderWidget was destroyed, the ack may never come back. Don't
+  // let that prevent us from speaking to the next RenderWidget.
+  waiting_for_screen_rects_ack_ = false;
 
-void RenderWidgetHostImpl::ResetRenderWidgetState() {
-  // Must reset these to ensure that keyboard events work with a new
-  // RenderWidget.
-  suppress_events_until_keydown_ = false;
+  visual_properties_ack_pending_ =
+      DoesVisualPropertiesNeedAck(nullptr, initial_props);
+  old_visual_properties_ = std::make_unique<VisualProperties>(initial_props);
 
   // Reconstruct the input router to ensure that it has fresh state for a new
   // RenderWidget. Otherwise it may be stuck waiting for the old renderer to ack
@@ -2917,17 +2912,6 @@
 }
 
 void RenderWidgetHostImpl::DidProcessFrame(uint32_t frame_token) {
-  // In this case the RenderWidgetHostImpl is still here because it's the top
-  // level RenderWidgetHostImpl, but the renderer's RenderWidget no longer
-  // exists and this would clobber state that was reset in
-  // DidDestroyRenderWidget() with data from the destroyed RenderWidget.
-  if (owner_delegate_ && !owner_delegate_->IsMainFrameActive())
-    return;
-  // This is similar to the above but when the renderer process has crashed, so
-  // more objects are gone than the RenderWidget.
-  if (!renderer_initialized_)
-    return;
-
   frame_token_message_queue_->DidProcessFrame(frame_token);
 }
 
@@ -2949,6 +2933,7 @@
 
 void RenderWidgetHostImpl::SetupInputRouter() {
   in_flight_event_count_ = 0;
+  suppress_events_until_keydown_ = false;
   StopInputEventAckTimeout();
   associated_widget_input_handler_.reset();
   widget_input_handler_.reset();
@@ -2985,16 +2970,18 @@
 
 void RenderWidgetHostImpl::SetWidget(
     mojo::PendingRemote<mojom::Widget> widget_remote) {
-  if (widget_remote) {
-    // If we have a bound handler ensure that we destroy the old input router.
-    if (widget_input_handler_.is_bound())
-      SetupInputRouter();
+  if (!widget_remote)
+    return;
 
-    mojo::Remote<mojom::Widget> widget(std::move(widget_remote));
-    widget->SetupWidgetInputHandler(
-        widget_input_handler_.BindNewPipeAndPassReceiver(),
-        input_router_->BindNewHost());
-  }
+  // If we have a bound handler ensure that we destroy the old input router
+  // while we reset the |widget_input_handler_|.
+  if (widget_input_handler_.is_bound())
+    SetupInputRouter();
+
+  mojo::Remote<mojom::Widget> widget(std::move(widget_remote));
+  widget->SetupWidgetInputHandler(
+      widget_input_handler_.BindNewPipeAndPassReceiver(),
+      input_router_->BindNewHost());
 }
 
 void RenderWidgetHostImpl::ProgressFlingIfNeeded(TimeTicks current_time) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index dd9d0ec..ff2505c 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -314,11 +314,6 @@
   void SetFrameDepth(unsigned int depth);
   void SetIntersectsViewport(bool intersects);
   void UpdatePriority();
-  // If there is no local main frame, then the RenderWidget in the renderer
-  // has been destroyed, and a new one will be created when a main frame
-  // exists again. This notifies that the renderer-side RenderWidget has been
-  // destroyed.
-  void DidDestroyRenderWidget();
 
   // Tells the renderer to die and optionally delete |this|.
   void ShutdownAndDestroyWidget(bool also_delete);
@@ -607,6 +602,9 @@
   // getting VisualProperties that will be sent in order to create a
   // RenderWidget, since the creation acts as the initial
   // SynchronizeVisualProperties().
+  //
+  // This has the side effect of resetting state that should match a newly
+  // created RenderWidget in the renderer.
   VisualProperties GetInitialVisualProperties();
 
   // Pushes updated visual properties to the renderer as well as whether the
@@ -864,9 +862,9 @@
                                          const gfx::Rect& rect_to_zoom);
   void OnZoomToFindInPageRectInMainFrame(const gfx::Rect& rect_to_zoom);
 
-  // When the RenderWidget is destroyed, this resets states in the browser
-  // to be ready for a replacement RenderWidget with a clean start.
-  void ResetRenderWidgetState();
+  // When the RenderWidget is destroyed and recreated, this resets states in the
+  // browser to match the clean start for the renderer side.
+  void ResetStateForCreatedRenderWidget(const VisualProperties& initial_props);
 
   // Generates a filled in VisualProperties struct representing the current
   // properties of this widget.
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 87faeb1..788e1f1 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -517,12 +517,13 @@
     view_ = std::make_unique<TestView>(host_.get());
     ConfigureView(view_.get());
     host_->SetView(view_.get());
-    host_->Init();
     host_->DisableGestureDebounce();
     // Act like we've created a RenderWidget.
     host_->GetInitialVisualProperties();
     EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
         .WillRepeatedly(Return(true));
+    // Init() happens once the navigation completes.
+    host_->Init();
 
     mojo::PendingRemote<mojom::RenderFrameMetadataObserver>
         renderer_render_frame_metadata_observer_remote;
@@ -972,9 +973,8 @@
 
   // The renderer is recreated.
   host_->SetView(view_.get());
-  // Make a new RenderWidget when the renderer is recreated. This should get
-  // properties that are intended to be sent to the renderer, obsoleting any
-  // previous SynchronizeVisualProperties() calls.
+  // Make a new RenderWidget when the renderer is recreated and inform that a
+  // RenderWidget is being created.
   VisualProperties props = host_->GetInitialVisualProperties();
   // The RenderWidget is recreated with the initial VisualProperties.
   host_->Init();
@@ -994,15 +994,13 @@
   // RenderWidgetView is still kept around for another RenderFrame.
   EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
       .WillRepeatedly(Return(false));
-  host_->DidDestroyRenderWidget();
 
   // Receive an in-flight frame token (it needs to monotonically increase)
   // while the RenderWidget is gone.
   host_->DidProcessFrame(3);
 
-  // Make a new RenderWidget for the RenderWidget being recreated. This should
-  // get properties that are intended to be sent to the renderer, obsoleting any
-  // previous SynchronizeVisualProperties() calls.
+  // Make a new RenderWidget when the renderer is recreated and inform that a
+  // RenderWidget is being created.
   VisualProperties props = host_->GetInitialVisualProperties();
   // The RenderWidget is recreated with the initial VisualProperties.
   EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
@@ -1610,31 +1608,139 @@
 }
 
 TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
+  EXPECT_EQ(0u, host_->in_flight_event_count());
+  SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+  EXPECT_EQ(1u, host_->in_flight_event_count());
+
+  EXPECT_FALSE(host_->input_router()->HasPendingEvents());
   blink::WebMouseWheelEvent event;
   event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
   host_->input_router()->SendWheelEvent(MouseWheelEventWithLatencyInfo(event));
-  ASSERT_TRUE(host_->input_router()->HasPendingEvents());
+  EXPECT_TRUE(host_->input_router()->HasPendingEvents());
 
   // RendererExited will delete the view.
   host_->SetView(new TestView(host_.get()));
   host_->RendererExited();
 
+  // The renderer is recreated.
+  host_->SetView(view_.get());
+  // Make a new RenderWidget when the renderer is recreated and inform that a
+  // RenderWidget is being created.
+  VisualProperties props = host_->GetInitialVisualProperties();
+  // The RenderWidget is recreated with the initial VisualProperties.
+  host_->Init();
+
   // Make sure the input router is in a fresh state.
   ASSERT_FALSE(host_->input_router()->HasPendingEvents());
+  // There should be no in flight events. https://crbug.com/615090#152.
+  EXPECT_EQ(0u, host_->in_flight_event_count());
 }
 
 TEST_F(RenderWidgetHostTest, DestroyingRenderWidgetResetsInputRouter) {
+  EXPECT_EQ(0u, host_->in_flight_event_count());
+  SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
+  EXPECT_EQ(1u, host_->in_flight_event_count());
+
+  EXPECT_FALSE(host_->input_router()->HasPendingEvents());
   blink::WebMouseWheelEvent event;
   event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
   host_->input_router()->SendWheelEvent(MouseWheelEventWithLatencyInfo(event));
-  ASSERT_TRUE(host_->input_router()->HasPendingEvents());
+  EXPECT_TRUE(host_->input_router()->HasPendingEvents());
 
+  // The RenderWidget is destroyed in the renderer process as the main frame
+  // is removed from this RenderWidgetHost's RenderWidgetView, but the
+  // RenderWidgetView is still kept around for another RenderFrame.
   EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
       .WillRepeatedly(Return(false));
-  host_->DidDestroyRenderWidget();
+
+  // Make a new RenderWidget when the renderer is recreated and inform that a
+  // RenderWidget is being created.
+  VisualProperties props = host_->GetInitialVisualProperties();
+  // The RenderWidget is recreated with the initial VisualProperties.
+  EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
+      .WillRepeatedly(Return(true));
 
   // Make sure the input router is in a fresh state.
-  ASSERT_FALSE(host_->input_router()->HasPendingEvents());
+  EXPECT_FALSE(host_->input_router()->HasPendingEvents());
+  // There should be no in flight events. https://crbug.com/615090#152.
+  EXPECT_EQ(0u, host_->in_flight_event_count());
+}
+
+TEST_F(RenderWidgetHostTest, RendererExitedResetsScreenRectsAck) {
+  auto count_screen_rect_messages = [&]() {
+    int count = 0;
+    for (uint32_t i = 0; i < sink_->message_count(); ++i) {
+      if (sink_->GetMessageAt(i)->type() == WidgetMsg_UpdateScreenRects::ID)
+        ++count;
+    }
+    return count;
+  };
+
+  // Screen rects are sent during initialization, but we are waiting for an ack.
+  EXPECT_EQ(1, count_screen_rect_messages());
+  // Waiting for the ack prevents further sending.
+  host_->SendScreenRects();
+  host_->SendScreenRects();
+  EXPECT_EQ(1, count_screen_rect_messages());
+
+  // RendererExited will delete the view.
+  host_->SetView(new TestView(host_.get()));
+  host_->RendererExited();
+
+  // Still can't send until the RenderWidget is replaced.
+  host_->SendScreenRects();
+  EXPECT_EQ(1, count_screen_rect_messages());
+
+  // The renderer is recreated.
+  host_->SetView(view_.get());
+  // Make a new RenderWidget when the renderer is recreated and inform that a
+  // RenderWidget is being created.
+  VisualProperties props = host_->GetInitialVisualProperties();
+  // The RenderWidget is recreated with the initial VisualProperties.
+  host_->Init();
+
+  // The RenderWidget is shown when navigation completes. This sends screen
+  // rects again. The IPC is sent as it's not waiting for an ack.
+  host_->WasShown(base::nullopt);
+  EXPECT_EQ(2, count_screen_rect_messages());
+}
+
+TEST_F(RenderWidgetHostTest, DestroyingRenderWidgetResetsScreenRectsAck) {
+  auto count_screen_rect_messages = [&]() {
+    int count = 0;
+    for (uint32_t i = 0; i < sink_->message_count(); ++i) {
+      if (sink_->GetMessageAt(i)->type() == WidgetMsg_UpdateScreenRects::ID)
+        ++count;
+    }
+    return count;
+  };
+
+  // Screen rects are sent during initialization, but we are waiting for an ack.
+  EXPECT_EQ(1, count_screen_rect_messages());
+  // Waiting for the ack prevents further sending.
+  host_->SendScreenRects();
+  host_->SendScreenRects();
+  EXPECT_EQ(1, count_screen_rect_messages());
+
+  // The RenderWidget has been destroyed in the renderer.
+  EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
+      .WillRepeatedly(Return(false));
+
+  // Still can't send until the RenderWidget is replaced.
+  host_->SendScreenRects();
+  EXPECT_EQ(1, count_screen_rect_messages());
+
+  // Make a new RenderWidget when the renderer is recreated and inform that a
+  // RenderWidget is being created.
+  VisualProperties props = host_->GetInitialVisualProperties();
+  // The RenderWidget is recreated with the initial VisualProperties.
+  EXPECT_CALL(mock_owner_delegate_, IsMainFrameActive())
+      .WillRepeatedly(Return(true));
+
+  // We are able to send screen rects again. The IPC is sent as it's not waiting
+  // for an ack.
+  host_->SendScreenRects();
+  EXPECT_EQ(2, count_screen_rect_messages());
 }
 
 // Regression test for http://crbug.com/401859 and http://crbug.com/522795.
@@ -1885,18 +1991,6 @@
   EXPECT_EQ(2u, host_->processed_frame_messages_count());
 }
 
-TEST_F(RenderWidgetHostTest, InflightEventCountResetsAfterRebind) {
-  // Simulate a keyboard event.
-  SimulateKeyboardEvent(WebInputEvent::kRawKeyDown);
-
-  EXPECT_EQ(1u, host_->in_flight_event_count());
-  mojo::PendingRemote<mojom::Widget> widget;
-  std::unique_ptr<MockWidgetImpl> widget_impl =
-      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
-  host_->SetWidget(std::move(widget));
-  EXPECT_EQ(0u, host_->in_flight_event_count());
-}
-
 TEST_F(RenderWidgetHostTest, ForceEnableZoomShouldUpdateAfterRebind) {
   SCOPED_TRACE("force_enable_zoom is false at start.");
   host_->ExpectForceEnableZoom(false);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 8d7acf87..89cbdb4d 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -363,6 +363,7 @@
   friend class InputMethodAuraTestBase;
   friend class RenderWidgetHostViewAuraTest;
   friend class RenderWidgetHostViewAuraBrowserTest;
+  friend class RenderWidgetHostViewAuraDevtoolsBrowserTest;
   friend class RenderWidgetHostViewAuraCopyRequestTest;
   friend class TestInputMethodObserver;
 #if defined(OS_WIN)
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
index 2c044cc0..8e48f2683 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
@@ -7,7 +7,9 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
 #include "content/browser/renderer_host/delegated_frame_host.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
@@ -19,6 +21,7 @@
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
+#include "ui/events/event_utils.h"
 
 namespace content {
 namespace {
@@ -194,4 +197,105 @@
 }
 #endif  // #if defined(OS_CHROMEOS)
 
+class RenderWidgetHostViewAuraDevtoolsBrowserTest
+    : public content::DevToolsProtocolTest {
+ public:
+  RenderWidgetHostViewAuraDevtoolsBrowserTest() = default;
+
+ protected:
+  aura::Window* window() {
+    return reinterpret_cast<content::RenderWidgetHostViewAura*>(
+               shell()->web_contents()->GetRenderWidgetHostView())
+        ->window();
+  }
+
+  bool HasChildPopup() const {
+    return reinterpret_cast<content::RenderWidgetHostViewAura*>(
+               shell()->web_contents()->GetRenderWidgetHostView())
+        ->popup_child_host_view_;
+  }
+};
+
+// This test opens a select popup which inside breaks the debugger
+// which enters a nested event loop.
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraDevtoolsBrowserTest,
+                       NoCrashOnSelect) {
+  GURL page(
+      "data:text/html;charset=utf-8,"
+      "<!DOCTYPE html>"
+      "<html>"
+      "<body>"
+      "<select id=\"ddlChoose\">"
+      " <option value=\"\">Choose</option>"
+      " <option value=\"A\">A</option>"
+      " <option value=\"B\">B</option>"
+      " <option value=\"C\">C</option>"
+      "</select>"
+      "<script type=\"text/javascript\">"
+      "  document.getElementById('ddlChoose').addEventListener('change', "
+      "    function () {"
+      "      debugger;"
+      "    });"
+      "  function focusSelectMenu() {"
+      "    document.getElementById('ddlChoose').focus();"
+      "  }"
+      "  function noop() {"
+      "  }"
+      "</script>"
+      "</body>"
+      "</html>");
+
+  EXPECT_TRUE(NavigateToURL(shell(), page));
+  auto* wc = shell()->web_contents();
+  Attach();
+  SendCommand("Debugger.enable", nullptr);
+
+  ASSERT_TRUE(ExecuteScript(wc, "focusSelectMenu();"));
+  SimulateKeyPress(wc, ui::DomKey::FromCharacter(' '), ui::DomCode::SPACE,
+                   ui::VKEY_SPACE, false, false, false, false);
+
+  // Wait until popup is opened.
+  while (!HasChildPopup()) {
+    base::RunLoop().RunUntilIdle();
+    base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
+  }
+
+  // Send down and enter to select next item and cause change listener to fire.
+  // The event listener causes devtools to break (and enter a nested event
+  // loop).
+  ui::KeyEvent press_down(ui::ET_KEY_PRESSED, ui::VKEY_DOWN,
+                          ui::DomCode::ARROW_DOWN, ui::EF_NONE,
+                          ui::DomKey::ARROW_DOWN, ui::EventTimeForNow());
+  ui::KeyEvent release_down(ui::ET_KEY_RELEASED, ui::VKEY_DOWN,
+                            ui::DomCode::ARROW_DOWN, ui::EF_NONE,
+                            ui::DomKey::ARROW_DOWN, ui::EventTimeForNow());
+  ui::KeyEvent press_enter(ui::ET_KEY_PRESSED, ui::VKEY_RETURN,
+                           ui::DomCode::ENTER, ui::EF_NONE, ui::DomKey::ENTER,
+                           ui::EventTimeForNow());
+  ui::KeyEvent release_enter(ui::ET_KEY_RELEASED, ui::VKEY_RETURN,
+                             ui::DomCode::ENTER, ui::EF_NONE, ui::DomKey::ENTER,
+                             ui::EventTimeForNow());
+  auto* host_view_aura = static_cast<content::RenderWidgetHostViewAura*>(
+      wc->GetRenderWidgetHostView());
+  host_view_aura->OnKeyEvent(&press_down);
+  host_view_aura->OnKeyEvent(&release_down);
+  host_view_aura->OnKeyEvent(&press_enter);
+  host_view_aura->OnKeyEvent(&release_enter);
+  WaitForNotification("Debugger.paused");
+
+  // Close the widget window while inside the nested event loop.
+  // This will cause the RenderWidget to be destroyed while we are inside a
+  // method and used to cause UAF when the nested event loop unwinds.
+  window()->Hide();
+
+  // Disconnect devtools causes script to resume. This causes the unwind of the
+  // nested event loop. The RenderWidget that was entered has been destroyed,
+  // make sure that we detect this and don't touch any members in the class.
+  Detach();
+
+  // Try to access the renderer process, it would have died if
+  // crbug.com/1032984 wasn't fixed.
+  ASSERT_TRUE(ExecuteScript(wc, "noop();"));
+}
+
 }  // namespace content
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index bb0d2623..5402a26 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -6751,8 +6751,7 @@
  protected:
   // Load the page |host_name| and retrieve the hit test data from HitTestQuery.
   std::vector<viz::AggregatedHitTestRegion> SetupAndGetHitTestData(
-      const std::string& host_name,
-      unsigned skipped_child = -1) {
+      const std::string& host_name) {
     GURL main_url(embedded_test_server()->GetURL(host_name));
     EXPECT_TRUE(NavigateToURL(shell(), main_url));
 
@@ -6765,11 +6764,7 @@
             root->current_frame_host()->GetRenderWidgetHost()->GetView());
 
     for (unsigned i = 0; i < root->child_count(); i++) {
-      // Child with pointer-events: none property will never submit a hit test
-      // region in /2 hit testing.
-      if (i != skipped_child) {
         WaitForHitTestData(root->child_at(i)->current_frame_host());
-      }
     }
 
     HitTestRegionObserver observer(rwhv_root->GetRootFrameSinkId());
@@ -7071,7 +7066,7 @@
 IN_PROC_BROWSER_TEST_F(SitePerProcessHitTestDataGenerationBrowserTest,
                        PointerEventsNoneOOPIF) {
   auto hit_test_data = SetupAndGetHitTestData(
-      "/frame_tree/page_with_positioned_frame_pointer-events_none.html", 0);
+      "/frame_tree/page_with_positioned_frame_pointer-events_none.html");
   float device_scale_factor = current_device_scale_factor();
   gfx::Transform expected_transform;
   gfx::Rect expected_region = gfx::ScaleToEnclosingRect(
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn
index d777b76..7917db1 100644
--- a/content/gpu/BUILD.gn
+++ b/content/gpu/BUILD.gn
@@ -13,13 +13,9 @@
   visibility = [ "//content/*" ]  # This is an internal content API.
 
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":gpu_sources",
-    ]
+    public_deps = [ ":gpu_sources" ]
   }
 }
 
diff --git a/content/gpu/OWNERS b/content/gpu/OWNERS
index 934c7f6e..5fd6529 100644
--- a/content/gpu/OWNERS
+++ b/content/gpu/OWNERS
@@ -2,9 +2,9 @@
 zmo@chromium.org
 
 # For security review.
-per-file browser_exposed_gpu_interfaces.cc=set noparent
-per-file browser_exposed_gpu_interfaces.cc=file://ipc/SECURITY_OWNERS
-per-file gpu_child_thread_receiver_bindings.cc=set noparent
-per-file gpu_child_thread_receiver_bindings.cc=file://ipc/SECURITY_OWNERS
+per-file browser_exposed_gpu_interfaces.*=set noparent
+per-file browser_exposed_gpu_interfaces.*=file://ipc/SECURITY_OWNERS
+per-file gpu_child_thread_receiver_bindings.*=set noparent
+per-file gpu_child_thread_receiver_bindings.*=file://ipc/SECURITY_OWNERS
 
 # COMPONENT: Internals>GPU>Internals
diff --git a/content/ppapi_plugin/BUILD.gn b/content/ppapi_plugin/BUILD.gn
index 2ffd7e4..35505cd 100644
--- a/content/ppapi_plugin/BUILD.gn
+++ b/content/ppapi_plugin/BUILD.gn
@@ -10,13 +10,9 @@
   visibility = [ "//content/*" ]  # This is an internal content API.
 
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":ppapi_plugin_sources",
-    ]
+    public_deps = [ ":ppapi_plugin_sources" ]
   }
 }
 
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 53027c5a..6dee2be 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -14,13 +14,9 @@
 # See //content/BUILD.gn for how this works.
 group("browser") {
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":browser_sources",
-    ]
+    public_deps = [ ":browser_sources" ]
   }
 }
 
@@ -470,6 +466,10 @@
     "//content/browser",
   ]
 
+  if (is_chromeos || is_android || is_chromecast || is_fuchsia) {
+    defines = [ "ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION" ]
+  }
+
   if (is_posix || is_fuchsia) {
     sources += [ "posix_file_descriptor_info.h" ]
   }
@@ -501,8 +501,6 @@
 
 if (is_android) {
   java_cpp_enum("contacts_picker_properties_requested_javagen") {
-    sources = [
-      "contacts_picker_properties_requested.h",
-    ]
+    sources = [ "contacts_picker_properties_requested.h" ]
   }
 }
diff --git a/content/public/browser/permission_type.cc b/content/public/browser/permission_type.cc
index 77902ac3..05632368 100644
--- a/content/public/browser/permission_type.cc
+++ b/content/public/browser/permission_type.cc
@@ -6,6 +6,12 @@
 
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
+#include "build/build_config.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
+
+using blink::mojom::PermissionDescriptorPtr;
+using blink::mojom::PermissionName;
+using blink::mojom::PermissionStatus;
 
 namespace content {
 
@@ -25,4 +31,78 @@
   return *kAllPermissionTypes;
 }
 
+base::Optional<PermissionType> PermissionDescriptorToPermissionType(
+    const PermissionDescriptorPtr& descriptor) {
+  switch (descriptor->name) {
+    case PermissionName::GEOLOCATION:
+      return PermissionType::GEOLOCATION;
+    case PermissionName::NOTIFICATIONS:
+      return PermissionType::NOTIFICATIONS;
+    case PermissionName::MIDI: {
+      if (descriptor->extension && descriptor->extension->is_midi() &&
+          descriptor->extension->get_midi()->sysex) {
+        return PermissionType::MIDI_SYSEX;
+      }
+      return PermissionType::MIDI;
+    }
+    case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
+#if defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
+      return PermissionType::PROTECTED_MEDIA_IDENTIFIER;
+#else
+      NOTIMPLEMENTED();
+      return base::nullopt;
+#endif  // defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
+    case PermissionName::DURABLE_STORAGE:
+      return PermissionType::DURABLE_STORAGE;
+    case PermissionName::AUDIO_CAPTURE:
+      return PermissionType::AUDIO_CAPTURE;
+    case PermissionName::VIDEO_CAPTURE:
+      return PermissionType::VIDEO_CAPTURE;
+    case PermissionName::BACKGROUND_SYNC:
+      return PermissionType::BACKGROUND_SYNC;
+    case PermissionName::SENSORS:
+      return PermissionType::SENSORS;
+    case PermissionName::ACCESSIBILITY_EVENTS:
+      return PermissionType::ACCESSIBILITY_EVENTS;
+    case PermissionName::CLIPBOARD_READ:
+      return PermissionType::CLIPBOARD_READ_WRITE;
+    case PermissionName::CLIPBOARD_WRITE: {
+      if (descriptor->extension && descriptor->extension->is_clipboard() &&
+          descriptor->extension->get_clipboard()->allowWithoutSanitization) {
+        return PermissionType::CLIPBOARD_READ_WRITE;
+      } else {
+        return PermissionType::CLIPBOARD_SANITIZED_WRITE;
+      }
+    }
+    case PermissionName::PAYMENT_HANDLER:
+      return PermissionType::PAYMENT_HANDLER;
+    case PermissionName::BACKGROUND_FETCH:
+      return PermissionType::BACKGROUND_FETCH;
+    case PermissionName::IDLE_DETECTION:
+      return PermissionType::IDLE_DETECTION;
+    case PermissionName::PERIODIC_BACKGROUND_SYNC:
+      return PermissionType::PERIODIC_BACKGROUND_SYNC;
+    case PermissionName::WAKE_LOCK:
+      if (descriptor->extension && descriptor->extension->is_wake_lock()) {
+        switch (descriptor->extension->get_wake_lock()->type) {
+          case blink::mojom::WakeLockType::kScreen:
+            return PermissionType::WAKE_LOCK_SCREEN;
+            break;
+          case blink::mojom::WakeLockType::kSystem:
+            return PermissionType::WAKE_LOCK_SYSTEM;
+            break;
+          default:
+            NOTREACHED();
+            return base::nullopt;
+        }
+      }
+      break;
+    case PermissionName::NFC:
+      return PermissionType::NFC;
+  }
+
+  NOTREACHED();
+  return base::nullopt;
+}
+
 }  // namespace content
diff --git a/content/public/browser/permission_type.h b/content/public/browser/permission_type.h
index fb79c710..187712c 100644
--- a/content/public/browser/permission_type.h
+++ b/content/public/browser/permission_type.h
@@ -7,7 +7,9 @@
 
 #include <vector>
 
+#include "base/optional.h"
 #include "content/common/content_export.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-forward.h"
 
 namespace content {
 
@@ -51,6 +53,11 @@
 
 CONTENT_EXPORT const std::vector<PermissionType>& GetAllPermissionTypes();
 
+// Given |descriptor|, set |permission_type| to a corresponding PermissionType.
+CONTENT_EXPORT base::Optional<PermissionType>
+PermissionDescriptorToPermissionType(
+    const blink::mojom::PermissionDescriptorPtr& descriptor);
+
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_BROWSER_PERMISSION_TYPE_H_
diff --git a/content/public/child/BUILD.gn b/content/public/child/BUILD.gn
index c7f6f6a..e16d75c 100644
--- a/content/public/child/BUILD.gn
+++ b/content/public/child/BUILD.gn
@@ -8,13 +8,9 @@
 # See //content/BUILD.gn for how this works.
 group("child") {
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":child_sources",
-    ]
+    public_deps = [ ":child_sources" ]
     if (!is_android) {
       public_deps += [ "//content/gpu" ]
     }
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index 1f05fef..f71f387 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -15,41 +15,29 @@
 # See //content/BUILD.gn for how this works.
 group("common") {
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":common_sources",
-    ]
+    public_deps = [ ":common_sources" ]
   }
 }
 
 # This target allows other targets to depend on result_codes.h which is a
 # header-only dependency, without bringing in all of content.
 source_set("result_codes") {
-  sources = [
-    "result_codes.h",
-  ]
+  sources = [ "result_codes.h" ]
 
-  deps = [
-    "//services/service_manager/embedder:embedder_result_codes",
-  ]
+  deps = [ "//services/service_manager/embedder:embedder_result_codes" ]
 }
 
 # This target allows other targets to depend on content_descriptors.h which is
 # a header-only dependency, without bringing in all of content.
 source_set("content_descriptors") {
-  sources = [
-    "content_descriptors.h",
-  ]
+  sources = [ "content_descriptors.h" ]
 
   # The header uses V8_USE_EXTERNAL_STARTUP_DATA.
   public_configs = [ "//v8:external_startup_data" ]
 
-  deps = [
-    "//ipc",
-  ]
+  deps = [ "//ipc" ]
 }
 
 source_set("content_descriptor_keys") {
@@ -71,9 +59,7 @@
 # link to it, without depending on the rest of content. This is only for use
 # without content, or you will get multiply defined symbols.
 source_set("static_switches") {
-  public = [
-    "content_switches.h",
-  ]
+  public = [ "content_switches.h" ]
   sources = [
     "//content/common/content_export.h",
     "content_switches.cc",
@@ -82,25 +68,19 @@
   public_configs = [ ":static_switches_defines" ]
 
   # Deps required by the above headers.
-  deps = [
-    "//media:media_buildflags",
-  ]
+  deps = [ "//media:media_buildflags" ]
 }
 
 # This target allows you to use the content_features constants and statically
 # link to it, without depending on the rest of content. This is only for use
 # without content, or you will get multiply defined symbols.
 source_set("static_features") {
-  public = [
-    "content_features.h",
-  ]
+  public = [ "content_features.h" ]
   sources = [
     "//content/common/content_export.h",
     "content_features.cc",
   ]
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 
   public_configs = [ ":static_switches_defines" ]
 
@@ -314,12 +294,8 @@
 # //content/public/common:interfaces ->
 # //content/public/common:resource_type_bindings ->
 source_set("resource_type_header") {
-  sources = [
-    "resource_type.h",
-  ]
-  public_deps = [
-    "//content:export",
-  ]
+  sources = [ "resource_type.h" ]
+  public_deps = [ "//content:export" ]
 }
 
 mojom("interfaces") {
@@ -371,9 +347,7 @@
 }
 
 mojom("client_hints_mojom") {
-  sources = [
-    "client_hints.mojom",
-  ]
+  sources = [ "client_hints.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
@@ -383,13 +357,9 @@
 }
 
 mojom("service_names") {
-  sources = [
-    "service_names.mojom",
-  ]
+  sources = [ "service_names.mojom" ]
 }
 
 mojom("resource_type_bindings") {
-  sources = [
-    "resource_type.mojom",
-  ]
+  sources = [ "resource_type.mojom" ]
 }
diff --git a/content/public/gpu/BUILD.gn b/content/public/gpu/BUILD.gn
index 717fc4b..a5c99cd 100644
--- a/content/public/gpu/BUILD.gn
+++ b/content/public/gpu/BUILD.gn
@@ -5,13 +5,9 @@
 # See //content/BUILD.gn for how this works.
 group("gpu") {
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":gpu_sources",
-    ]
+    public_deps = [ ":gpu_sources" ]
   }
 }
 
diff --git a/content/public/renderer/BUILD.gn b/content/public/renderer/BUILD.gn
index 9e21dea..5114462 100644
--- a/content/public/renderer/BUILD.gn
+++ b/content/public/renderer/BUILD.gn
@@ -10,13 +10,9 @@
 # See //content/BUILD.gn for how this works.
 group("renderer") {
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":renderer_sources",
-    ]
+    public_deps = [ ":renderer_sources" ]
   }
 }
 
@@ -74,9 +70,7 @@
 
   configs += [ "//content:content_implementation" ]
 
-  public_deps = [
-    "//media",
-  ]
+  public_deps = [ "//media" ]
 
   deps = [
     "//content/public/child:child_sources",
diff --git a/content/public/utility/BUILD.gn b/content/public/utility/BUILD.gn
index 31d1fdd..031e9ba 100644
--- a/content/public/utility/BUILD.gn
+++ b/content/public/utility/BUILD.gn
@@ -5,13 +5,9 @@
 # See //content/BUILD.gn for how this works.
 group("utility") {
   if (is_component_build) {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   } else {
-    public_deps = [
-      ":utility_sources",
-    ]
+    public_deps = [ ":utility_sources" ]
   }
 }
 
diff --git a/content/renderer/ime_event_guard.cc b/content/renderer/ime_event_guard.cc
index c6f5b0b..0ad1636 100644
--- a/content/renderer/ime_event_guard.cc
+++ b/content/renderer/ime_event_guard.cc
@@ -12,13 +12,14 @@
 // is set only for OnRequestTextInputStateUpdate() so that we can distinguish
 // it from other updates so that we can wait for it safely. So it is false by
 // default.
-ImeEventGuard::ImeEventGuard(RenderWidget* widget)
-    : widget_(widget), show_virtual_keyboard_(false) {
+ImeEventGuard::ImeEventGuard(base::WeakPtr<RenderWidget> widget)
+    : widget_(std::move(widget)) {
   widget_->OnImeEventGuardStart(this);
 }
 
 ImeEventGuard::~ImeEventGuard() {
-  widget_->OnImeEventGuardFinish(this);
+  if (widget_)
+    widget_->OnImeEventGuardFinish(this);
 }
 
 } //  namespace content
diff --git a/content/renderer/ime_event_guard.h b/content/renderer/ime_event_guard.h
index a92d453..07056f50 100644
--- a/content/renderer/ime_event_guard.h
+++ b/content/renderer/ime_event_guard.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_RENDERER_IME_EVENT_GUARD_H_
 #define CONTENT_RENDERER_IME_EVENT_GUARD_H_
 
+#include "base/memory/weak_ptr.h"
+
 namespace content {
 class RenderWidget;
 
@@ -12,17 +14,19 @@
 // construction and OnImeGuardFinish on destruction.
 class ImeEventGuard {
  public:
-  explicit ImeEventGuard(RenderWidget* widget);
+  // The ImeEventGuard is intended to be allocated on the stack. A WeakPtr is
+  // used because the associated RenderWidget may be destroyed while this
+  // variable is on the stack. (i.e. inside a nested event loop).
+  explicit ImeEventGuard(base::WeakPtr<RenderWidget> widget);
   ~ImeEventGuard();
 
   bool show_virtual_keyboard() const { return show_virtual_keyboard_; }
   void set_show_virtual_keyboard(bool show) { show_virtual_keyboard_ = show; }
 
  private:
-  RenderWidget* widget_;
-  bool show_virtual_keyboard_;
+  base::WeakPtr<RenderWidget> widget_;
+  bool show_virtual_keyboard_ = false;
 };
 }
 
 #endif  // CONTENT_RENDERER_IME_EVENT_GUARD_H_
-
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc
index 2b3feaa..1d98b814 100644
--- a/content/renderer/input/frame_input_handler_impl.cc
+++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -80,7 +80,7 @@
   if (!render_frame_)
     return;
 
-  ImeEventGuard guard(render_frame_->GetLocalRootRenderWidget());
+  ImeEventGuard guard(render_frame_->GetLocalRootRenderWidget()->AsWeakPtr());
 
   render_frame_->GetWebFrame()->SetCompositionFromExistingText(
       start, end, ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans));
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc
index 44ae6ab..6a481573 100644
--- a/content/renderer/input/render_widget_input_handler.cc
+++ b/content/renderer/input/render_widget_input_handler.cc
@@ -186,19 +186,66 @@
   return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id();
 }
 
+InputEventAckState GetAckResult(WebInputEventResult processed) {
+  return processed == WebInputEventResult::kNotHandled
+             ? INPUT_EVENT_ACK_STATE_NOT_CONSUMED
+             : INPUT_EVENT_ACK_STATE_CONSUMED;
+}
+
 }  // namespace
 
+// This class should be placed on the stack when handling an input event. It
+// stores information from callbacks from blink while handling an input event
+// and allows them to be returned in the InputEventAck result.
+class RenderWidgetInputHandler::HandlingState {
+ public:
+  HandlingState(base::WeakPtr<RenderWidgetInputHandler> input_handler_param,
+                blink::WebInputEvent::Type type)
+      : event_type(type), input_handler(std::move(input_handler_param)) {
+    previous_was_handling_input = input_handler->handling_input_event_;
+    previous_state = input_handler->handling_input_state_;
+    input_handler->handling_input_event_ = true;
+    input_handler->handling_input_state_ = this;
+  }
+
+  ~HandlingState() {
+    // Unwinding the HandlingState on the stack might result in an
+    // input_handler_ that got destroyed. i.e. via a nested event loop.
+    if (!input_handler)
+      return;
+    input_handler->handling_input_event_ = previous_was_handling_input;
+    DCHECK_EQ(input_handler->handling_input_state_, this);
+    input_handler->handling_input_state_ = previous_state;
+  }
+
+  // Used to intercept overscroll notifications while an event is being
+  // handled. If the event causes overscroll, the overscroll metadata can be
+  // bundled in the event ack, saving an IPC.  Note that we must continue
+  // supporting overscroll IPC notifications due to fling animation updates.
+  std::unique_ptr<ui::DidOverscrollParams> event_overscroll;
+
+  base::Optional<cc::TouchAction> touch_action;
+
+  // Used to hold a sequence of parameters corresponding to scroll gesture
+  // events that should be injected once the current input event is done
+  // being processed.
+  std::unique_ptr<
+      std::vector<RenderWidgetInputHandler::InjectScrollGestureParams>>
+      injected_scroll_params;
+
+  // Type of the input event we are currently handling.
+  blink::WebInputEvent::Type event_type;
+
+ private:
+  HandlingState* previous_state;
+  bool previous_was_handling_input;
+  base::WeakPtr<RenderWidgetInputHandler> input_handler;
+};
+
 RenderWidgetInputHandler::RenderWidgetInputHandler(
     RenderWidgetInputHandlerDelegate* delegate,
     RenderWidget* widget)
-    : delegate_(delegate),
-      widget_(widget),
-      handling_input_event_(false),
-      handling_event_overscroll_(nullptr),
-      handling_injected_scroll_params_(nullptr),
-      handling_event_type_(WebInputEvent::kUndefined),
-      suppress_next_char_events_(false),
-      last_injected_gesture_was_begin_(false) {
+    : delegate_(delegate), widget_(widget) {
   DCHECK(delegate);
   DCHECK(widget);
   delegate->SetInputHandler(this);
@@ -299,34 +346,15 @@
   DCHECK(widget_->GetWebWidget());
 
   const WebInputEvent& input_event = coalesced_event.Event();
-  base::AutoReset<bool> handling_input_event_resetter(&handling_input_event_,
-                                                      true);
-  base::AutoReset<WebInputEvent::Type> handling_event_type_resetter(
-      &handling_event_type_, input_event.GetType());
 
-  // Calls into |didOverscroll()| while handling this event will populate
-  // |event_overscroll|, which in turn will be bundled with the event ack.
-  std::unique_ptr<DidOverscrollParams> event_overscroll;
-  base::AutoReset<std::unique_ptr<DidOverscrollParams>*>
-      handling_event_overscroll_resetter(&handling_event_overscroll_,
-                                         &event_overscroll);
-
-  // Calls into |ProcessTouchAction()| while handling this event will
-  // populate |handling_touch_action_|, which in turn will be bundled with
-  // the event ack.
-  base::AutoReset<base::Optional<cc::TouchAction>>
-      handling_touch_action_resetter(&handling_touch_action_, base::nullopt);
-
-  // Calls into |InjectGestureScrollEvent()| while handling this event
-  // will populate injected_scroll_params.
-  std::unique_ptr<std::vector<InjectScrollGestureParams>>
-      injected_scroll_params;
-  base::AutoReset<std::unique_ptr<std::vector<InjectScrollGestureParams>>*>
-      injected_scroll_resetter(&handling_injected_scroll_params_,
-                               &injected_scroll_params);
+  // Keep a WeakPtr to this RenderWidgetInputHandler to detect if executing the
+  // input event destroyed the associated RenderWidget (and this handler).
+  base::WeakPtr<RenderWidgetInputHandler> weak_self =
+      weak_ptr_factory_.GetWeakPtr();
+  HandlingState handling_state(weak_self, input_event.GetType());
 
 #if defined(OS_ANDROID)
-  ImeEventGuard guard(widget_);
+  ImeEventGuard guard(widget_->AsWeakPtr());
 #endif
 
   base::TimeTicks start_time;
@@ -423,6 +451,18 @@
       else
         processed = widget_->GetWebWidget()->HandleInputEvent(coalesced_event);
     }
+
+    // The associated RenderWidget (and this RenderWidgetInputHandler) could
+    // have been destroyed. If it was return early before accessing any more of
+    // this class.
+    if (!weak_self) {
+      if (callback) {
+        std::move(callback).Run(GetAckResult(processed), swap_latency_info,
+                                std::move(handling_state.event_overscroll),
+                                handling_state.touch_action);
+      }
+      return;
+    }
   }
 
   LogAllPassiveEventListenersUma(input_event, processed, latency_info);
@@ -436,17 +476,15 @@
   if (processed == WebInputEventResult::kNotHandled && is_keyboard_shortcut)
     suppress_next_char_events_ = true;
 
-  InputEventAckState ack_result = processed == WebInputEventResult::kNotHandled
-                                      ? INPUT_EVENT_ACK_STATE_NOT_CONSUMED
-                                      : INPUT_EVENT_ACK_STATE_CONSUMED;
-
   // The handling of some input events on the main thread may require injecting
   // scroll gestures back into blink, e.g., a mousedown on a scrollbar. We
-  // do this here so that we can attribute lateny information from the mouse as
+  // do this here so that we can attribute latency information from the mouse as
   // a scroll interaction, instead of just classifying as mouse input.
-  if (injected_scroll_params && injected_scroll_params->size()) {
-    HandleInjectedScrollGestures(std::move(*injected_scroll_params),
-                                 input_event, latency_info);
+  if (handling_state.injected_scroll_params &&
+      handling_state.injected_scroll_params->size()) {
+    HandleInjectedScrollGestures(
+        std::move(*handling_state.injected_scroll_params), input_event,
+        latency_info);
   }
 
   // Send gesture scroll events and their dispositions to the compositor thread,
@@ -458,11 +496,13 @@
         static_cast<const WebGestureEvent&>(input_event);
     if (gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchpad) {
       gfx::Vector2dF latest_overscroll_delta =
-          event_overscroll ? event_overscroll->latest_overscroll_delta
-                           : gfx::Vector2dF();
+          handling_state.event_overscroll
+              ? handling_state.event_overscroll->latest_overscroll_delta
+              : gfx::Vector2dF();
       cc::OverscrollBehavior overscroll_behavior =
-          event_overscroll ? event_overscroll->overscroll_behavior
-                           : cc::OverscrollBehavior();
+          handling_state.event_overscroll
+              ? handling_state.event_overscroll->overscroll_behavior
+              : cc::OverscrollBehavior();
       delegate_->ObserveGestureEventAndResult(
           gesture_event, latest_overscroll_delta, overscroll_behavior,
           processed != WebInputEventResult::kNotHandled);
@@ -470,11 +510,12 @@
   }
 
   if (callback) {
-    std::move(callback).Run(ack_result, swap_latency_info,
-                            std::move(event_overscroll),
-                            handling_touch_action_);
+    std::move(callback).Run(GetAckResult(processed), swap_latency_info,
+                            std::move(handling_state.event_overscroll),
+                            handling_state.touch_action);
   } else {
-    DCHECK(!event_overscroll) << "Unexpected overscroll for un-acked event";
+    DCHECK(!handling_state.event_overscroll)
+        << "Unexpected overscroll for un-acked event";
   }
 
   // Show the virtual keyboard if enabled and a user gesture triggers a focus
@@ -502,9 +543,8 @@
 
   // Ensure all injected scrolls were handled or queue up - any remaining
   // injected scrolls at this point would not be processed.
-  DCHECK(!handling_injected_scroll_params_ ||
-         !*handling_injected_scroll_params_ ||
-         (*handling_injected_scroll_params_)->empty());
+  DCHECK(!handling_state.injected_scroll_params ||
+         (handling_state.injected_scroll_params)->empty());
 }
 
 void RenderWidgetInputHandler::DidOverscrollFromBlink(
@@ -522,8 +562,8 @@
 
   // If we're currently handling an event, stash the overscroll data such that
   // it can be bundled in the event ack.
-  if (handling_event_overscroll_) {
-    *handling_event_overscroll_ = std::move(params);
+  if (handling_input_state_) {
+    handling_input_state_->event_overscroll = std::move(params);
     return;
   }
 
@@ -548,18 +588,18 @@
   // be dispatched until the next time the queue gets to run. The side effect
   // of that would be an extra frame of latency if we're injecting a scroll
   // during the handling of a rAF aligned input event, such as mouse move.
-  if (handling_injected_scroll_params_) {
+  if (handling_input_state_) {
     // Multiple gestures may be injected during the dispatch of a single
     // input event (e.g. Begin/Update). Create a vector and append to the
     // end of it - the gestures will subsequently be injected in order.
-    if (!*handling_injected_scroll_params_) {
-      *handling_injected_scroll_params_ =
+    if (!handling_input_state_->injected_scroll_params) {
+      handling_input_state_->injected_scroll_params =
           std::make_unique<std::vector<InjectScrollGestureParams>>();
     }
 
     InjectScrollGestureParams params{device, delta, granularity,
                                      scrollable_area_element_id, injected_type};
-    (*handling_injected_scroll_params_)->push_back(params);
+    handling_input_state_->injected_scroll_params->push_back(params);
   } else {
     base::TimeTicks now = base::TimeTicks::Now();
     std::unique_ptr<WebGestureEvent> gesture_event =
@@ -671,12 +711,14 @@
 
 bool RenderWidgetInputHandler::ProcessTouchAction(
     cc::TouchAction touch_action) {
+  if (!handling_input_state_)
+    return false;
   // Ignore setTouchAction calls that result from synthetic touch events (eg.
   // when blink is emulating touch with mouse).
-  if (handling_event_type_ != WebInputEvent::kTouchStart)
+  if (handling_input_state_->event_type != WebInputEvent::kTouchStart)
     return false;
 
-  handling_touch_action_ = touch_action;
+  handling_input_state_->touch_action = touch_action;
   return true;
 }
 
diff --git a/content/renderer/input/render_widget_input_handler.h b/content/renderer/input/render_widget_input_handler.h
index 0f881e61..4ad51f2 100644
--- a/content/renderer/input/render_widget_input_handler.h
+++ b/content/renderer/input/render_widget_input_handler.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "content/common/cursors/webcursor.h"
 #include "content/common/input/input_event_ack.h"
@@ -83,6 +84,7 @@
   bool DidChangeCursor(const WebCursor& cursor);
 
  private:
+  class HandlingState;
   struct InjectScrollGestureParams {
     blink::WebGestureDevice device;
     gfx::Vector2dF scroll_delta;
@@ -104,36 +106,25 @@
   RenderWidget* const widget_;
 
   // Are we currently handling an input event?
-  bool handling_input_event_;
+  bool handling_input_event_ = false;
+
+  // Current state from HandleInputEvent. This variable is stack allocated
+  // and is not owned.
+  HandlingState* handling_input_state_ = nullptr;
 
   // We store the current cursor object so we can avoid spamming SetCursor
   // messages.
   base::Optional<WebCursor> current_cursor_;
 
-  // Used to intercept overscroll notifications while an event is being
-  // handled. If the event causes overscroll, the overscroll metadata can be
-  // bundled in the event ack, saving an IPC.  Note that we must continue
-  // supporting overscroll IPC notifications due to fling animation updates.
-  std::unique_ptr<ui::DidOverscrollParams>* handling_event_overscroll_;
-
-  base::Optional<cc::TouchAction> handling_touch_action_;
-
-  // Used to hold a sequence of parameters corresponding to scroll gesture
-  // events that should be injected once the current input event is done
-  // being processed.
-  std::unique_ptr<std::vector<InjectScrollGestureParams>>*
-      handling_injected_scroll_params_;
-
-  // Type of the input event we are currently handling.
-  blink::WebInputEvent::Type handling_event_type_;
-
   // Indicates if the next sequence of Char events should be suppressed or not.
-  bool suppress_next_char_events_;
+  bool suppress_next_char_events_ = false;
 
   // Whether the last injected scroll gesture was a GestureScrollBegin. Used to
   // determine which GestureScrollUpdate is the first in a gesture sequence for
   // latency classification.
-  bool last_injected_gesture_was_begin_;
+  bool last_injected_gesture_was_begin_ = false;
+
+  base::WeakPtrFactory<RenderWidgetInputHandler> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetInputHandler);
 };
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index d05abec..1e50073 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -2278,7 +2278,7 @@
     return;
   }
 #endif
-  ImeEventGuard guard(this);
+  ImeEventGuard guard(weak_ptr_factory_.GetWeakPtr());
   blink::WebInputMethodController* controller = GetInputMethodController();
   if (!controller ||
       !controller->SetComposition(
@@ -2313,7 +2313,7 @@
     return;
   }
 #endif
-  ImeEventGuard guard(this);
+  ImeEventGuard guard(weak_ptr_factory_.GetWeakPtr());
   input_handler_->set_handling_input_event(true);
   if (auto* controller = GetInputMethodController()) {
     controller->CommitText(
@@ -2338,7 +2338,7 @@
   }
 #endif
 
-  ImeEventGuard guard(this);
+  ImeEventGuard guard(weak_ptr_factory_.GetWeakPtr());
   input_handler_->set_handling_input_event(true);
   if (auto* controller = GetInputMethodController()) {
     controller->FinishComposingText(
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.cc b/content/shell/browser/web_test/web_test_content_browser_client.cc
index 700996b..3f2d303 100644
--- a/content/shell/browser/web_test/web_test_content_browser_client.cc
+++ b/content/shell/browser/web_test/web_test_content_browser_client.cc
@@ -34,6 +34,7 @@
 #include "content/shell/browser/web_test/web_test_browser_context.h"
 #include "content/shell/browser/web_test/web_test_browser_main_parts.h"
 #include "content/shell/browser/web_test/web_test_message_filter.h"
+#include "content/shell/browser/web_test/web_test_permission_manager.h"
 #include "content/shell/browser/web_test/web_test_tts_controller_delegate.h"
 #include "content/shell/browser/web_test/web_test_tts_platform.h"
 #include "content/shell/common/web_test/web_test_switches.h"
@@ -178,6 +179,12 @@
           &WebTestContentBrowserClient::BindClientHintsControllerDelegate,
           base::Unretained(this)),
       ui_task_runner);
+
+  registry->AddInterface(
+      base::BindRepeating(
+          &WebTestContentBrowserClient::BindPermissionAutomation,
+          base::Unretained(this)),
+      ui_task_runner);
 }
 
 void WebTestContentBrowserClient::BindClipboardHostForRequest(
@@ -202,6 +209,12 @@
   delegate->Bind(std::move(receiver));
 }
 
+void WebTestContentBrowserClient::BindPermissionAutomation(
+    mojo::PendingReceiver<blink::test::mojom::PermissionAutomation> receiver) {
+  GetWebTestBrowserContext()->GetWebTestPermissionManager()->Bind(
+      std::move(receiver));
+}
+
 void WebTestContentBrowserClient::OverrideWebkitPrefs(
     RenderViewHost* render_view_host,
     WebPreferences* prefs) {
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.h b/content/shell/browser/web_test/web_test_content_browser_client.h
index c5dd687..0c9e573 100644
--- a/content/shell/browser/web_test/web_test_content_browser_client.h
+++ b/content/shell/browser/web_test/web_test_content_browser_client.h
@@ -14,6 +14,7 @@
 #include "services/service_manager/public/cpp/binder_map.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
+#include "third_party/blink/public/mojom/permissions/permission_automation.mojom-forward.h"
 
 namespace content {
 
@@ -102,6 +103,9 @@
   void BindClientHintsControllerDelegate(
       mojo::PendingReceiver<client_hints::mojom::ClientHints> receiver);
 
+  void BindPermissionAutomation(
+      mojo::PendingReceiver<blink::test::mojom::PermissionAutomation> receiver);
+
   std::unique_ptr<MockPlatformNotificationService>
       mock_platform_notification_service_;
   bool block_popups_ = false;
diff --git a/content/shell/browser/web_test/web_test_permission_manager.cc b/content/shell/browser/web_test/web_test_permission_manager.cc
index 1a00c6a..67f34de 100644
--- a/content/shell/browser/web_test/web_test_permission_manager.cc
+++ b/content/shell/browser/web_test/web_test_permission_manager.cc
@@ -207,6 +207,22 @@
   OnPermissionChanged(description, status);
 }
 
+void WebTestPermissionManager::SetPermission(
+    blink::mojom::PermissionDescriptorPtr descriptor,
+    blink::mojom::PermissionStatus status,
+    const GURL& url,
+    const GURL& embedding_url,
+    blink::test::mojom::PermissionAutomation::SetPermissionCallback callback) {
+  auto type = PermissionDescriptorToPermissionType(descriptor);
+  if (!type) {
+    std::move(callback).Run(false);
+    return;
+  }
+
+  SetPermission(*type, status, url, embedding_url);
+  std::move(callback).Run(true);
+}
+
 void WebTestPermissionManager::ResetPermissions() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -214,6 +230,11 @@
   permissions_.clear();
 }
 
+void WebTestPermissionManager::Bind(
+    mojo::PendingReceiver<blink::test::mojom::PermissionAutomation> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
 void WebTestPermissionManager::OnPermissionChanged(
     const PermissionDescription& permission,
     blink::mojom::PermissionStatus status) {
diff --git a/content/shell/browser/web_test/web_test_permission_manager.h b/content/shell/browser/web_test/web_test_permission_manager.h
index dfff29f9..1d15dbb 100644
--- a/content/shell/browser/web_test/web_test_permission_manager.h
+++ b/content/shell/browser/web_test/web_test_permission_manager.h
@@ -12,11 +12,16 @@
 #include "base/macros.h"
 #include "base/synchronization/lock.h"
 #include "content/public/browser/permission_controller_delegate.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
+#include "third_party/blink/public/mojom/permissions/permission_automation.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
 
-class WebTestPermissionManager : public PermissionControllerDelegate {
+class WebTestPermissionManager
+    : public PermissionControllerDelegate,
+      public blink::test::mojom::PermissionAutomation {
  public:
   WebTestPermissionManager();
   ~WebTestPermissionManager() override;
@@ -61,6 +66,17 @@
                      const GURL& embedding_url);
   void ResetPermissions();
 
+  // blink::test::mojom::PermissionAutomation
+  void SetPermission(
+      blink::mojom::PermissionDescriptorPtr descriptor,
+      blink::mojom::PermissionStatus status,
+      const GURL& url,
+      const GURL& embedding_url,
+      blink::test::mojom::PermissionAutomation::SetPermissionCallback) override;
+
+  void Bind(
+      mojo::PendingReceiver<blink::test::mojom::PermissionAutomation> receiver);
+
  private:
   // Representation of a permission for the WebTestPermissionManager.
   struct PermissionDescription {
@@ -101,6 +117,8 @@
   // List of subscribers currently listening to permission changes.
   SubscriptionsMap subscriptions_;
 
+  mojo::ReceiverSet<blink::test::mojom::PermissionAutomation> receivers_;
+
   DISALLOW_COPY_AND_ASSIGN(WebTestPermissionManager);
 };
 
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc
index 7d64ac10..215f3e8e6 100644
--- a/content/shell/renderer/web_test/blink_test_runner.cc
+++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -61,6 +61,7 @@
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
 #include "third_party/blink/public/mojom/app_banner/app_banner.mojom.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -618,20 +619,9 @@
                                     const std::string& value,
                                     const GURL& origin,
                                     const GURL& embedding_origin) {
-  blink::mojom::PermissionStatus status;
-  if (value == "granted") {
-    status = blink::mojom::PermissionStatus::GRANTED;
-  } else if (value == "prompt") {
-    status = blink::mojom::PermissionStatus::ASK;
-  } else if (value == "denied") {
-    status = blink::mojom::PermissionStatus::DENIED;
-  } else {
-    NOTREACHED();
-    status = blink::mojom::PermissionStatus::DENIED;
-  }
-
-  Send(new WebTestHostMsg_SetPermission(routing_id(), name, status, origin,
-                                        embedding_origin));
+  Send(new WebTestHostMsg_SetPermission(routing_id(), name,
+                                        blink::ToPermissionStatus(value),
+                                        origin, embedding_origin));
 }
 
 void BlinkTestRunner::ResetPermissions() {
diff --git a/content/test/data/cross-origin-opener-policy_csp_sandboxed.html b/content/test/data/cross-origin-opener-policy_csp_sandboxed.html
new file mode 100644
index 0000000..8c797df
--- /dev/null
+++ b/content/test/data/cross-origin-opener-policy_csp_sandboxed.html
@@ -0,0 +1 @@
+This is a sandboxed document (through CSP).
\ No newline at end of file
diff --git a/content/test/data/cross-origin-opener-policy_csp_sandboxed.html.mock-http-headers b/content/test/data/cross-origin-opener-policy_csp_sandboxed.html.mock-http-headers
new file mode 100644
index 0000000..4f8228a
--- /dev/null
+++ b/content/test/data/cross-origin-opener-policy_csp_sandboxed.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Content-Security-Policy: sandbox allow-scripts
diff --git a/content/test/data/cross-origin-opener-policy_same-origin.html b/content/test/data/cross-origin-opener-policy_same-origin.html
new file mode 100644
index 0000000..df3aa9d
--- /dev/null
+++ b/content/test/data/cross-origin-opener-policy_same-origin.html
@@ -0,0 +1 @@
+Document with "Cross-Origin-Opener-Policy: same-origin"
\ No newline at end of file
diff --git a/content/test/data/cross-origin-opener-policy_same-origin.html.mock-http-headers b/content/test/data/cross-origin-opener-policy_same-origin.html.mock-http-headers
new file mode 100644
index 0000000..40a218e
--- /dev/null
+++ b/content/test/data/cross-origin-opener-policy_same-origin.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Cross-Origin-Opener-Policy: same-origin
diff --git a/content/test/data/cross-origin-opener-policy_sandbox_popup.html b/content/test/data/cross-origin-opener-policy_sandbox_popup.html
new file mode 100644
index 0000000..1ca1c4a39
--- /dev/null
+++ b/content/test/data/cross-origin-opener-policy_sandbox_popup.html
@@ -0,0 +1 @@
+<iframe id="frame" sandbox="allow-scripts allow-popups" src='empty.html'></iframe>
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 41fbe9e..67374828 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -191,6 +191,7 @@
 crbug.com/1033121 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Rot_180 [ Skip ]
 crbug.com/1033121 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Rot_270 [ Skip ]
 crbug.com/1033121 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4_FourColors_Rot_90 [ Skip ]
+crbug.com/1041856 [ android skia-renderer use-gl no-use-vulkan ] Pixel_Video_MP4 [ Skip ]
 
 # Produces blank images on Intel HD 630 w/ Mesa 19.0.2
 crbug.com/976861 [ linux intel-0x5912 ] Pixel_OffscreenCanvasTransferToImageBitmap [ Skip ]
diff --git a/content/utility/BUILD.gn b/content/utility/BUILD.gn
index 962efd7..ce21651a 100644
--- a/content/utility/BUILD.gn
+++ b/content/utility/BUILD.gn
@@ -83,8 +83,6 @@
 group("for_content_tests") {
   visibility = [ "//content/test/*" ]
   if (!is_component_build) {
-    public_deps = [
-      ":utility",
-    ]
+    public_deps = [ ":utility" ]
   }
 }
diff --git a/extensions/browser/OWNERS b/extensions/browser/OWNERS
index b755bba7..881388a 100644
--- a/extensions/browser/OWNERS
+++ b/extensions/browser/OWNERS
@@ -12,5 +12,5 @@
 per-file device_local_account_util*=isandrk@chromium.org
 
 # For security review.
-per-file extensions_browser_interface_binders.cc=set noparent
-per-file extensions_browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
+per-file extensions_browser_interface_binders.*=set noparent
+per-file extensions_browser_interface_binders.*=file://ipc/SECURITY_OWNERS
diff --git a/extensions/browser/api/networking_config/BUILD.gn b/extensions/browser/api/networking_config/BUILD.gn
index 172052ac..190cadc 100644
--- a/extensions/browser/api/networking_config/BUILD.gn
+++ b/extensions/browser/api/networking_config/BUILD.gn
@@ -19,11 +19,7 @@
     "networking_config_service_factory.h",
   ]
 
-  deps = [
-    "//extensions/common/api",
-  ]
+  deps = [ "//extensions/common/api" ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/printer_provider/BUILD.gn b/extensions/browser/api/printer_provider/BUILD.gn
index d9d81bc3..d8c7e5c2 100644
--- a/extensions/browser/api/printer_provider/BUILD.gn
+++ b/extensions/browser/api/printer_provider/BUILD.gn
@@ -23,7 +23,5 @@
     "//services/device/public/mojom:usb",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/system_display/BUILD.gn b/extensions/browser/api/system_display/BUILD.gn
index a5aa07a..4dbf01f 100644
--- a/extensions/browser/api/system_display/BUILD.gn
+++ b/extensions/browser/api/system_display/BUILD.gn
@@ -20,7 +20,5 @@
     "//extensions/common/api",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/fuchsia/engine/OWNERS b/fuchsia/engine/OWNERS
index ed938cb..a76b25273 100644
--- a/fuchsia/engine/OWNERS
+++ b/fuchsia/engine/OWNERS
@@ -4,5 +4,5 @@
 per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
 
 # For security review.
-per-file web_engine_browser_interface_binders.cc=set noparent
-per-file web_engine_browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
+per-file web_engine_browser_interface_binders.*=set noparent
+per-file web_engine_browser_interface_binders.*=file://ipc/SECURITY_OWNERS
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn
index 64500bfc..ab55ed3 100644
--- a/gpu/vulkan/BUILD.gn
+++ b/gpu/vulkan/BUILD.gn
@@ -67,9 +67,7 @@
       "//base",
       "//ui/gfx",
     ]
-    public_deps = [
-      "//gpu/config:vulkan_info",
-    ]
+    public_deps = [ "//gpu/config:vulkan_info" ]
     data_deps = []
 
     if (is_posix) {
@@ -98,9 +96,7 @@
 
   jumbo_static_library("test_support") {
     testonly = true
-    sources = [
-      "tests/native_window.h",
-    ]
+    sources = [ "tests/native_window.h" ]
 
     deps = [
       "//ui/gfx",
diff --git a/gpu/vulkan/demo/BUILD.gn b/gpu/vulkan/demo/BUILD.gn
index 08d81481..5224c131 100644
--- a/gpu/vulkan/demo/BUILD.gn
+++ b/gpu/vulkan/demo/BUILD.gn
@@ -11,9 +11,7 @@
 
 group("demo") {
   if (use_x11) {
-    deps = [
-      ":vulkan_demo",
-    ]
+    deps = [ ":vulkan_demo" ]
   }
 }
 
diff --git a/gpu/vulkan/win32/BUILD.gn b/gpu/vulkan/win32/BUILD.gn
index d1834ff8..680717fa 100644
--- a/gpu/vulkan/win32/BUILD.gn
+++ b/gpu/vulkan/win32/BUILD.gn
@@ -24,9 +24,7 @@
 
   public_configs = [ ":vulkan_win32" ]
 
-  deps = [
-    "//ui/gfx",
-  ]
+  deps = [ "//ui/gfx" ]
 
   public_deps = [
     "//base",
diff --git a/gpu/vulkan/x/BUILD.gn b/gpu/vulkan/x/BUILD.gn
index 2ea73efd..48a5a51 100644
--- a/gpu/vulkan/x/BUILD.gn
+++ b/gpu/vulkan/x/BUILD.gn
@@ -41,8 +41,6 @@
   if (enable_swiftshader_vulkan) {
     # Vulkan Swiftshader can only be built on Linux.
     # TODO(samans): Support more platforms. https://crbug.com/963988
-    data_deps = [
-      "//third_party/swiftshader/src/Vulkan:swiftshader_libvulkan",
-    ]
+    data_deps = [ "//third_party/swiftshader/src/Vulkan:swiftshader_libvulkan" ]
   }
 }
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 4b58b50..0f58200 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -23,9 +23,7 @@
 }
 
 group("headless_lib") {
-  deps = [
-    ":headless_non_renderer",
-  ]
+  deps = [ ":headless_non_renderer" ]
 }
 
 repack("pak") {
@@ -78,9 +76,7 @@
   # TODO(altimin): Consider zipping file here, it can reduce size up to 80%.
   script = "lib/embed_data.py"
 
-  inputs = [
-    "$root_out_dir/headless_lib.pak",
-  ]
+  inputs = [ "$root_out_dir/headless_lib.pak" ]
 
   outputs = [
     "$root_gen_dir/headless/embedded_resource_pak.cc",
@@ -102,9 +98,7 @@
     "kHeadlessResourcePak",
   ]
 
-  deps = [
-    ":pak",
-  ]
+  deps = [ ":pak" ]
 }
 
 grit("resources") {
@@ -169,9 +163,7 @@
 
 action("gen_devtools_client_api") {
   script = "lib/browser/devtools_api/client_api_generator.py"
-  deps = [
-    "//third_party/blink/public/devtools_protocol:protocol_version",
-  ]
+  deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
   inputs = [
     "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json",
   ]
@@ -212,9 +204,7 @@
 
 inspector_protocol_generate("protocol_sources") {
   visibility = [ "//headless:headless_shared_sources" ]
-  deps = [
-    "//third_party/blink/public/devtools_protocol:protocol_version",
-  ]
+  deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
   _blink_protocol_path = rebase_path(
           "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json",
           root_build_dir)
@@ -309,9 +299,7 @@
 
 # Code that is needed in a renderer process.
 jumbo_component("headless") {
-  deps = [
-    ":headless_shared_sources",
-  ]
+  deps = [ ":headless_shared_sources" ]
 }
 
 # Code that is not needed in a renderer process.
@@ -556,9 +544,7 @@
   # For component builds all dependencies are already included in the headless
   # component.
   group("headless_renderer") {
-    deps = [
-      ":headless_non_renderer",
-    ]
+    deps = [ ":headless_non_renderer" ]
   }
 }
 
@@ -620,17 +606,11 @@
 
 if (is_mac) {
   copy("mac_helpers") {
-    sources = [
-      "$root_out_dir/chrome_crashpad_handler",
-    ]
+    sources = [ "$root_out_dir/chrome_crashpad_handler" ]
 
-    deps = [
-      "//components/crash/content/app:chrome_crashpad_handler",
-    ]
+    deps = [ "//components/crash/content/app:chrome_crashpad_handler" ]
 
-    outputs = [
-      "$root_out_dir/Helpers/{{source_file_part}}",
-    ]
+    outputs = [ "$root_out_dir/Helpers/{{source_file_part}}" ]
   }
 }
 
@@ -662,9 +642,7 @@
   ]
 
   if (is_mac) {
-    data_deps = [
-      ":mac_helpers",
-    ]
+    data_deps = [ ":mac_helpers" ]
   }
 
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
@@ -813,9 +791,7 @@
     "//content/public/common",
   ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 
   if (!is_component_build) {
     public_deps += [ ":headless_non_renderer" ]
@@ -859,18 +835,12 @@
 }
 
 executable("headless_shell") {
-  sources = [
-    "app/headless_shell_main.cc",
-  ]
+  sources = [ "app/headless_shell_main.cc" ]
 
-  deps = [
-    ":headless_shell_lib",
-  ]
+  deps = [ ":headless_shell_lib" ]
 
   if (!headless_use_embedded_resources) {
-    data = [
-      "$root_out_dir/headless_lib.pak",
-    ]
+    data = [ "$root_out_dir/headless_lib.pak" ]
   }
 
   if (is_win) {
@@ -892,9 +862,7 @@
 }
 
 executable("headless_example") {
-  sources = [
-    "app/headless_example.cc",
-  ]
+  sources = [ "app/headless_example.cc" ]
 
   deps = [
     ":headless_shell_lib",
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn
index 561297b5..56c752be 100644
--- a/ios/chrome/app/BUILD.gn
+++ b/ios/chrome/app/BUILD.gn
@@ -30,7 +30,6 @@
   deps = [
     "//base",
     "//ios/chrome/browser",
-    "//ios/chrome/browser/payments:constants",
     "//net",
     "//url",
   ]
@@ -42,7 +41,6 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "app_startup_parameters_unittest.mm",
     "chrome_overlay_window_testing.h",
     "deferred_initialization_runner_unittest.mm",
     "firebase_utils_unittest.mm",
@@ -77,21 +75,15 @@
 
 source_set("tests_hook") {
   # This target is intentionally not test-only, as the main app depends on it.
-  sources = [
-    "tests_hook.h",
-  ]
+  sources = [ "tests_hook.h" ]
 }
 
 source_set("tests_fake_hook") {
   configs += [ "//build/config/compiler:enable_arc" ]
 
   # This target is intentionally not test-only, as the main app depends on it.
-  sources = [
-    "tests_fake_hook.mm",
-  ]
-  deps = [
-    ":tests_hook",
-  ]
+  sources = [ "tests_fake_hook.mm" ]
+  deps = [ ":tests_hook" ]
 }
 
 tweak_info_plist("info_plist") {
@@ -169,7 +161,6 @@
     "//components/metrics",
     "//components/ntp_snippets",
     "//components/password_manager/core/common",
-    "//components/payments/core",
     "//components/prefs",
     "//components/prefs/ios",
     "//components/proxy_config",
@@ -212,8 +203,6 @@
     "//ios/chrome/browser/ntp_snippets",
     "//ios/chrome/browser/omaha",
     "//ios/chrome/browser/passwords",
-    "//ios/chrome/browser/payments",
-    "//ios/chrome/browser/payments:constants",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/search_engines",
     "//ios/chrome/browser/search_engines:extension_search_engine_data_updater",
@@ -233,6 +222,7 @@
     "//ios/chrome/browser/ui/history",
     "//ios/chrome/browser/ui/main",
     "//ios/chrome/browser/ui/main:scene",
+    "//ios/chrome/browser/ui/main:scene_guts",
     "//ios/chrome/browser/ui/promos",
     "//ios/chrome/browser/ui/settings",
     "//ios/chrome/browser/ui/settings:settings_root",
@@ -289,20 +279,14 @@
 
 source_set("mode") {
   configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "application_mode.h",
-  ]
+  sources = [ "application_mode.h" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("main") {
   configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "chrome_exe_main.mm",
-  ]
+  sources = [ "chrome_exe_main.mm" ]
 
   deps = [
     ":app_internal",
@@ -408,43 +392,25 @@
 if (current_toolchain == default_toolchain) {
   if (ios_enable_content_widget_extension) {
     bundle_data("content_widget_extension_bundle") {
-      public_deps = [
-        "//ios/chrome/content_widget_extension",
-      ]
-      sources = [
-        "$root_out_dir/content_widget_extension.appex",
-      ]
-      outputs = [
-        "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}",
-      ]
+      public_deps = [ "//ios/chrome/content_widget_extension" ]
+      sources = [ "$root_out_dir/content_widget_extension.appex" ]
+      outputs = [ "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}" ]
     }
   }
 
   if (ios_enable_search_widget_extension) {
     bundle_data("search_widget_extension_bundle") {
-      public_deps = [
-        "//ios/chrome/search_widget_extension",
-      ]
-      sources = [
-        "$root_out_dir/search_widget_extension.appex",
-      ]
-      outputs = [
-        "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}",
-      ]
+      public_deps = [ "//ios/chrome/search_widget_extension" ]
+      sources = [ "$root_out_dir/search_widget_extension.appex" ]
+      outputs = [ "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}" ]
     }
   }
 
   if (ios_enable_share_extension) {
     bundle_data("share_extension_bundle") {
-      public_deps = [
-        "//ios/chrome/share_extension",
-      ]
-      sources = [
-        "$root_out_dir/share_extension.appex",
-      ]
-      outputs = [
-        "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}",
-      ]
+      public_deps = [ "//ios/chrome/share_extension" ]
+      sources = [ "$root_out_dir/share_extension.appex" ]
+      outputs = [ "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}" ]
     }
   }
 }
diff --git a/ios/chrome/app/app_startup_parameters.mm b/ios/chrome/app/app_startup_parameters.mm
index ec733641..c7f81c5 100644
--- a/ios/chrome/app/app_startup_parameters.mm
+++ b/ios/chrome/app/app_startup_parameters.mm
@@ -6,7 +6,6 @@
 
 #include "base/stl_util.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#include "ios/chrome/browser/payments/payment_request_constants.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/base/url_util.h"
 #include "url/gurl.h"
@@ -23,6 +22,7 @@
 @synthesize externalURLParams = _externalURLParams;
 @synthesize postOpeningAction = _postOpeningAction;
 @synthesize launchInIncognito = _launchInIncognito;
+// TODO(crbug.com/1021752): Remove this stub.
 @synthesize completePaymentRequest = _completePaymentRequest;
 @synthesize textQuery = _textQuery;
 
@@ -44,30 +44,13 @@
   return self;
 }
 
+// TODO(crbug.com/1021752): Remove this stub since |universalLink| is unused.
 - (instancetype)initWithUniversalLink:(const GURL&)universalLink {
   // If a new tab with |_externalURL| needs to be opened after the App
   // was launched as the result of a Universal Link navigation, the only
   // supported possibility at this time is the New Tab Page.
   self = [self initWithExternalURL:GURL(kChromeUINewTabURL)
                        completeURL:GURL(kChromeUINewTabURL)];
-
-  if (self) {
-    std::map<std::string, std::string> parameters;
-    net::QueryIterator query_iterator(universalLink);
-    while (!query_iterator.IsAtEnd()) {
-      parameters.insert(std::make_pair(query_iterator.GetKey(),
-                                       query_iterator.GetUnescapedValue()));
-      query_iterator.Advance();
-    }
-
-    // Currently only Payment Request parameters are supported.
-    if (base::Contains(parameters, payments::kPaymentRequestIDExternal) &&
-        base::Contains(parameters, payments::kPaymentRequestDataExternal)) {
-      _externalURLParams = parameters;
-      _completePaymentRequest = YES;
-    }
-  }
-
   return self;
 }
 
diff --git a/ios/chrome/app/app_startup_parameters_unittest.mm b/ios/chrome/app/app_startup_parameters_unittest.mm
deleted file mode 100644
index dc4c110..0000000
--- a/ios/chrome/app/app_startup_parameters_unittest.mm
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/chrome/app/app_startup_parameters.h"
-
-#include "base/stl_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "url/gurl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-struct UniversalLinkDecodeTestCase {
-  GURL universal_link;
-  std::map<std::string, std::string> expected_external_url_params;
-  bool expected_complete_payment_request;
-};
-
-using AppStartupParametersTest = PlatformTest;
-
-TEST_F(AppStartupParametersTest, QueryParametersPaymentRequest) {
-  const UniversalLinkDecodeTestCase test_cases[] = {
-      {
-          GURL("https://goo.gl/ioschrome/"),
-          {},
-          false,
-      },
-      {
-          GURL("https://goo.gl/ioschrome?payment-request-id"),
-          {},
-          false,
-      },
-      {
-          GURL("https://goo.gl/ioschrome?payment-request-id=092831-af18l-324"
-               "&payment-request-data="),
-          {{"payment-request-id", "092831-af18l-324"},
-           {"payment-request-data", ""}},
-          true,
-      },
-      {
-          GURL("https://goo.gl/ioschrome?payment-request-id=092831-af18l-324"
-               "&payment-request-data=JNLSKFknrlwe80dkzrnLEWR"),
-          {{"payment-request-id", "092831-af18l-324"},
-           {"payment-request-data", "JNLSKFknrlwe80dkzrnLEWR"}},
-          true,
-      },
-      {
-          GURL("https://goo.gl/ioschrome?payment-request-id=092831-af18l-324"
-               "&payment-request-data=JNLSKFknrlwe80dkzrnLEWR"
-               "&unecessary-parameter=0"),
-          {{"payment-request-id", "092831-af18l-324"},
-           {"payment-request-data", "JNLSKFknrlwe80dkzrnLEWR"},
-           {"unecessary-parameter", "0"}},
-          true,
-      },
-  };
-
-  for (size_t i = 0; i < base::size(test_cases); ++i) {
-    const UniversalLinkDecodeTestCase& test_case = test_cases[i];
-    AppStartupParameters* params = [[AppStartupParameters alloc]
-        initWithUniversalLink:test_case.universal_link];
-    EXPECT_EQ(test_case.expected_external_url_params, params.externalURLParams);
-    EXPECT_EQ(test_case.expected_complete_payment_request,
-              params.completePaymentRequest);
-  }
-}
-
-}  // namespace
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn
index e03c893..c08f1f4e 100644
--- a/ios/chrome/app/application_delegate/BUILD.gn
+++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -107,7 +107,6 @@
     "//components/feature_engagement",
     "//components/handoff",
     "//components/metrics",
-    "//components/payments/core",
     "//components/prefs",
     "//components/search_engines",
     "//components/ukm/ios:features",
@@ -125,7 +124,6 @@
     "//ios/chrome/browser/metrics",
     "//ios/chrome/browser/metrics:metrics_internal",
     "//ios/chrome/browser/net",
-    "//ios/chrome/browser/payments",
     "//ios/chrome/browser/search_engines",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/tabs",
diff --git a/ios/chrome/app/intents/BUILD.gn b/ios/chrome/app/intents/BUILD.gn
index 8248745..b998185 100644
--- a/ios/chrome/app/intents/BUILD.gn
+++ b/ios/chrome/app/intents/BUILD.gn
@@ -9,18 +9,12 @@
     "SearchInChromeIntent.h",
     "SearchInChromeIntent.m",
   ]
-  deps = [
-    ":resources",
-  ]
+  deps = [ ":resources" ]
   libs = [ "Intents.framework" ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
 bundle_data("resources") {
-  sources = [
-    "Intents.intentdefinition",
-  ]
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_file_part}}",
-  ]
+  sources = [ "Intents.intentdefinition" ]
+  outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 }
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm
index 6b22ac1..ae39e43 100644
--- a/ios/chrome/app/main_application_delegate.mm
+++ b/ios/chrome/app/main_application_delegate.mm
@@ -86,6 +86,7 @@
       _sceneController =
           [[SceneController alloc] initWithSceneState:_sceneState];
 
+      // TODO(crbug.com/1040501): remove this.
       // This is temporary plumbing that's not supposed to be here.
       _sceneController.mainController = (id<MainControllerGuts>)_mainController;
       _mainController.sceneController = _sceneController;
diff --git a/ios/chrome/app/main_controller.h b/ios/chrome/app/main_controller.h
index 7628417..8062d27 100644
--- a/ios/chrome/app/main_controller.h
+++ b/ios/chrome/app/main_controller.h
@@ -17,7 +17,9 @@
 
 @class AppState;
 @class MetricsMediator;
+@protocol AppURLLoadingServiceDelegate;
 @protocol BrowsingDataCommands;
+@protocol SceneControllerGuts;
 @protocol TabSwitcherDelegate;
 
 // The main controller of the application, owned by the MainWindow nib. Also
@@ -45,7 +47,10 @@
 @property(nonatomic, weak) MetricsMediator* metricsMediator;
 
 // For temporary plumbing only.
-@property(nonatomic, weak) id<ApplicationCommands, TabSwitcherDelegate>
+@property(nonatomic, weak) id<ApplicationCommands,
+                              TabSwitcherDelegate,
+                              AppURLLoadingServiceDelegate,
+                              SceneControllerGuts>
     sceneController;
 
 @end
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 6c5c9e26..68617985 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -34,7 +34,6 @@
 #include "components/metrics/metrics_service.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/password_manager/core/common/passwords_directory_util_ios.h"
-#include "components/payments/core/features.h"
 #include "components/prefs/ios/pref_observer_bridge.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/search_engines/template_url_service.h"
@@ -75,7 +74,6 @@
 #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "ios/chrome/browser/crash_report/breakpad_helper.h"
 #include "ios/chrome/browser/crash_report/crash_loop_detection_util.h"
-#import "ios/chrome/browser/crash_report/crash_restore_helper.h"
 #include "ios/chrome/browser/download/download_directory_util.h"
 #import "ios/chrome/browser/external_files/external_file_remover_factory.h"
 #import "ios/chrome/browser/external_files/external_file_remover_impl.h"
@@ -91,11 +89,7 @@
 #include "ios/chrome/browser/metrics/first_user_action_recorder.h"
 #import "ios/chrome/browser/metrics/previous_session_info.h"
 #import "ios/chrome/browser/net/cookie_util.h"
-#include "ios/chrome/browser/ntp/features.h"
 #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h"
-#include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h"
-#include "ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h"
-#import "ios/chrome/browser/payments/payment_request_constants.h"
 #include "ios/chrome/browser/pref_names.h"
 #import "ios/chrome/browser/reading_list/reading_list_download_service.h"
 #import "ios/chrome/browser/reading_list/reading_list_download_service_factory.h"
@@ -126,6 +120,7 @@
 #import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h"
 #include "ios/chrome/browser/ui/history/history_coordinator.h"
 #import "ios/chrome/browser/ui/main/browser_view_wrangler.h"
+#import "ios/chrome/browser/ui/main/scene_controller_guts.h"
 #import "ios/chrome/browser/ui/promos/signin_promo_view_controller.h"
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.h"
@@ -239,11 +234,6 @@
       cus, GetApplicationContext()->GetApplicationLocale());
 }
 
-// Used to update the current BVC mode if a new tab is added while the tab
-// switcher view is being dimissed.  This is different than ApplicationMode in
-// that it can be set to |NONE| when not in use.
-enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
-
 // The delay, in seconds, for cleaning external files.
 const int kExternalFilesCleanupDelaySeconds = 60;
 
@@ -286,8 +276,7 @@
 
 }  // namespace
 
-@interface MainController () <AppURLLoadingServiceDelegate,
-                              BrowserStateStorageSwitching,
+@interface MainController () <BrowserStateStorageSwitching,
                               PrefObserverDelegate,
                               WebStateListObserving> {
   IBOutlet UIWindow* _window;
@@ -303,27 +292,13 @@
   // BrowserViewInformation protocol.
   BrowserViewWrangler* _browserViewWrangler;
 
-  // Parameters received at startup time when the app is launched from another
-  // app.
-  AppStartupParameters* _startupParameters;
-
   // TabSwitcher object -- the tab grid.
   id<TabSwitcher> _tabSwitcher;
 
-  // YES while animating the dismissal of tab switcher.
-  BOOL _dismissingTabSwitcher;
-
-  // If not NONE, the current BVC should be switched to this BVC on completion
-  // of tab switcher dismissal.
-  TabSwitcherDismissalMode _modeToDisplayOnTabSwitcherDismissal;
-
   // True if the current session began from a cold start. False if the app has
   // entered the background at least once since start up.
   BOOL _isColdStart;
 
-  // Keeps track of the restore state during startup.
-  CrashRestoreHelper* _restoreHelper;
-
   // An object to record metrics related to the user's first action.
   std::unique_ptr<FirstUserActionRecorder> _firstUserActionRecorder;
 
@@ -372,22 +347,6 @@
 // browser has started up to the FOREGROUND stage.
 @property(nonatomic, readonly) TabGridCoordinator* mainCoordinator;
 
-// A property to track whether the QR Scanner should be started upon tab
-// switcher dismissal. It can only be YES if the QR Scanner experiment is
-// enabled.
-@property(nonatomic, readwrite)
-    NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal;
-
-// Returns YES if the settings are presented, either from
-// self.settingsNavigationController or from SigninInteractionCoordinator.
-@property(nonatomic, assign, readonly, getter=isSettingsViewPresented)
-    BOOL settingsViewPresented;
-
-// Activates |mainBVC| and |otrBVC| and sets |currentBVC| as primary iff
-// |currentBVC| can be made active.
-- (void)activateBVCAndMakeCurrentBVCPrimary;
-// Sets |currentBVC| as the root view controller for the window.
-- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox;
 // Shows the tab switcher UI.
 - (void)showTabSwitcher;
 // Starts a voice search on the current BVC.
@@ -396,26 +355,6 @@
 - (void)lastIncognitoTabClosed;
 // Called when the last regular tab was closed.
 - (void)lastRegularTabClosed;
-// Opens a tab in the target BVC, and switches to it in a way that's appropriate
-// to the current UI, based on the |dismissModals| flag:
-// - If a modal dialog is showing and |dismissModals| is NO, the selected tab of
-// the main tab model will change in the background, but the view won't change.
-// - Otherwise, any modal view will be dismissed, the tab switcher will animate
-// out if it is showing, the target BVC will become active, and the new tab will
-// be shown.
-// If the current tab in |targetMode| is a NTP, it can be reused to open URL.
-// |completion| is executed after the tab is opened. After Tab is open the
-// virtual URL is set to the pending navigation item.
-- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)targetMode
-            withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
-                   completion:(ProceduralBlock)completion;
-// Checks the target BVC's current tab's URL. If this URL is chrome://newtab,
-// loads |urlLoadParams| in this tab. Otherwise, open |urlLoadParams| in a new
-// tab in the target BVC. |tabDisplayedCompletion| will be called on the new tab
-// (if not nil).
-- (void)openOrReuseTabInMode:(ApplicationMode)targetMode
-           withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
-         tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion;
 // Returns whether the restore infobar should be displayed.
 - (bool)mustShowRestoreInfobar;
 // Switch all global states for the given mode (normal or incognito).
@@ -507,6 +446,8 @@
 @synthesize isProcessingTabSwitcherCommand;
 @synthesize isProcessingVoiceSearchCommand;
 @synthesize signinInteractionCoordinator;
+@synthesize dismissingTabSwitcher = _dismissingTabSwitcher;
+@synthesize restoreHelper = _restoreHelper;
 
 // Defined by public protocols.
 // - BrowserLauncher
@@ -522,6 +463,8 @@
 @synthesize NTPActionAfterTabSwitcherDismissal =
     _NTPActionAfterTabSwitcherDismissal;
 @synthesize tabSwitcherIsActive;
+@synthesize modeToDisplayOnTabSwitcherDismissal =
+    _modeToDisplayOnTabSwitcherDismissal;
 
 #pragma mark - Application lifecycle
 
@@ -644,17 +587,17 @@
       _browserStateManager->GetLastUsedBrowserState();
 
   // The CrashRestoreHelper must clean up the old browser state information
-  // before the tabModels can be created.  |_restoreHelper| must be kept alive
-  // until the BVC receives the browser state and tab model.
+  // before the tabModels can be created.  |self.restoreHelper| must be kept
+  // alive until the BVC receives the browser state and tab model.
   BOOL postCrashLaunch = [self mustShowRestoreInfobar];
   if (postCrashLaunch) {
-    _restoreHelper =
+    self.restoreHelper =
         [[CrashRestoreHelper alloc] initWithBrowserState:chromeBrowserState];
-    [_restoreHelper moveAsideSessionInformation];
+    [self.restoreHelper moveAsideSessionInformation];
   }
 
   self.appURLLoadingService = new AppUrlLoadingService();
-  self.appURLLoadingService->SetDelegate(self);
+  self.appURLLoadingService->SetDelegate(self.sceneController);
 
   // Initialize and set the main browser state.
   [self initializeBrowserState:chromeBrowserState];
@@ -737,16 +680,16 @@
                         appState:self.appState];
   _launchOptions = nil;
 
-  if (!_startupParameters) {
+  if (!self.startupParameters) {
     // The startup parameters may create new tabs or navigations. If the restore
     // infobar is displayed now, it may be dismissed immediately and the user
     // will never be able to restore the session.
     TabModel* currentTabModel = [self currentTabModel];
-    [_restoreHelper
+    [self.restoreHelper
         showRestoreIfNeededUsingWebState:currentTabModel.webStateList
                                              ->GetActiveWebState()
                          sessionRestorer:currentTabModel];
-    _restoreHelper = nil;
+    self.restoreHelper = nil;
   }
 
   [self scheduleTasksRequiringBVCWithBrowserState];
@@ -772,9 +715,9 @@
 
   [self markEulaAsAccepted];
 
-  if (_startupParameters) {
+  if (self.startupParameters) {
     UrlLoadParams params =
-        UrlLoadParams::InNewTab(_startupParameters.externalURL);
+        UrlLoadParams::InNewTab(self.startupParameters.externalURL);
     [self dismissModalsAndOpenSelectedTabInMode:ApplicationModeForTabOpening::
                                                     NORMAL
                               withUrlLoadParams:params
@@ -1330,13 +1273,14 @@
   TabModel* tabModel;
   if (launchMode == ApplicationMode::INCOGNITO) {
     tabModel = otrTabModel;
-    [self setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
+    [self.sceneController
+        setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
   } else {
     tabModel = mainTabModel;
-    [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
+    [self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
   }
   if (self.tabSwitcherIsActive) {
-    DCHECK(!_dismissingTabSwitcher);
+    DCHECK(!self.dismissingTabSwitcher);
     [self beginDismissingTabSwitcherWithCurrentModel:self.mainTabModel
                                         focusOmnibox:NO];
     [self finishDismissingTabSwitcher];
@@ -1351,7 +1295,7 @@
   if (firstRun) {
     [self showFirstRunUI];
     // Do not ever show the 'restore' infobar during first run.
-    _restoreHelper = nil;
+    self.restoreHelper = nil;
   }
 }
 
@@ -1408,7 +1352,7 @@
   if (self.currentBVC == self.otrBVC)
     return;
   // Don't show promos if the app was launched from a URL.
-  if (_startupParameters)
+  if (self.startupParameters)
     return;
 
   // Show the sign-in promo if needed
@@ -1457,26 +1401,6 @@
 
 
 
-#pragma mark - AppURLLoadingServiceDelegate
-
-- (void)openURLInNewTabWithCommand:(OpenNewTabCommand*)command {
-  [self openURLInNewTab:command];
-}
-
-- (void)expectNewForegroundTabForMode:(ApplicationMode)targetMode {
-  id<BrowserInterface> interface =
-      targetMode == ApplicationMode::INCOGNITO
-          ? self.interfaceProvider.incognitoInterface
-          : self.interfaceProvider.mainInterface;
-  DCHECK(interface);
-  [interface.bvc expectNewForegroundTab];
-}
-
-- (void)openNewTabFromOriginPoint:(CGPoint)originPoint
-                     focusOmnibox:(BOOL)focusOmnibox {
-  [self.currentBVC openNewTabFromOriginPoint:originPoint
-                                focusOmnibox:focusOmnibox];
-}
 
 #pragma mark - Preferences Management
 
@@ -1515,34 +1439,7 @@
   return self.interfaceProvider.currentInterface.bvc;
 }
 
-// Note that the current tab of |browserCoordinator|'s BVC will normally be
-// reloaded by this method. If a new tab is about to be added, call
-// expectNewForegroundTab on the BVC first to avoid extra work and possible page
-// load side-effects for the tab being replaced.
-- (void)setCurrentInterfaceForMode:(ApplicationMode)mode {
-  DCHECK(self.interfaceProvider);
-  BOOL incognitio = mode == ApplicationMode::INCOGNITO;
-  id<BrowserInterface> currentInterface =
-      self.interfaceProvider.currentInterface;
-  id<BrowserInterface> newInterface =
-      incognitio ? self.interfaceProvider.incognitoInterface
-                 : self.interfaceProvider.mainInterface;
-  if (currentInterface && currentInterface == newInterface)
-    return;
 
-  // Update the snapshot before switching another application mode.  This
-  // ensures that the snapshot is correct when links are opened in a different
-  // application mode.
-  [self updateActiveWebStateSnapshot];
-
-  self.interfaceProvider.currentInterface = newInterface;
-
-  if (!_dismissingTabSwitcher)
-    [self displayCurrentBVCAndFocusOmnibox:NO];
-
-  // Tell the BVC that was made current that it can use the web.
-  [self activateBVCAndMakeCurrentBVCPrimary];
-}
 
 #pragma mark - Tab closure handlers
 
@@ -1575,7 +1472,7 @@
   if ([self.currentTabModel count] == 0U) {
     [self showTabSwitcher];
   } else {
-    [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
+    [self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
   }
 }
 
@@ -1680,14 +1577,14 @@
                                       focusOmnibox:(BOOL)focusOmnibox {
   DCHECK(tabModel == self.mainTabModel || tabModel == self.otrTabModel);
 
-  _dismissingTabSwitcher = YES;
+  self.dismissingTabSwitcher = YES;
   ApplicationMode mode = (tabModel == self.mainTabModel)
                              ? ApplicationMode::NORMAL
                              : ApplicationMode::INCOGNITO;
-  [self setCurrentInterfaceForMode:mode];
+  [self.sceneController setCurrentInterfaceForMode:mode];
 
   // The call to set currentBVC above does not actually display the BVC, because
-  // _dismissingTabSwitcher is YES.  So: Force the BVC transition to start.
+  // self.dismissingTabSwitcher is YES.  So: Force the BVC transition to start.
   [self displayCurrentBVCAndFocusOmnibox:focusOmnibox];
 }
 
@@ -1702,8 +1599,8 @@
   // user to the tab switcher.
   if (self.currentTabModel.count == 0U) {
     self.tabSwitcherIsActive = NO;
-    _dismissingTabSwitcher = NO;
-    _modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
+    self.dismissingTabSwitcher = NO;
+    self.modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
     self.NTPActionAfterTabSwitcherDismissal = NO_ACTION;
     [self showTabSwitcher];
     return;
@@ -1714,15 +1611,16 @@
   // animations begin, so it should be the current active VC at this point.
   DCHECK_EQ(self.mainCoordinator.activeViewController, self.currentBVC);
 
-  if (_modeToDisplayOnTabSwitcherDismissal ==
+  if (self.modeToDisplayOnTabSwitcherDismissal ==
       TabSwitcherDismissalMode::NORMAL) {
-    [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
-  } else if (_modeToDisplayOnTabSwitcherDismissal ==
+    [self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
+  } else if (self.modeToDisplayOnTabSwitcherDismissal ==
              TabSwitcherDismissalMode::INCOGNITO) {
-    [self setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
+    [self.sceneController
+        setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
   }
 
-  _modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
+  self.modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
 
   ProceduralBlock action = [self completionBlockForTriggeringAction:
                                      self.NTPActionAfterTabSwitcherDismissal];
@@ -1732,11 +1630,10 @@
   }
 
   self.tabSwitcherIsActive = NO;
-  _dismissingTabSwitcher = NO;
+  self.dismissingTabSwitcher = NO;
 }
 
-
-#pragma mark - Navigation Controllers
+#pragma mark - App Navigation
 
 - (void)presentSignedInAccountsViewControllerForBrowserState:
     (ios::ChromeBrowserState*)browserState {
@@ -1752,32 +1649,7 @@
 
 - (void)closeSettingsAnimated:(BOOL)animated
                    completion:(ProceduralBlock)completion {
-  if (self.settingsNavigationController) {
-    [self.settingsNavigationController cleanUpSettings];
-    UIViewController* presentingViewController =
-        [self.settingsNavigationController presentingViewController];
-    // If presentingViewController is nil it means the VC was already dismissed
-    // by some other action like swiping down.
-    DCHECK(presentingViewController);
-    [presentingViewController dismissViewControllerAnimated:animated
-                                                 completion:completion];
-    self.settingsNavigationController = nil;
-    return;
-  }
-  // |self.signinInteractionCoordinator| can also present settings, like
-  // the advanced sign-in settings navigation controller. If the settings has
-  // to be cloase, it is thus the responsibility of the main controller to
-  // dismiss the the advanced sign-in settings by dismssing the settings
-  // presented by |self.signinInteractionCoordinator|.
-  // To reproduce this case:
-  //  - open Bookmark view
-  //  - start sign-in
-  //  - tap on "Settings" to open the advanced sign-in settings
-  //  - tap on "Manage Your Google Account"
-  DCHECK(self.signinInteractionCoordinator.isSettingsViewPresented);
-  [self.signinInteractionCoordinator
-      abortAndDismissSettingsViewAnimated:animated
-                               completion:completion];
+  [self.sceneController closeSettingsAnimated:animated completion:completion];
 }
 
 #pragma mark - WebStateListObserving
@@ -1802,54 +1674,6 @@
 
 #pragma mark - Tab opening utility methods.
 
-- (void)openOrReuseTabInMode:(ApplicationMode)targetMode
-           withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
-         tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion {
-  BrowserViewController* targetBVC =
-      targetMode == ApplicationMode::NORMAL ? self.mainBVC : self.otrBVC;
-  web::WebState* currentWebState =
-      targetBVC.tabModel.webStateList->GetActiveWebState();
-
-  // Don't call loadWithParams for chrome://newtab when it's already loaded.
-  // Note that it's safe to use -GetVisibleURL here, as it doesn't matter if the
-  // NTP hasn't finished loading.
-  if (currentWebState && IsURLNtp(currentWebState->GetVisibleURL()) &&
-      IsURLNtp(urlLoadParams.web_params.url)) {
-    if (tabOpenedCompletion) {
-      tabOpenedCompletion();
-    }
-    return;
-  }
-
-  // With kBrowserContainerContainsNTP enabled paired with a restored NTP
-  // session, the NTP may appear committed when it is still loading.  For the
-  // time being, always load within a new tab when this feature is enabled.
-  // TODO(crbug.com/931284): Revert this change when fixed.
-  BOOL alwaysInsertNewTab =
-      base::FeatureList::IsEnabled(kBlockNewTabPagePendingLoad);
-  // If the current tab isn't an NTP, open a new tab.  Be sure to use
-  // -GetLastCommittedURL incase the NTP is still loading.
-  if (alwaysInsertNewTab ||
-      !(currentWebState && IsURLNtp(currentWebState->GetVisibleURL()))) {
-    [targetBVC appendTabAddedCompletion:tabOpenedCompletion];
-    UrlLoadParams newTabParams = urlLoadParams;
-    newTabParams.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
-    newTabParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
-    UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
-        ->Load(newTabParams);
-    return;
-  }
-
-  // Otherwise, load |urlLoadParams| in the current tab.
-  UrlLoadParams sameTabParams = urlLoadParams;
-  sameTabParams.disposition = WindowOpenDisposition::CURRENT_TAB;
-  UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
-      ->Load(sameTabParams);
-  if (tabOpenedCompletion) {
-    tabOpenedCompletion();
-  }
-}
-
 - (ProceduralBlock)completionBlockForTriggeringAction:
     (NTPTabOpeningPostOpeningAction)action {
   switch (action) {
@@ -1870,164 +1694,6 @@
   }
 }
 
-- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)tabOpeningTargetMode
-            withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
-                   completion:(ProceduralBlock)completion {
-  // Update the snapshot before opening a new tab. This ensures that the
-  // snapshot is correct when tabs are openned via the dispatcher.
-  [self updateActiveWebStateSnapshot];
-
-  ApplicationMode targetMode;
-
-  if (tabOpeningTargetMode == ApplicationModeForTabOpening::CURRENT) {
-    targetMode = self.interfaceProvider.currentInterface.incognito
-                     ? ApplicationMode::INCOGNITO
-                     : ApplicationMode::NORMAL;
-  } else if (tabOpeningTargetMode == ApplicationModeForTabOpening::NORMAL) {
-    targetMode = ApplicationMode::NORMAL;
-  } else {
-    targetMode = ApplicationMode::INCOGNITO;
-  }
-
-  id<BrowserInterface> targetInterface =
-      targetMode == ApplicationMode::NORMAL
-          ? self.interfaceProvider.mainInterface
-          : self.interfaceProvider.incognitoInterface;
-  NSUInteger tabIndex = NSNotFound;
-  ProceduralBlock startupCompletion =
-      [self completionBlockForTriggeringAction:[_startupParameters
-                                                   postOpeningAction]];
-
-  // Commands are only allowed on NTP.
-  DCHECK(IsURLNtp(urlLoadParams.web_params.url) || !startupCompletion);
-
-  ProceduralBlock tabOpenedCompletion = nil;
-  if (startupCompletion && completion) {
-    tabOpenedCompletion = ^{
-      // Order is important here. |completion| may do cleaning tasks that will
-      // invalidate |startupCompletion|.
-      startupCompletion();
-      completion();
-    };
-  } else if (startupCompletion) {
-    tabOpenedCompletion = startupCompletion;
-  } else {
-    tabOpenedCompletion = completion;
-  }
-
-  if (self.tabSwitcherIsActive) {
-    // If the tab switcher is already being dismissed, simply add the tab and
-    // note that when the tab switcher finishes dismissing, the current BVC
-    // should be switched to be the main BVC if necessary.
-    if (_dismissingTabSwitcher) {
-      _modeToDisplayOnTabSwitcherDismissal =
-          targetMode == ApplicationMode::NORMAL
-              ? TabSwitcherDismissalMode::NORMAL
-              : TabSwitcherDismissalMode::INCOGNITO;
-      [targetInterface.bvc appendTabAddedCompletion:tabOpenedCompletion];
-      UrlLoadParams savedParams = urlLoadParams;
-      savedParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
-      UrlLoadingServiceFactory::GetForBrowserState(
-          [targetInterface.bvc browserState])
-          ->Load(savedParams);
-    } else {
-      // Voice search, QRScanner and the omnibox are presented by the BVC.
-      // They must be started after the BVC view is added in the hierarchy.
-      self.NTPActionAfterTabSwitcherDismissal =
-          [_startupParameters postOpeningAction];
-      [self setStartupParameters:nil];
-      [_tabSwitcher dismissWithNewTabAnimationToBrowser:targetInterface.browser
-                                      withUrlLoadParams:urlLoadParams
-                                                atIndex:tabIndex];
-    }
-  } else {
-    if (!self.currentBVC.presentedViewController) {
-      [targetInterface.bvc expectNewForegroundTab];
-    }
-    [self setCurrentInterfaceForMode:targetMode];
-    [self openOrReuseTabInMode:targetMode
-             withUrlLoadParams:urlLoadParams
-           tabOpenedCompletion:tabOpenedCompletion];
-  }
-
-  if (_restoreHelper) {
-    // Now that all the operations on the tabs have been done, display the
-    // restore infobar if needed.
-    dispatch_async(dispatch_get_main_queue(), ^{
-      TabModel* currentTabModel = [self currentTabModel];
-      [_restoreHelper
-          showRestoreIfNeededUsingWebState:currentTabModel.webStateList
-                                               ->GetActiveWebState()
-                           sessionRestorer:currentTabModel];
-      _restoreHelper = nil;
-    });
-  }
-}
-
-- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
-                           dismissOmnibox:(BOOL)dismissOmnibox {
-  // Immediately hide modals from the provider (alert views, action sheets,
-  // popovers). They will be ultimately dismissed by their owners, but at least,
-  // they are not visible.
-  ios::GetChromeBrowserProvider()->HideModalViewStack();
-
-  // ChromeIdentityService is responsible for the dialogs displayed by the
-  // services it wraps.
-  ios::GetChromeBrowserProvider()->GetChromeIdentityService()->DismissDialogs();
-
-  // MailtoHandlerProvider is responsible for the dialogs displayed by the
-  // services it wraps.
-  ios::GetChromeBrowserProvider()
-      ->GetMailtoHandlerProvider()
-      ->DismissAllMailtoHandlerInterfaces();
-
-  // Then, depending on what the SSO view controller is presented on, dismiss
-  // it.
-  ProceduralBlock completionWithBVC = ^{
-    DCHECK(self.currentBVC);
-    DCHECK(!self.tabSwitcherIsActive);
-    DCHECK(!self.signinInteractionCoordinator.isActive);
-    // This will dismiss the SSO view controller.
-    [self.interfaceProvider.currentInterface
-        clearPresentedStateWithCompletion:completion
-                           dismissOmnibox:dismissOmnibox];
-  };
-  ProceduralBlock completionWithoutBVC = ^{
-    // |self.currentBVC| may exist but tab switcher should be active.
-    DCHECK(self.tabSwitcherIsActive);
-    // This will dismiss the SSO view controller.
-    [self.signinInteractionCoordinator cancelAndDismiss];
-    // History coordinator can be started on top of the tab grid. This is not
-    // true of the other tab switchers.
-    DCHECK(self.mainCoordinator);
-    [self.mainCoordinator stopChildCoordinatorsWithCompletion:completion];
-  };
-
-  // As a top level rule, if the settings are showing, they need to be
-  // dismissed. Then, based on whether the BVC is present or not, a different
-  // completion callback is called.
-  if (!self.tabSwitcherIsActive && self.isSettingsViewPresented) {
-    // In this case, the settings are up and the BVC is showing. Close the
-    // settings then call the BVC completion.
-    [self closeSettingsAnimated:NO completion:completionWithBVC];
-  } else if (self.isSettingsViewPresented) {
-    // In this case, the settings are up but the BVC is not showing. Close the
-    // settings then call the no-BVC completion.
-    [self closeSettingsAnimated:NO completion:completionWithoutBVC];
-  } else if (![self isTabSwitcherActive]) {
-    // In this case, the settings are not shown but the BVC is showing. Call the
-    // BVC completion.
-    [self.signinInteractionCoordinator cancel];
-    completionWithBVC();
-  } else {
-    // In this case, neither the settings nor the BVC are shown. Call the no-BVC
-    // completion.
-    completionWithoutBVC();
-  }
-
-  // Verify that no modal views are left presented.
-  ios::GetChromeBrowserProvider()->LogIfModalViewsArePresented();
-}
 
 - (bool)mustShowRestoreInfobar {
   if ([self isFirstLaunchAfterUpgrade])
@@ -2045,18 +1711,6 @@
   return result;
 }
 
-// Asks the respective Snapshot helper to update the snapshot for the active
-// WebState.
-- (void)updateActiveWebStateSnapshot {
-  WebStateList* webStateList = self.currentBVC.tabModel.webStateList;
-  if (webStateList) {
-    web::WebState* webState = webStateList->GetActiveWebState();
-    if (webState) {
-      SnapshotTabHelper::FromWebState(webState)->UpdateSnapshotWithCallback(
-          nil);
-    }
-  }
-}
 
 - (void)purgeSnapshots {
   NSMutableSet* liveSessions = [self liveSessionsForTabModel:self.mainTabModel];
@@ -2087,11 +1741,11 @@
                                dismissOmnibox:(BOOL)dismissOmnibox
                                    completion:(ProceduralBlock)completion {
   UrlLoadParams copyOfUrlLoadParams = urlLoadParams;
-  [self
+  [self.sceneController
       dismissModalDialogsWithCompletion:^{
-        [self openSelectedTabInMode:targetMode
-                  withUrlLoadParams:copyOfUrlLoadParams
-                         completion:completion];
+        [self.sceneController openSelectedTabInMode:targetMode
+                                  withUrlLoadParams:copyOfUrlLoadParams
+                                         completion:completion];
       }
                          dismissOmnibox:dismissOmnibox];
 }
@@ -2112,38 +1766,10 @@
   }
 }
 
+// TODO(crbug.com/1021752): Remove this stub.
 - (BOOL)shouldCompletePaymentRequestOnCurrentTab:
     (id<StartupInformation>)startupInformation {
-  if (!startupInformation.startupParameters)
-    return NO;
-
-  if (!startupInformation.startupParameters.completePaymentRequest)
-    return NO;
-
-  if (!base::FeatureList::IsEnabled(payments::features::kWebPaymentsNativeApps))
-    return NO;
-
-  payments::IOSPaymentInstrumentLauncher* paymentAppLauncher =
-      payments::IOSPaymentInstrumentLauncherFactory::GetInstance()
-          ->GetForBrowserState(self.mainBrowserState);
-
-  if (!paymentAppLauncher->delegate())
-    return NO;
-
-  std::string payment_id =
-      startupInformation.startupParameters.externalURLParams
-          .find(payments::kPaymentRequestIDExternal)
-          ->second;
-  if (paymentAppLauncher->payment_request_id() != payment_id)
-    return NO;
-
-  std::string payment_response =
-      startupInformation.startupParameters.externalURLParams
-          .find(payments::kPaymentRequestDataExternal)
-          ->second;
-  paymentAppLauncher->ReceiveResponseFromIOSPaymentInstrument(payment_response);
-  [startupInformation setStartupParameters:nil];
-  return YES;
+  return NO;
 }
 
 - (BOOL)URLIsOpenedInRegularMode:(const GURL&)URL {
@@ -2171,21 +1797,6 @@
   return [self currentBrowserState] -> IsOffTheRecord();
 }
 
-// This method is temporarily both required in the scene controller and here.
-- (void)openURLInNewTab:(OpenNewTabCommand*)command {
-  UrlLoadParams params =
-      UrlLoadParams::InNewTab(command.URL, command.virtualURL);
-  params.SetInBackground(command.inBackground);
-  params.web_params.referrer = command.referrer;
-  params.in_incognito = command.inIncognito;
-  params.append_to = command.appendTo;
-  params.origin_point = command.originPoint;
-  params.from_chrome = command.fromChrome;
-  params.user_initiated = command.userInitiated;
-  params.should_focus_omnibox = command.shouldFocusOmnibox;
-  self.appURLLoadingService->LoadUrlInNewTab(params);
-}
-
 #pragma mark - BrowsingDataCommands
 
 - (void)removeBrowsingDataForBrowserState:(ios::ChromeBrowserState*)browserState
@@ -2259,6 +1870,12 @@
 
 @implementation MainController (TestingOnly)
 
+- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox {
+  [self.sceneController dismissModalDialogsWithCompletion:completion
+                                           dismissOmnibox:dismissOmnibox];
+}
+
 - (DeviceSharingManager*)deviceSharingManager {
   return [_browserViewWrangler deviceSharingManager];
 }
@@ -2278,13 +1895,9 @@
   self.tabSwitcherIsActive = active;
 }
 
-- (BOOL)dismissingTabSwitcher {
-  return _dismissingTabSwitcher;
-}
-
 - (void)setStartupParametersWithURL:(const GURL&)launchURL {
   NSString* sourceApplication = @"Fake App";
-  _startupParameters = [ChromeAppStartupParameters
+  self.startupParameters = [ChromeAppStartupParameters
       newChromeAppStartupParametersWithURL:net::NSURLWithGURL(launchURL)
                      fromSourceApplication:sourceApplication];
 }
diff --git a/ios/chrome/app/main_controller_guts.h b/ios/chrome/app/main_controller_guts.h
index c288e55..e9169a8c 100644
--- a/ios/chrome/app/main_controller_guts.h
+++ b/ios/chrome/app/main_controller_guts.h
@@ -7,6 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
+#import "ios/chrome/browser/crash_report/crash_restore_helper.h"
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
 
@@ -22,6 +23,11 @@
 class ChromeBrowserState;
 }  // namespace ios
 
+// Used to update the current BVC mode if a new tab is added while the tab
+// switcher view is being dismissed.  This is different than ApplicationMode in
+// that it can be set to |NONE| when not in use.
+enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
+
 // TODO(crbug.com/1012697): Remove this protocol when SceneController is
 // operational. Move the private internals back into MainController, and pass
 // ownership of Scene-related objects to SceneController.
@@ -54,10 +60,39 @@
     SigninInteractionCoordinator* signinInteractionCoordinator;
 
 // If YES, the tab switcher is currently active.
-
 @property(nonatomic, assign, getter=isTabSwitcherActive)
     BOOL tabSwitcherIsActive;
 
+// YES while animating the dismissal of tab switcher.
+@property(nonatomic, assign, getter=dismissingTabSwitcher)
+    BOOL dismissingTabSwitcher;
+
+// Returns YES if the settings are presented, either from
+// self.settingsNavigationController or from SigninInteractionCoordinator.
+@property(nonatomic, assign, readonly, getter=isSettingsViewPresented)
+    BOOL settingsViewPresented;
+
+// If not NONE, the current BVC should be switched to this BVC on completion
+// of tab switcher dismissal.
+@property(nonatomic, assign)
+    TabSwitcherDismissalMode modeToDisplayOnTabSwitcherDismissal;
+
+// A property to track whether the QR Scanner should be started upon tab
+// switcher dismissal. It can only be YES if the QR Scanner experiment is
+// enabled.
+@property(nonatomic, readwrite)
+    NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal;
+
+// Parameters received at startup time when the app is launched from another
+// app.
+@property(nonatomic, strong) AppStartupParameters* startupParameters;
+
+- (ProceduralBlock)completionBlockForTriggeringAction:
+    (NTPTabOpeningPostOpeningAction)action;
+
+// Keeps track of the restore state during startup.
+@property(nonatomic, strong) CrashRestoreHelper* restoreHelper;
+
 - (id<TabSwitcher>)tabSwitcher;
 - (TabModel*)currentTabModel;
 - (id<TabSwitcher>)tabSwitcher;
@@ -70,11 +105,6 @@
 - (id<BrowserInterfaceProvider>)interfaceProvider;
 - (void)startVoiceSearchInCurrentBVC;
 
-- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
-                           dismissOmnibox:(BOOL)dismissOmnibox;
-- (void)closeSettingsAnimated:(BOOL)animated
-                   completion:(ProceduralBlock)completion;
-
 - (void)dismissModalsAndOpenSelectedTabInMode:
             (ApplicationModeForTabOpening)targetMode
                             withUrlLoadParams:
@@ -95,6 +125,13 @@
 // screen and showing the appropriate BVC.
 - (void)finishDismissingTabSwitcher;
 
+// Sets |currentBVC| as the root view controller for the window.
+- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox;
+
+// Activates |mainBVC| and |otrBVC| and sets |currentBVC| as primary iff
+// |currentBVC| can be made active.
+- (void)activateBVCAndMakeCurrentBVCPrimary;
+
 @end
 
 #endif  // IOS_CHROME_APP_MAIN_CONTROLLER_GUTS_H_
diff --git a/ios/chrome/app/main_controller_private.h b/ios/chrome/app/main_controller_private.h
index a26d4d3f..edd36ff 100644
--- a/ios/chrome/app/main_controller_private.h
+++ b/ios/chrome/app/main_controller_private.h
@@ -24,11 +24,6 @@
 // Presents a promo's navigation controller.
 - (void)showPromo:(UIViewController*)promo;
 
-// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is
-// NO, then call |completion|.
-- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
-                           dismissOmnibox:(BOOL)dismissOmnibox;
-
 @end
 
 // Methods that only exist for tests.
@@ -42,12 +37,16 @@
 
 // Tab switcher state.
 @property(nonatomic, getter=isTabSwitcherActive) BOOL tabSwitcherActive;
-@property(nonatomic, readonly) BOOL dismissingTabSwitcher;
 
 // Sets the internal startup state to indicate that the launch was triggered
 // by an external app opening the given URL.
 - (void)setStartupParametersWithURL:(const GURL&)launchURL;
 
+// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is
+// NO, then call |completion|.
+- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox;
+
 @end
 
 #endif  // IOS_CHROME_APP_MAIN_CONTROLLER_PRIVATE_H_
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn
index dddf70f..6fbce16 100644
--- a/ios/chrome/app/resources/BUILD.gn
+++ b/ios/chrome/app/resources/BUILD.gn
@@ -135,9 +135,7 @@
 
 bundle_data_ib_file("launchscreen_xib") {
   source = "LaunchScreen.xib"
-  deps = [
-    ios_launchscreen_assets_target,
-  ]
+  deps = [ ios_launchscreen_assets_target ]
 }
 
 generate_localizable_strings("system_strings") {
@@ -149,9 +147,7 @@
     "Localizable.strings",
     "Intents.strings",
   ]
-  deps = [
-    ios_packed_resources_target,
-  ]
+  deps = [ ios_packed_resources_target ]
 }
 
 imageset("quick_action_incognito_search") {
diff --git a/ios/chrome/app/spotlight/BUILD.gn b/ios/chrome/app/spotlight/BUILD.gn
index f8cd548..c8c04f9 100644
--- a/ios/chrome/app/spotlight/BUILD.gn
+++ b/ios/chrome/app/spotlight/BUILD.gn
@@ -53,9 +53,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "spotlight_manager_unittest.mm",
-  ]
+  sources = [ "spotlight_manager_unittest.mm" ]
   deps = [
     ":spotlight",
     "//base",
diff --git a/ios/chrome/app/startup/BUILD.gn b/ios/chrome/app/startup/BUILD.gn
index 02e8dde..920eba0 100644
--- a/ios/chrome/app/startup/BUILD.gn
+++ b/ios/chrome/app/startup/BUILD.gn
@@ -72,9 +72,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "chrome_app_startup_parameters_unittest.mm",
-  ]
+  sources = [ "chrome_app_startup_parameters_unittest.mm" ]
   deps = [
     ":startup",
     "//base",
diff --git a/ios/chrome/app/strings/BUILD.gn b/ios/chrome/app/strings/BUILD.gn
index be6b02b..e6be093 100644
--- a/ios/chrome/app/strings/BUILD.gn
+++ b/ios/chrome/app/strings/BUILD.gn
@@ -16,9 +16,7 @@
 grit("ios_strings") {
   source = "ios_strings.grd"
   output_dir = "$root_gen_dir/ios/chrome"
-  outputs = [
-    "grit/ios_strings.h",
-  ]
+  outputs = [ "grit/ios_strings.h" ]
   foreach(locale, locales_with_fake_bidi) {
     outputs += [ "ios_strings_$locale.pak" ]
   }
@@ -27,9 +25,7 @@
 grit("ios_chromium_strings") {
   source = "ios_chromium_strings.grd"
   output_dir = "$root_gen_dir/ios/chrome"
-  outputs = [
-    "grit/ios_chromium_strings.h",
-  ]
+  outputs = [ "grit/ios_chromium_strings.h" ]
   foreach(locale, locales_with_fake_bidi) {
     outputs += [ "ios_chromium_strings_$locale.pak" ]
   }
@@ -38,9 +34,7 @@
 grit("ios_google_chrome_strings") {
   source = "ios_google_chrome_strings.grd"
   output_dir = "$root_gen_dir/ios/chrome"
-  outputs = [
-    "grit/ios_google_chrome_strings.h",
-  ]
+  outputs = [ "grit/ios_google_chrome_strings.h" ]
   foreach(locale, locales_with_fake_bidi) {
     outputs += [ "ios_google_chrome_strings_$locale.pak" ]
   }
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index be37357..9390444b 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -74,7 +74,6 @@
     "//components/ntp_tiles",
     "//components/omnibox/browser",
     "//components/password_manager/core/common:common",
-    "//components/payments/core",
     "//components/pref_registry",
     "//components/prefs",
     "//components/proxy_config",
@@ -103,7 +102,6 @@
     "//ios/chrome/browser/drag_and_drop",
     "//ios/chrome/browser/find_in_page:feature_flags",
     "//ios/chrome/browser/itunes_urls",
-    "//ios/chrome/browser/payments:constants",
     "//ios/chrome/browser/signin:feature_flags",
     "//ios/chrome/browser/ssl:feature_flags",
     "//ios/chrome/browser/sync/glue",
@@ -169,7 +167,9 @@
     "chrome_url_constants.h",
   ]
 
-  deps = [ "//base" ]
+  deps = [
+    "//base",
+  ]
   libs = [ "UIKit.framework" ]
 }
 
@@ -254,7 +254,9 @@
     "resources/Settings.bundle/Experimental.plist",
     "resources/Settings.bundle/Root.plist",
   ]
-  outputs = [ "{{bundle_resources_dir}}/Settings.bundle/{{source_file_part}}" ]
+  outputs = [
+    "{{bundle_resources_dir}}/Settings.bundle/{{source_file_part}}",
+  ]
 }
 
 source_set("unit_tests") {
diff --git a/ios/chrome/browser/device_sharing/BUILD.gn b/ios/chrome/browser/device_sharing/BUILD.gn
index 94906696..742343de 100644
--- a/ios/chrome/browser/device_sharing/BUILD.gn
+++ b/ios/chrome/browser/device_sharing/BUILD.gn
@@ -22,9 +22,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "device_sharing_manager_unittest.mm",
-  ]
+  sources = [ "device_sharing_manager_unittest.mm" ]
   deps = [
     ":device_sharing",
     "//base",
@@ -79,18 +77,14 @@
   ]
   testonly = true
 
-  sources = [
-    "handoff_manager_app_interface.h",
-  ]
+  sources = [ "handoff_manager_app_interface.h" ]
 }
 
 source_set("eg_tests") {
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "handoff_manager_egtest.mm",
-  ]
+  sources = [ "handoff_manager_egtest.mm" ]
   deps = [
     ":test_support",
     "//ios/chrome/browser/ui/util",
@@ -112,9 +106,7 @@
   ]
   testonly = true
 
-  sources = [
-    "handoff_manager_egtest.mm",
-  ]
+  sources = [ "handoff_manager_egtest.mm" ]
 
   deps = [
     ":eg_test_support+eg2",
diff --git a/ios/chrome/browser/dom_distiller/BUILD.gn b/ios/chrome/browser/dom_distiller/BUILD.gn
index dab73d24..f6552a5 100644
--- a/ios/chrome/browser/dom_distiller/BUILD.gn
+++ b/ios/chrome/browser/dom_distiller/BUILD.gn
@@ -20,7 +20,5 @@
     "//ui/gfx",
     "//url",
   ]
-  public_deps = [
-    "//components/dom_distiller/core",
-  ]
+  public_deps = [ "//components/dom_distiller/core" ]
 }
diff --git a/ios/chrome/browser/download/BUILD.gn b/ios/chrome/browser/download/BUILD.gn
index 5eafcfa..b3cff38 100644
--- a/ios/chrome/browser/download/BUILD.gn
+++ b/ios/chrome/browser/download/BUILD.gn
@@ -24,9 +24,7 @@
     "pass_kit_tab_helper_delegate.h",
   ]
 
-  public_deps = [
-    ":mime_types",
-  ]
+  public_deps = [ ":mime_types" ]
 
   deps = [
     "//base",
@@ -57,9 +55,7 @@
     "usdz_mime_type.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 }
@@ -100,7 +96,5 @@
     "download_test_util.cc",
     "download_test_util.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/ios/chrome/browser/find_in_page/find_tab_helper.h b/ios/chrome/browser/find_in_page/find_tab_helper.h
index 430f639..d166e29 100644
--- a/ios/chrome/browser/find_in_page/find_tab_helper.h
+++ b/ios/chrome/browser/find_in_page/find_tab_helper.h
@@ -82,8 +82,6 @@
   FindTabHelper(web::WebState* web_state);
 
   // web::WebStateObserver.
-  void DidFinishNavigation(web::WebState* web_state,
-                           web::NavigationContext* navigation_context) override;
   void WebStateDestroyed(web::WebState* web_state) override;
 
   // The ObjC find in page controller.
diff --git a/ios/chrome/browser/find_in_page/find_tab_helper.mm b/ios/chrome/browser/find_in_page/find_tab_helper.mm
index 0459600..0a211451 100644
--- a/ios/chrome/browser/find_in_page/find_tab_helper.mm
+++ b/ios/chrome/browser/find_in_page/find_tab_helper.mm
@@ -90,12 +90,6 @@
   [controller_ restoreSearchTerm];
 }
 
-void FindTabHelper::DidFinishNavigation(
-    web::WebState* web_state,
-    web::NavigationContext* navigation_context) {
-  StopFinding(nil);
-}
-
 void FindTabHelper::WebStateDestroyed(web::WebState* web_state) {
   [controller_ detachFromWebState];
   web_state->RemoveObserver(this);
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn
index 690ea68..5e6c81d2 100644
--- a/ios/chrome/browser/metrics/BUILD.gn
+++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -41,9 +41,7 @@
     "previous_session_info.mm",
     "previous_session_info_private.h",
   ]
-  public_deps = [
-    "//components/ukm/ios:ukm_url_recorder",
-  ]
+  public_deps = [ "//components/ukm/ios:ukm_url_recorder" ]
   deps = [
     ":chrome_browser_state_client",
     "//base",
@@ -168,9 +166,7 @@
     "tab_usage_recorder_metrics.h",
     "tab_usage_recorder_metrics.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests_internal") {
diff --git a/ios/chrome/browser/ntp/BUILD.gn b/ios/chrome/browser/ntp/BUILD.gn
index 21508a3..e34fffb8 100644
--- a/ios/chrome/browser/ntp/BUILD.gn
+++ b/ios/chrome/browser/ntp/BUILD.gn
@@ -25,17 +25,13 @@
     "features.cc",
     "features.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "new_tab_page_tab_helper_unittest.mm",
-  ]
+  sources = [ "new_tab_page_tab_helper_unittest.mm" ]
   deps = [
     "//base/test:test_support",
     "//components/strings:components_strings_grit",
diff --git a/ios/chrome/browser/ui/alert_view/BUILD.gn b/ios/chrome/browser/ui/alert_view/BUILD.gn
index e7f5e8b..8ec9bb8 100644
--- a/ios/chrome/browser/ui/alert_view/BUILD.gn
+++ b/ios/chrome/browser/ui/alert_view/BUILD.gn
@@ -25,9 +25,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "alert_view_controller_unittest.mm",
-  ]
+  sources = [ "alert_view_controller_unittest.mm" ]
   deps = [
     ":alert_view",
     "//testing/gtest:gtest",
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index 9015181..33d3ecdd 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -25,7 +25,6 @@
     "//components/image_fetcher/ios",
     "//components/language/ios/browser",
     "//components/omnibox/browser",
-    "//components/payments/core",
     "//components/reading_list/core",
     "//components/search_engines",
     "//components/sessions",
@@ -121,7 +120,6 @@
     "//ios/chrome/browser/ui/page_info:features",
     "//ios/chrome/browser/ui/page_info/requirements",
     "//ios/chrome/browser/ui/passwords",
-    "//ios/chrome/browser/ui/payments",
     "//ios/chrome/browser/ui/popup_menu",
     "//ios/chrome/browser/ui/presenters",
     "//ios/chrome/browser/ui/print",
@@ -252,7 +250,9 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [ "browser_view_controller_egtest.mm" ]
+  sources = [
+    "browser_view_controller_egtest.mm",
+  ]
   deps = [
     ":browser_view",
     "//base",
@@ -290,7 +290,9 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [ "browser_view_controller_egtest.mm" ]
+  sources = [
+    "browser_view_controller_egtest.mm",
+  ]
   deps = [
     "//base",
     "//base/test:test_support",
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index aa0decb..88fb71c 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -115,7 +115,6 @@
 #import "ios/chrome/browser/ui/ntp/ntp_util.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h"
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
-#import "ios/chrome/browser/ui/payments/payment_request_manager.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.h"
 #import "ios/chrome/browser/ui/presenters/vertical_animation_container.h"
 #import "ios/chrome/browser/ui/sad_tab/sad_tab_coordinator.h"
@@ -398,10 +397,6 @@
   // management off of the BVC.
   KeyCommandsProvider* _keyCommandsProvider;
 
-  // Used to inject Javascript implementing the PaymentRequest API and to
-  // display the UI.
-  PaymentRequestManager* _paymentRequestManager;
-
   // Used to display the Voice Search UI.  Nil if not visible.
   scoped_refptr<VoiceSearchController> _voiceSearchController;
 
@@ -1188,6 +1183,7 @@
   // Keyboard shouldn't overlay the ecoutez window, so dismiss find in page and
   // dismiss the keyboard.
   [self closeFindInPage];
+  [self hideTextZoom];
   [[self viewForWebState:self.currentWebState] endEditing:NO];
 
   // Ensure that voice search objects are created.
@@ -1249,7 +1245,6 @@
   } else {
     [_dialogPresenter cancelAllDialogs];
   }
-  [_paymentRequestManager enablePaymentRequest:active];
 
   [self setNeedsStatusBarAppearanceUpdate];
 }
@@ -1279,9 +1274,9 @@
         [self.findBarCoordinator stop];
       });
     }
+    [self.textZoomCoordinator stop];
   }
 
-  [_paymentRequestManager cancelRequest];
   [self.dispatcher dismissPopupMenuAnimated:NO];
   [_contextMenuCoordinator stop];
 
@@ -1350,8 +1345,6 @@
   _isShutdown = YES;
 
   [self setActive:NO];
-  [_paymentRequestManager close];
-  _paymentRequestManager = nil;
 
   if (self.browserState) {
     TextToSpeechPlaybackController* controller =
@@ -1410,7 +1403,6 @@
   _allWebStateObservationForwarder = nullptr;
   if (_voiceSearchController)
     _voiceSearchController->SetDispatcher(nil);
-  [_paymentRequestManager setActiveWebState:nullptr];
   [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
@@ -1675,6 +1667,7 @@
   if (ShouldShowCompactToolbar(previousTraitCollection) !=
       ShouldShowCompactToolbar()) {
     [self.findBarCoordinator stop];
+    [self.textZoomCoordinator stop];
   }
 
   // Update the toolbar visibility.
@@ -2223,13 +2216,6 @@
         SadTabTabHelper::FromWebState(webStateList->GetWebStateAt(i));
     sadTabHelper->SetDelegate(_sadTabCoordinator);
   }
-
-  _paymentRequestManager = [[PaymentRequestManager alloc]
-      initWithBaseViewController:self
-                    browserState:self.browserState
-                      dispatcher:self.dispatcher];
-  [_paymentRequestManager setLocationBarModel:_locationBarModel.get()];
-  [_paymentRequestManager setActiveWebState:self.currentWebState];
 }
 
 // Set the frame for the various views. View must be loaded.
@@ -2368,6 +2354,7 @@
   if (!self.inNewTabAnimation) {
     // Hide findbar.  |updateToolbar| will restore the findbar later.
     [self.findBarCoordinator stop];
+    [self.textZoomCoordinator stop];
 
     // Make new content visible, resizing it first as the orientation may
     // have changed from the last time it was displayed.
@@ -2458,7 +2445,8 @@
     [self.primaryToolbarCoordinator showPrerenderingAnimation];
 
   auto* findHelper = FindTabHelper::FromWebState(webState);
-  if (findHelper && findHelper->IsFindUIActive()) {
+  if (findHelper && findHelper->IsFindUIActive() &&
+      !self.findBarCoordinator.presenter.isPresenting) {
     [self.findBarCoordinator start];
   }
 
@@ -3428,13 +3416,8 @@
     [self updateToolbar];
 }
 
-// TODO(crbug.com/918934): This call to closeFindInPage incorrectly triggers for
-// all navigations, not just navigations in the active WebState.
 - (void)webState:(web::WebState*)webState
     didFinishNavigation:(web::NavigationContext*)navigation {
-  // Stop any Find in Page searches and close the find bar when navigating to a
-  // new page.
-  [self closeFindInPage];
   [self.tabModel saveSessionImmediately:NO];
 }
 
@@ -4058,6 +4041,12 @@
     return;
   }
 
+  self.findBarCoordinator =
+      [[FindBarCoordinator alloc] initWithBaseViewController:self
+                                                     browser:self.browser];
+  self.findBarCoordinator.presenter = self.toolbarAccessoryPresenter;
+  self.findBarCoordinator.delegate = self;
+
   [self.findBarCoordinator start];
 }
 
@@ -4217,6 +4206,12 @@
     return;
   }
 
+  self.textZoomCoordinator =
+      [[TextZoomCoordinator alloc] initWithBaseViewController:self
+                                                      browser:self.browser];
+  self.textZoomCoordinator.presenter = self.toolbarAccessoryPresenter;
+  self.textZoomCoordinator.delegate = self;
+
   [self.textZoomCoordinator start];
 }
 
@@ -4256,8 +4251,6 @@
 
   self.currentWebState->GetWebViewProxy().scrollViewProxy.clipsToBounds = NO;
 
-  [_paymentRequestManager setActiveWebState:newWebState];
-
   [self webStateSelected:newWebState notifyToolbar:YES];
 }
 
@@ -4280,6 +4273,7 @@
 
   // Remove the find bar for now.
   [self.findBarCoordinator stop];
+  [self.textZoomCoordinator stop];
 }
 
 - (void)webStateList:(WebStateList*)webStateList
@@ -4289,13 +4283,8 @@
     self.browserContainerViewController.contentView = nil;
   }
 
-  [_paymentRequestManager stopTrackingWebState:webState];
-
   [[UpgradeCenter sharedInstance]
       tabWillClose:TabIdTabHelper::FromWebState(webState)->tab_id()];
-  if (webStateList->count() == 1) {  // About to remove the last tab.
-    [_paymentRequestManager setActiveWebState:nullptr];
-  }
 }
 
 // Observer method, WebState replaced in |webStateList|.
@@ -4309,9 +4298,6 @@
   // Add |newTab|'s view to the hierarchy if it's the current Tab.
   if (self.active && self.currentWebState == newWebState)
     [self displayWebState:newWebState];
-
-  if (newWebState)
-    [_paymentRequestManager setActiveWebState:newWebState];
 }
 
 // Observer method, |webState| inserted in |webStateList|.
@@ -4322,10 +4308,6 @@
   DCHECK(webState);
   [self installDelegatesForWebState:webState];
 
-  if (activating) {
-    [_paymentRequestManager setActiveWebState:webState];
-  }
-
   DCHECK_EQ(self.tabModel.webStateList, webStateList);
 
   // Don't initiate Tab animation while session restoration is in progress
@@ -4557,6 +4539,7 @@
     // Hide UI accessories such as find bar and first visit overlays
     // for welcome page.
     [self.findBarCoordinator stop];
+    [self.textZoomCoordinator stop];
     [self.infobarContainerCoordinator hideContainer:YES];
   }
 }
@@ -4739,6 +4722,9 @@
 
 - (void)toolbarAccessoryCoordinatorDidDismissUI:
     (ChromeCoordinator*)coordinator {
+  if (!self.nextToolbarCoordinator) {
+    return;
+  }
   if (self.nextToolbarCoordinator == self.findBarCoordinator) {
     dispatch_async(dispatch_get_main_queue(), ^{
       [self showFindInPage];
@@ -4765,31 +4751,6 @@
   return _toolbarAccessoryPresenter;
 }
 
-- (FindBarCoordinator*)findBarCoordinator {
-  if (_findBarCoordinator) {
-    return _findBarCoordinator;
-  }
-  _findBarCoordinator =
-      [[FindBarCoordinator alloc] initWithBaseViewController:self
-                                                     browser:self.browser];
-  _findBarCoordinator.presenter = self.toolbarAccessoryPresenter;
-  _findBarCoordinator.delegate = self;
-
-  return _findBarCoordinator;
-}
-
-- (TextZoomCoordinator*)textZoomCoordinator {
-  if (_textZoomCoordinator) {
-    return _textZoomCoordinator;
-  }
-  _textZoomCoordinator =
-      [[TextZoomCoordinator alloc] initWithBaseViewController:self
-                                                      browser:self.browser];
-  _textZoomCoordinator.presenter = self.toolbarAccessoryPresenter;
-  _textZoomCoordinator.delegate = self;
-  return _textZoomCoordinator;
-}
-
 #pragma mark - ManageAccountsDelegate
 
 - (void)onManageAccounts {
diff --git a/ios/chrome/browser/ui/find_bar/BUILD.gn b/ios/chrome/browser/ui/find_bar/BUILD.gn
index 5df40b0..d67ddd0 100644
--- a/ios/chrome/browser/ui/find_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/find_bar/BUILD.gn
@@ -9,6 +9,8 @@
     "find_bar_controller_ios.mm",
     "find_bar_coordinator.h",
     "find_bar_coordinator.mm",
+    "find_bar_mediator.h",
+    "find_bar_mediator.mm",
     "find_bar_view.h",
     "find_bar_view.mm",
     "find_bar_view_controller.h",
@@ -58,9 +60,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "find_in_page_egtest.mm",
-  ]
+  sources = [ "find_in_page_egtest.mm" ]
   deps = [
     ":constants",
     ":eg_test_support+eg2",
@@ -83,9 +83,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "find_in_page_egtest.mm",
-  ]
+  sources = [ "find_in_page_egtest.mm" ]
   deps = [
     ":constants",
     ":test_support",
@@ -111,9 +109,7 @@
     "find_in_page_controller_app_interface.h",
     "find_in_page_controller_app_interface.mm",
   ]
-  deps = [
-    "//ios/chrome/browser/find_in_page",
-  ]
+  deps = [ "//ios/chrome/browser/find_in_page" ]
 }
 
 source_set("eg_app_support+eg2") {
@@ -127,9 +123,7 @@
     "find_in_page_controller_app_interface.h",
     "find_in_page_controller_app_interface.mm",
   ]
-  deps = [
-    "//ios/chrome/browser/find_in_page",
-  ]
+  deps = [ "//ios/chrome/browser/find_in_page" ]
 }
 
 source_set("eg_test_support+eg2") {
@@ -139,7 +133,5 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "find_in_page_controller_app_interface.h",
-  ]
+  sources = [ "find_in_page_controller_app_interface.h" ]
 }
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_coordinator.mm b/ios/chrome/browser/ui/find_bar/find_bar_coordinator.mm
index 42133b0..eadf58a 100644
--- a/ios/chrome/browser/ui/find_bar/find_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/find_bar/find_bar_coordinator.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h"
+#import "ios/chrome/browser/ui/find_bar/find_bar_mediator.h"
 #import "ios/chrome/browser/ui/find_bar/find_bar_view_controller.h"
 #include "ios/chrome/browser/ui/presenters/contained_presenter_delegate.h"
 #import "ios/chrome/browser/ui/toolbar/accessory/toolbar_accessory_coordinator_delegate.h"
@@ -27,6 +28,8 @@
 // Command handler for |BrowserCommand|s.
 @property(nonatomic, readonly) id<BrowserCommands> browserCommandHandler;
 
+@property(nonatomic, strong) FindBarMediator* mediator;
+
 @end
 
 @implementation FindBarCoordinator
@@ -40,6 +43,12 @@
   }
   self.presenter.delegate = self;
 
+  self.mediator = [[FindBarMediator alloc]
+      initWithWebStateList:self.browser->GetWebStateList()
+            commandHandler:HandlerForProtocol(
+                               self.browser->GetCommandDispatcher(),
+                               BrowserCommands)];
+
   DCHECK(self.currentWebState);
   FindTabHelper* helper = FindTabHelper::FromWebState(self.currentWebState);
   // If the FindUI is already active, just reshow it.
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_mediator.h b/ios/chrome/browser/ui/find_bar/find_bar_mediator.h
new file mode 100644
index 0000000..48fe006
--- /dev/null
+++ b/ios/chrome/browser/ui/find_bar/find_bar_mediator.h
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_FIND_BAR_FIND_BAR_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_UI_FIND_BAR_FIND_BAR_MEDIATOR_H_
+
+#import <Foundation/Foundation.h>
+
+@protocol BrowserCommands;
+class WebStateList;
+
+// Mediator for the Find Bar and the Find In page feature. As this feature is
+// currently being split off from BVC, this mediator will have more features
+// added and is not an ideal example of the mediator pattern.
+@interface FindBarMediator : NSObject
+
+- (instancetype)initWithWebStateList:(WebStateList*)webStateList
+                      commandHandler:(id<BrowserCommands>)commandHandler;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_FIND_BAR_FIND_BAR_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_mediator.mm b/ios/chrome/browser/ui/find_bar/find_bar_mediator.mm
new file mode 100644
index 0000000..e8728b77
--- /dev/null
+++ b/ios/chrome/browser/ui/find_bar/find_bar_mediator.mm
@@ -0,0 +1,53 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/find_bar/find_bar_mediator.h"
+
+#import "ios/chrome/browser/main/browser.h"
+#import "ios/chrome/browser/ui/commands/browser_commands.h"
+#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
+#import "ios/chrome/browser/web_state_list/active_web_state_observation_forwarder.h"
+#import "ios/web/public/web_state.h"
+#import "ios/web/public/web_state_observer_bridge.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface FindBarMediator () <CRWWebStateObserver> {
+  std::unique_ptr<web::WebStateObserverBridge> _observer;
+  std::unique_ptr<ActiveWebStateObservationForwarder> _forwarder;
+}
+
+// Handler for any BrowserCommands.
+@property(nonatomic, weak) id<BrowserCommands> commandHandler;
+
+@end
+
+@implementation FindBarMediator
+
+- (instancetype)initWithWebStateList:(WebStateList*)webStateList
+                      commandHandler:(id<BrowserCommands>)commandHandler {
+  self = [super init];
+  if (self) {
+    DCHECK(webStateList);
+
+    _commandHandler = commandHandler;
+
+    // Set up the WebState and its observer.
+    _observer = std::make_unique<web::WebStateObserverBridge>(self);
+    _forwarder = std::make_unique<ActiveWebStateObservationForwarder>(
+        webStateList, _observer.get());
+  }
+  return self;
+}
+
+#pragma mark - CRWWebStateObserver
+
+- (void)webState:(web::WebState*)webState
+    didFinishNavigation:(web::NavigationContext*)navigation {
+  [self.commandHandler closeFindInPage];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn
index f246d95a..f54075d4 100644
--- a/ios/chrome/browser/ui/main/BUILD.gn
+++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -4,6 +4,19 @@
 
 import("//ios/build/chrome_build.gni")
 
+source_set("scene_guts") {
+  sources = [
+    "scene_controller_guts.h",
+  ]
+  deps = [
+    "//ios/chrome/app/application_delegate:application_delegate_internal",
+    "//ios/chrome/browser:utils",
+    "//ios/chrome/browser/url_loading",
+  ]
+
+  libs = [ "UIKit.framework" ]
+}
+
 source_set("scene") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
@@ -17,15 +30,18 @@
 
   deps = [
     ":main",
+    ":scene_guts",
     "//base",
     "//components/signin/public/identity_manager",
     "//components/url_formatter",
     "//ios/chrome/app:app",
     "//ios/chrome/app/application_delegate:application_delegate_internal",
+    "//ios/chrome/browser",
     "//ios/chrome/browser:chrome_url_constants",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/browsing_data",
     "//ios/chrome/browser/main",
+    "//ios/chrome/browser/ntp:features",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/snapshots",
     "//ios/chrome/browser/tabs:tabs",
@@ -39,6 +55,9 @@
     "//ios/chrome/browser/ui/util:multiwindow_util",
     "//ios/chrome/browser/url_loading",
     "//ios/chrome/browser/web_state_list",
+    "//ios/public/provider/chrome/browser",
+    "//ios/public/provider/chrome/browser/mailto",
+    "//ios/public/provider/chrome/browser/signin",
     "//ios/public/provider/chrome/browser/user_feedback",
   ]
 
diff --git a/ios/chrome/browser/ui/main/scene_controller.h b/ios/chrome/browser/ui/main/scene_controller.h
index 7c89e91..39d23a2 100644
--- a/ios/chrome/browser/ui/main/scene_controller.h
+++ b/ios/chrome/browser/ui/main/scene_controller.h
@@ -9,16 +9,20 @@
 
 #import "ios/chrome/app/application_delegate/tab_switching.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
+#import "ios/chrome/browser/ui/main/scene_controller_guts.h"
 #import "ios/chrome/browser/ui/main/scene_state.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_switcher.h"
+#import "ios/chrome/browser/url_loading/app_url_loading_service.h"
 
 @protocol MainControllerGuts;
 
 // The controller object for a scene. Reacts to scene state changes.
-@interface SceneController : NSObject <SceneStateObserver,
+@interface SceneController : NSObject <AppURLLoadingServiceDelegate,
+                                       SceneStateObserver,
                                        ApplicationCommands,
                                        TabSwitcherDelegate,
-                                       TabSwitching>
+                                       TabSwitching,
+                                       SceneControllerGuts>
 
 - (instancetype)init NS_UNAVAILABLE;
 - (instancetype)initWithSceneState:(SceneState*)sceneState
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index 1a0f8e1..78440be 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -19,7 +19,9 @@
 #include "ios/chrome/browser/browsing_data/browsing_data_remover.h"
 #include "ios/chrome/browser/browsing_data/browsing_data_remover_factory.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
+#import "ios/chrome/browser/chrome_url_util.h"
 #include "ios/chrome/browser/main/browser.h"
+#include "ios/chrome/browser/ntp/features.h"
 #include "ios/chrome/browser/signin/identity_manager_factory.h"
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
@@ -37,7 +39,12 @@
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/browser/url_loading/app_url_loading_service.h"
 #import "ios/chrome/browser/url_loading/url_loading_params.h"
+#import "ios/chrome/browser/url_loading/url_loading_service.h"
+#import "ios/chrome/browser/url_loading/url_loading_service_factory.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+#include "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h"
+#include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
 #import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
 #import "ios/web/public/web_state.h"
 
@@ -115,6 +122,10 @@
   return self.mainController.interfaceProvider.incognitoInterface;
 }
 
+- (id<BrowserInterfaceProvider>)interfaceProvider {
+  return self.mainController.interfaceProvider;
+}
+
 #pragma mark - SceneStateObserver
 
 - (void)sceneState:(SceneState*)sceneState
@@ -133,8 +144,7 @@
 #pragma mark - ApplicationCommands
 
 - (void)dismissModalDialogs {
-  [self.mainController dismissModalDialogsWithCompletion:nil
-                                          dismissOmnibox:YES];
+  [self dismissModalDialogsWithCompletion:nil dismissOmnibox:YES];
 }
 
 - (void)showHistory {
@@ -155,7 +165,7 @@
 }
 
 - (void)closeSettingsUI {
-  [self.mainController closeSettingsAnimated:YES completion:nullptr];
+  [self closeSettingsAnimated:YES completion:nullptr];
 }
 
 - (void)prepareTabSwitcher {
@@ -513,7 +523,7 @@
                                                 dismissOmnibox:YES
                                                     completion:nil];
   };
-  [self.mainController closeSettingsAnimated:YES completion:completion];
+  [self closeSettingsAnimated:YES completion:completion];
 }
 
 #pragma mark - UserFeedbackDataSource
@@ -606,4 +616,335 @@
   return YES;
 }
 
+#pragma mark - AppURLLoadingServiceDelegate
+
+// Note that the current tab of |browserCoordinator|'s BVC will normally be
+// reloaded by this method. If a new tab is about to be added, call
+// expectNewForegroundTab on the BVC first to avoid extra work and possible page
+// load side-effects for the tab being replaced.
+- (void)setCurrentInterfaceForMode:(ApplicationMode)mode {
+  DCHECK(self.interfaceProvider);
+  BOOL incognitio = mode == ApplicationMode::INCOGNITO;
+  id<BrowserInterface> currentInterface =
+      self.interfaceProvider.currentInterface;
+  id<BrowserInterface> newInterface =
+      incognitio ? self.interfaceProvider.incognitoInterface
+                 : self.interfaceProvider.mainInterface;
+  if (currentInterface && currentInterface == newInterface)
+    return;
+
+  // Update the snapshot before switching another application mode.  This
+  // ensures that the snapshot is correct when links are opened in a different
+  // application mode.
+  [self updateActiveWebStateSnapshot];
+
+  self.interfaceProvider.currentInterface = newInterface;
+
+  if (!self.mainController.dismissingTabSwitcher)
+    [self.mainController displayCurrentBVCAndFocusOmnibox:NO];
+
+  // Tell the BVC that was made current that it can use the web.
+  [self.mainController activateBVCAndMakeCurrentBVCPrimary];
+}
+
+- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox {
+  // Immediately hide modals from the provider (alert views, action sheets,
+  // popovers). They will be ultimately dismissed by their owners, but at least,
+  // they are not visible.
+  ios::GetChromeBrowserProvider()->HideModalViewStack();
+
+  // ChromeIdentityService is responsible for the dialogs displayed by the
+  // services it wraps.
+  ios::GetChromeBrowserProvider()->GetChromeIdentityService()->DismissDialogs();
+
+  // MailtoHandlerProvider is responsible for the dialogs displayed by the
+  // services it wraps.
+  ios::GetChromeBrowserProvider()
+      ->GetMailtoHandlerProvider()
+      ->DismissAllMailtoHandlerInterfaces();
+
+  // Then, depending on what the SSO view controller is presented on, dismiss
+  // it.
+  ProceduralBlock completionWithBVC = ^{
+    DCHECK(self.mainController.currentBVC);
+    DCHECK(!self.mainController.tabSwitcherIsActive);
+    DCHECK(!self.mainController.signinInteractionCoordinator.isActive);
+    // This will dismiss the SSO view controller.
+    [self.interfaceProvider.currentInterface
+        clearPresentedStateWithCompletion:completion
+                           dismissOmnibox:dismissOmnibox];
+  };
+  ProceduralBlock completionWithoutBVC = ^{
+    // |self.mainController.currentBVC| may exist but tab switcher should be
+    // active.
+    DCHECK(self.mainController.tabSwitcherIsActive);
+    // This will dismiss the SSO view controller.
+    [self.mainController.signinInteractionCoordinator cancelAndDismiss];
+    // History coordinator can be started on top of the tab grid. This is not
+    // true of the other tab switchers.
+    DCHECK(self.mainController.mainCoordinator);
+    [self.mainController.mainCoordinator
+        stopChildCoordinatorsWithCompletion:completion];
+  };
+
+  // As a top level rule, if the settings are showing, they need to be
+  // dismissed. Then, based on whether the BVC is present or not, a different
+  // completion callback is called.
+  if (!self.mainController.tabSwitcherIsActive &&
+      self.mainController.isSettingsViewPresented) {
+    // In this case, the settings are up and the BVC is showing. Close the
+    // settings then call the BVC completion.
+    [self closeSettingsAnimated:NO completion:completionWithBVC];
+  } else if (self.mainController.isSettingsViewPresented) {
+    // In this case, the settings are up but the BVC is not showing. Close the
+    // settings then call the no-BVC completion.
+    [self closeSettingsAnimated:NO completion:completionWithoutBVC];
+  } else if (![self.mainController isTabSwitcherActive]) {
+    // In this case, the settings are not shown but the BVC is showing. Call the
+    // BVC completion.
+    [self.mainController.signinInteractionCoordinator cancel];
+    completionWithBVC();
+  } else {
+    // In this case, neither the settings nor the BVC are shown. Call the no-BVC
+    // completion.
+    completionWithoutBVC();
+  }
+
+  // Verify that no modal views are left presented.
+  ios::GetChromeBrowserProvider()->LogIfModalViewsArePresented();
+}
+
+// Opens a tab in the target BVC, and switches to it in a way that's appropriate
+// to the current UI, based on the |dismissModals| flag:
+// - If a modal dialog is showing and |dismissModals| is NO, the selected tab of
+// the main tab model will change in the background, but the view won't change.
+// - Otherwise, any modal view will be dismissed, the tab switcher will animate
+// out if it is showing, the target BVC will become active, and the new tab will
+// be shown.
+// If the current tab in |targetMode| is a NTP, it can be reused to open URL.
+// |completion| is executed after the tab is opened. After Tab is open the
+// virtual URL is set to the pending navigation item.
+- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)tabOpeningTargetMode
+            withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
+                   completion:(ProceduralBlock)completion {
+  // Update the snapshot before opening a new tab. This ensures that the
+  // snapshot is correct when tabs are openned via the dispatcher.
+  [self updateActiveWebStateSnapshot];
+
+  ApplicationMode targetMode;
+
+  if (tabOpeningTargetMode == ApplicationModeForTabOpening::CURRENT) {
+    targetMode = self.interfaceProvider.currentInterface.incognito
+                     ? ApplicationMode::INCOGNITO
+                     : ApplicationMode::NORMAL;
+  } else if (tabOpeningTargetMode == ApplicationModeForTabOpening::NORMAL) {
+    targetMode = ApplicationMode::NORMAL;
+  } else {
+    targetMode = ApplicationMode::INCOGNITO;
+  }
+
+  id<BrowserInterface> targetInterface =
+      targetMode == ApplicationMode::NORMAL
+          ? self.interfaceProvider.mainInterface
+          : self.interfaceProvider.incognitoInterface;
+  NSUInteger tabIndex = NSNotFound;
+  ProceduralBlock startupCompletion = [self.mainController
+      completionBlockForTriggeringAction:[self.mainController.startupParameters
+                                                 postOpeningAction]];
+
+  // Commands are only allowed on NTP.
+  DCHECK(IsURLNtp(urlLoadParams.web_params.url) || !startupCompletion);
+
+  ProceduralBlock tabOpenedCompletion = nil;
+  if (startupCompletion && completion) {
+    tabOpenedCompletion = ^{
+      // Order is important here. |completion| may do cleaning tasks that will
+      // invalidate |startupCompletion|.
+      startupCompletion();
+      completion();
+    };
+  } else if (startupCompletion) {
+    tabOpenedCompletion = startupCompletion;
+  } else {
+    tabOpenedCompletion = completion;
+  }
+
+  if (self.mainController.tabSwitcherIsActive) {
+    // If the tab switcher is already being dismissed, simply add the tab and
+    // note that when the tab switcher finishes dismissing, the current BVC
+    // should be switched to be the main BVC if necessary.
+    if (self.mainController.dismissingTabSwitcher) {
+      self.mainController.modeToDisplayOnTabSwitcherDismissal =
+          targetMode == ApplicationMode::NORMAL
+              ? TabSwitcherDismissalMode::NORMAL
+              : TabSwitcherDismissalMode::INCOGNITO;
+      [targetInterface.bvc appendTabAddedCompletion:tabOpenedCompletion];
+      UrlLoadParams savedParams = urlLoadParams;
+      savedParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
+      UrlLoadingServiceFactory::GetForBrowserState(
+          [targetInterface.bvc browserState])
+          ->Load(savedParams);
+    } else {
+      // Voice search, QRScanner and the omnibox are presented by the BVC.
+      // They must be started after the BVC view is added in the hierarchy.
+      self.mainController.NTPActionAfterTabSwitcherDismissal =
+          [self.mainController.startupParameters postOpeningAction];
+      [self.mainController setStartupParameters:nil];
+      [self.mainController.tabSwitcher
+          dismissWithNewTabAnimationToBrowser:targetInterface.browser
+                            withUrlLoadParams:urlLoadParams
+                                      atIndex:tabIndex];
+    }
+  } else {
+    if (!self.mainController.currentBVC.presentedViewController) {
+      [targetInterface.bvc expectNewForegroundTab];
+    }
+    [self setCurrentInterfaceForMode:targetMode];
+    [self openOrReuseTabInMode:targetMode
+             withUrlLoadParams:urlLoadParams
+           tabOpenedCompletion:tabOpenedCompletion];
+  }
+
+  if (self.mainController.restoreHelper) {
+    // Now that all the operations on the tabs have been done, display the
+    // restore infobar if needed.
+    dispatch_async(dispatch_get_main_queue(), ^{
+      TabModel* currentTabModel = [self currentTabModel];
+      [self.mainController.restoreHelper
+          showRestoreIfNeededUsingWebState:currentTabModel.webStateList
+                                               ->GetActiveWebState()
+                           sessionRestorer:currentTabModel];
+      self.mainController.restoreHelper = nil;
+    });
+  }
+}
+
+- (void)openURLInNewTabWithCommand:(OpenNewTabCommand*)command {
+  [self openURLInNewTab:command];
+}
+
+- (void)expectNewForegroundTabForMode:(ApplicationMode)targetMode {
+  id<BrowserInterface> interface =
+      targetMode == ApplicationMode::INCOGNITO
+          ? self.interfaceProvider.incognitoInterface
+          : self.interfaceProvider.mainInterface;
+  DCHECK(interface);
+  [interface.bvc expectNewForegroundTab];
+}
+
+- (void)openNewTabFromOriginPoint:(CGPoint)originPoint
+                     focusOmnibox:(BOOL)focusOmnibox {
+  [self.mainController.currentBVC openNewTabFromOriginPoint:originPoint
+                                               focusOmnibox:focusOmnibox];
+}
+
+- (ios::ChromeBrowserState*)currentBrowserState {
+  return self.mainController.interfaceProvider.currentInterface.browserState;
+}
+
+- (TabModel*)currentTabModel {
+  return self.mainController.interfaceProvider.currentInterface.bvc.tabModel;
+}
+
+// Asks the respective Snapshot helper to update the snapshot for the active
+// WebState.
+- (void)updateActiveWebStateSnapshot {
+  WebStateList* webStateList =
+      self.mainController.currentBVC.tabModel.webStateList;
+  if (webStateList) {
+    web::WebState* webState = webStateList->GetActiveWebState();
+    if (webState) {
+      SnapshotTabHelper::FromWebState(webState)->UpdateSnapshotWithCallback(
+          nil);
+    }
+  }
+}
+
+- (void)closeSettingsAnimated:(BOOL)animated
+                   completion:(ProceduralBlock)completion {
+  if (self.mainController.settingsNavigationController) {
+    [self.mainController.settingsNavigationController cleanUpSettings];
+    UIViewController* presentingViewController =
+        [self.mainController
+                .settingsNavigationController presentingViewController];
+    // If presentingViewController is nil it means the VC was already dismissed
+    // by some other action like swiping down.
+    DCHECK(presentingViewController);
+    [presentingViewController dismissViewControllerAnimated:animated
+                                                 completion:completion];
+    self.mainController.settingsNavigationController = nil;
+    return;
+  }
+  // |self.signinInteractionCoordinator| can also present settings, like
+  // the advanced sign-in settings navigation controller. If the settings has
+  // to be cloase, it is thus the responsibility of the main controller to
+  // dismiss the the advanced sign-in settings by dismssing the settings
+  // presented by |self.signinInteractionCoordinator|.
+  // To reproduce this case:
+  //  - open Bookmark view
+  //  - start sign-in
+  //  - tap on "Settings" to open the advanced sign-in settings
+  //  - tap on "Manage Your Google Account"
+  DCHECK(
+      self.mainController.signinInteractionCoordinator.isSettingsViewPresented);
+  [self.mainController.signinInteractionCoordinator
+      abortAndDismissSettingsViewAnimated:animated
+                               completion:completion];
+}
+
+// Checks the target BVC's current tab's URL. If this URL is chrome://newtab,
+// loads |urlLoadParams| in this tab. Otherwise, open |urlLoadParams| in a new
+// tab in the target BVC. |tabDisplayedCompletion| will be called on the new tab
+// (if not nil).
+- (void)openOrReuseTabInMode:(ApplicationMode)targetMode
+           withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
+         tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion {
+  BrowserViewController* targetBVC =
+      targetMode == ApplicationMode::NORMAL
+          ? self.mainController.interfaceProvider.mainInterface.bvc
+          : self.mainController.interfaceProvider.incognitoInterface.bvc;
+  web::WebState* currentWebState =
+      targetBVC.tabModel.webStateList->GetActiveWebState();
+
+  // Don't call loadWithParams for chrome://newtab when it's already loaded.
+  // Note that it's safe to use -GetVisibleURL here, as it doesn't matter if the
+  // NTP hasn't finished loading.
+  if (currentWebState && IsURLNtp(currentWebState->GetVisibleURL()) &&
+      IsURLNtp(urlLoadParams.web_params.url)) {
+    if (tabOpenedCompletion) {
+      tabOpenedCompletion();
+    }
+    return;
+  }
+
+  // With kBrowserContainerContainsNTP enabled paired with a restored NTP
+  // session, the NTP may appear committed when it is still loading.  For the
+  // time being, always load within a new tab when this feature is enabled.
+  // TODO(crbug.com/931284): Revert this change when fixed.
+  BOOL alwaysInsertNewTab =
+      base::FeatureList::IsEnabled(kBlockNewTabPagePendingLoad);
+  // If the current tab isn't an NTP, open a new tab.  Be sure to use
+  // -GetLastCommittedURL incase the NTP is still loading.
+  if (alwaysInsertNewTab ||
+      !(currentWebState && IsURLNtp(currentWebState->GetVisibleURL()))) {
+    [targetBVC appendTabAddedCompletion:tabOpenedCompletion];
+    UrlLoadParams newTabParams = urlLoadParams;
+    newTabParams.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
+    newTabParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
+    UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
+        ->Load(newTabParams);
+    return;
+  }
+
+  // Otherwise, load |urlLoadParams| in the current tab.
+  UrlLoadParams sameTabParams = urlLoadParams;
+  sameTabParams.disposition = WindowOpenDisposition::CURRENT_TAB;
+  UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
+      ->Load(sameTabParams);
+  if (tabOpenedCompletion) {
+    tabOpenedCompletion();
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/main/scene_controller_guts.h b/ios/chrome/browser/ui/main/scene_controller_guts.h
new file mode 100644
index 0000000..8f6791f
--- /dev/null
+++ b/ios/chrome/browser/ui/main/scene_controller_guts.h
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_
+#define IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/app/application_delegate/tab_opening.h"
+#import "ios/chrome/browser/procedural_block_types.h"
+#import "ios/chrome/browser/url_loading/url_loading_params.h"
+
+@protocol SceneControllerGuts
+
+- (void)closeSettingsAnimated:(BOOL)animated
+                   completion:(ProceduralBlock)completion;
+
+- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox;
+
+- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)tabOpeningTargetMode
+            withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
+                   completion:(ProceduralBlock)completion;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn
index 8e0f2a7..e5c3be4 100644
--- a/ios/chrome/browser/ui/omnibox/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -97,9 +97,7 @@
     "omnibox_icon_type.h",
     "omnibox_icon_type.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("omnibox_internal") {
@@ -243,9 +241,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "omnibox_app_interface.h",
-  ]
+  sources = [ "omnibox_app_interface.h" ]
 }
 
 source_set("eg2_tests") {
@@ -255,9 +251,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "omnibox_egtest.mm",
-  ]
+  sources = [ "omnibox_egtest.mm" ]
   deps = [
     ":test_support+eg2",
     "//ios/chrome/app/strings:ios_strings_grit",
@@ -274,9 +268,7 @@
 source_set("eg_tests") {
   defines = [ "CHROME_EARL_GREY_1" ]
   testonly = true
-  sources = [
-    "omnibox_egtest.mm",
-  ]
+  sources = [ "omnibox_egtest.mm" ]
   deps = [
     ":omnibox",
     ":omnibox_internal",
@@ -329,21 +321,15 @@
 bundle_data("resources_unit_tests") {
   visibility = [ ":unit_tests" ]
   testonly = true
-  sources = [
-    "//ios/chrome/test/data/omnibox/selected_ranges.txt",
-  ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "ios/chrome/test/data/omnibox/{{source_file_part}}",
-  ]
+  sources = [ "//ios/chrome/test/data/omnibox/selected_ranges.txt" ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "ios/chrome/test/data/omnibox/{{source_file_part}}" ]
 }
 
 source_set("perf_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "omnibox_perftest.mm",
-  ]
+  sources = [ "omnibox_perftest.mm" ]
   deps = [
     ":omnibox_internal",
     "//base",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
index fdfab48..1edee943 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -307,7 +307,8 @@
 
 // Copies and pastes a URL, then performs an undo of the paste, and attempts to
 // perform a second undo.
-- (void)testCopyPasteUndo {
+// TODO(crbug.com/1041478): This test is flaky.
+- (void)FLAKY_testCopyPasteUndo {
   [self openPage1];
 
   [ChromeEarlGreyUI focusOmnibox];
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index d68d3bb..9ab2a46 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -256,7 +256,6 @@
     "payment_request_egtest_base.mm",
     "payment_request_journey_logger_egtest.mm",
     "payment_request_misc_egtest.mm",
-    "payment_request_modifiers_egtest.mm",
     "payment_request_payment_app_egtest.mm",
     "payment_request_payment_method_identifier_egtest.mm",
     "payment_request_payment_response_egtest.mm",
diff --git a/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm
deleted file mode 100644
index 96f3b9b..0000000
--- a/ios/chrome/browser/ui/payments/payment_request_modifiers_egtest.mm
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <EarlGrey/EarlGrey.h>
-
-#include "base/strings/sys_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
-#include "components/autofill/core/browser/autofill_test_utils.h"
-#include "components/payments/core/features.h"
-#import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h"
-#import "ios/chrome/test/app/chrome_test_util.h"
-#import "ios/chrome/test/app/tab_test_util.h"
-#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_matchers.h"
-#import "ios/web/public/test/http_server/http_server.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-constexpr auto CREDIT = ::autofill::CreditCard::CardType::CARD_TYPE_CREDIT;
-
-using chrome_test_util::GetCurrentWebState;
-
-// URLs of the test pages.
-const char kModifiersPage[] =
-    "https://components/test/data/payments/"
-    "payment_request_bobpay_and_basic_card_with_modifiers_test.html";
-
-// Matcher for the PriceCell.
-id<GREYMatcher> PriceCellMatcher(NSString* accessibilityLabel, BOOL is_button) {
-  return grey_allOf(
-      grey_accessibilityLabel(accessibilityLabel),
-      is_button ? grey_accessibilityTrait(UIAccessibilityTraitButton)
-                : grey_not(grey_accessibilityTrait(UIAccessibilityTraitButton)),
-      grey_sufficientlyVisible(), nil);
-}
-
-// Matcher for the PaymentMethodCell.
-id<GREYMatcher> PaymentMethodCellMatcher(
-    const autofill::CreditCard& credit_card) {
-  return chrome_test_util::ButtonWithAccessibilityLabel([NSString
-      stringWithFormat:@"%@, %@",
-                       base::SysUTF16ToNSString(
-                           credit_card.NetworkAndLastFourDigits()),
-                       base::SysUTF16ToNSString(credit_card.GetRawInfo(
-                           autofill::CREDIT_CARD_NAME_FULL))]);
-}
-
-}  // namepsace
-
-// Tests for the PaymentDetailsModifier.
-@interface PaymentRequestModifiersEGTest : PaymentRequestEGTestBase
-
-@end
-
-@implementation PaymentRequestModifiersEGTest {
-  autofill::AutofillProfile _profile;
-  autofill::CreditCard _localCard;
-  autofill::CreditCard _serverCard;
-}
-
-- (void)setUp {
-  [super setUp];
-  if (![ChromeEarlGrey isWebPaymentsModifiersEnabled]) {
-    // payments::features::kWebPaymentsModifiers feature is not enabled,
-    // You have to pass --enable-features=WebPaymentsModifiers command line
-    // argument in order to run this test.
-    DCHECK(false);
-  }
-
-  [self addProfile];
-}
-
-#pragma mark - Helper methods
-
-- (void)addProfile {
-  _profile = autofill::test::GetFullProfile();
-  [self addAutofillProfile:_profile];
-}
-
-- (void)addLocalCard {
-  _localCard = autofill::test::GetCreditCard();  // Visa.
-  _localCard.set_billing_address_id(_profile.guid());
-  [self addCreditCard:_localCard];
-}
-
-- (void)addServerCardWithType:(autofill::CreditCard::CardType)cardType {
-  _serverCard = autofill::test::GetMaskedServerCard();  // Mastercard.
-  _serverCard.set_card_type(cardType);
-  _serverCard.set_billing_address_id(_profile.guid());
-  [self addServerCreditCard:_serverCard];
-}
-
-#pragma mark - Tests
-
-// Tests that no modifier should be applied if there is no selected instrument.
-- (void)testNoModifierAppliedNoSelectedInstrument {
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"buy"];
-
-  // Verify there's no line item.
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $5.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that modifiers should be applied if there is a selected local credit
-// card instrument and the modifiers are for basic-card.
-- (void)testModifierAppliedSelectedLocalInstrumentWithoutTypeOrNetwork {
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addLocalCard];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"buy"];
-
-  // Verify there's a selected payment method.
-  [[EarlGrey selectElementWithMatcher:PaymentMethodCellMatcher(_localCard)]
-      assertWithMatcher:grey_notNil()];
-
-  // Verify there is one line item for the discount and one for the total.
-  [[EarlGrey
-      selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", YES)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", NO)]
-      assertWithMatcher:grey_notNil()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(
-                                          @"basic-card discount, -$1.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that modifiers should be applied if there is a selected server credit
-// card instrument and the modifiers are for basic-card.
-- (void)testModifierAppliedSelectedServerInstrumentWithoutTypeOrNetwork {
-  base::test::ScopedFeatureList featureList;
-  featureList.InitAndEnableFeature(
-      payments::features::kReturnGooglePayInBasicCard);
-
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addServerCardWithType:CREDIT];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"buy"];
-
-  // Verify there's a selected payment method.
-  [[EarlGrey selectElementWithMatcher:PaymentMethodCellMatcher(_serverCard)]
-      assertWithMatcher:grey_notNil()];
-
-  // Verify there is one line item for the discount and one for the total.
-  [[EarlGrey
-      selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", YES)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", NO)]
-      assertWithMatcher:grey_notNil()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(
-                                          @"basic-card discount, -$1.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that modifiers should be applied if there is a selected credit card
-// instrument and the modifiers are for basic-card of matching type.
-- (void)testModifierAppliedSelectedInstrumentWithMatchingSupportedType {
-  base::test::ScopedFeatureList featureList;
-  featureList.InitAndEnableFeature(
-      payments::features::kReturnGooglePayInBasicCard);
-
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addServerCardWithType:CREDIT];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"credit_supported_type"];
-
-  // Verify there's a selected payment method.
-  [[EarlGrey selectElementWithMatcher:PaymentMethodCellMatcher(_serverCard)]
-      assertWithMatcher:grey_notNil()];
-
-  // Verify there is one line item for the discount and one for the total.
-  [[EarlGrey
-      selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", YES)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", NO)]
-      assertWithMatcher:grey_notNil()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(
-                                          @"basic-card discount, -$1.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that no modifier should be applied if there is a selected credit card
-// instrument but the modifiers are for basic-card of mismatching type.
-- (void)testNoModifierAppliedSelectedInstrumentWithMismatchingSupportedType {
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addServerCardWithType:CREDIT];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"debit_supported_type"];
-
-  // Verify there's no line item.
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $5.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that modifiers should be applied if there is a selected credit card
-// instrument and the modifiers are for basic-card of a matching network.
-- (void)testModifierAppliedSelectedInstrumentWithMatchingSupportedNetwork {
-  base::test::ScopedFeatureList featureList;
-  featureList.InitAndEnableFeature(
-      payments::features::kReturnGooglePayInBasicCard);
-
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addServerCardWithType:CREDIT];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"mastercard_any_supported_type"];
-
-  // Verify there's a selected payment method.
-  [[EarlGrey selectElementWithMatcher:PaymentMethodCellMatcher(_serverCard)]
-      assertWithMatcher:grey_notNil()];
-
-  // Verify there is one line item for the discount and one for the total.
-  [[EarlGrey
-      selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", YES)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", NO)]
-      assertWithMatcher:grey_notNil()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(
-                                          @"basic-card discount, -$1.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that no modifier should be applied if there is a selected credit card
-// instrument but the modifiers are for basic-card of mismatching network.
-- (void)testNoModifierAppliedSelectedInstrumentWithMismatchingSupportedNetwork {
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addLocalCard];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"mastercard_any_supported_type"];
-
-  // Verify there's a selected payment method.
-  [[EarlGrey selectElementWithMatcher:PaymentMethodCellMatcher(_localCard)]
-      assertWithMatcher:grey_notNil()];
-
-  // Verify there's no line item.
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $5.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests that modifiers should be applied if there is a selected credit card
-// instrument and the modifiers are for basic-card of a matching network and
-// type.
-- (void)testModifierAppliedSelectedInstrumentWithMatchingNetworkAndType {
-  base::test::ScopedFeatureList featureList;
-  featureList.InitAndEnableFeature(
-      payments::features::kReturnGooglePayInBasicCard);
-
-  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kModifiersPage)];
-
-  [self addServerCardWithType:CREDIT];
-
-  [ChromeEarlGrey tapWebStateElementWithID:@"mastercard_supported_network"];
-
-  // Verify there's a selected payment method.
-  [[EarlGrey selectElementWithMatcher:PaymentMethodCellMatcher(_serverCard)]
-      assertWithMatcher:grey_notNil()];
-
-  // Verify there is one line item for the discount and one for the total.
-  [[EarlGrey
-      selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", YES)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(@"Total, USD $4.00", NO)]
-      assertWithMatcher:grey_notNil()];
-  [[EarlGrey selectElementWithMatcher:PriceCellMatcher(
-                                          @"basic-card discount, -$1.00", NO)]
-      assertWithMatcher:grey_notNil()];
-}
-
-@end
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 6bfab65..4e3c54b 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -37,7 +37,9 @@
     "settings_root_table_constants.h",
     "settings_root_table_constants.mm",
   ]
-  deps = [ "//base" ]
+  deps = [
+    "//base",
+  ]
 }
 
 source_set("settings") {
@@ -110,7 +112,6 @@
     "//components/keyed_service/core",
     "//components/password_manager/core/browser",
     "//components/password_manager/core/common",
-    "//components/payments/core",
     "//components/prefs/ios",
     "//components/resources",
     "//components/search_engines",
@@ -152,7 +153,6 @@
     "//ios/chrome/browser/ui/icons",
     "//ios/chrome/browser/ui/keyboard",
     "//ios/chrome/browser/ui/list_model",
-    "//ios/chrome/browser/ui/payments/cells",
     "//ios/chrome/browser/ui/settings/autofill",
     "//ios/chrome/browser/ui/settings/cells",
     "//ios/chrome/browser/ui/settings/cells:public",
@@ -276,7 +276,6 @@
     "//components/language/core/browser",
     "//components/password_manager/core/browser:test_support",
     "//components/password_manager/core/common",
-    "//components/payments/core",
     "//components/pref_registry",
     "//components/prefs:test_support",
     "//components/search_engines",
@@ -445,7 +444,9 @@
     "//ios/chrome/test/app:test_support",
     "//third_party/breakpad:client",
   ]
-  public_deps = [ "//components/content_settings/core/common" ]
+  public_deps = [
+    "//components/content_settings/core/common",
+  ]
 }
 
 source_set("eg_test_support+eg2") {
@@ -457,8 +458,12 @@
     "settings_app_interface.h",
     "signin_settings_app_interface.h",
   ]
-  public_deps = [ "//components/content_settings/core/common" ]
-  deps = [ "//base" ]
+  public_deps = [
+    "//components/content_settings/core/common",
+  ]
+  deps = [
+    "//base",
+  ]
 }
 
 source_set("eg2_tests") {
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
index 1a957720..a4e4294 100644
--- a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
@@ -7,7 +7,6 @@
 #include "base/logging.h"
 #import "base/mac/foundation_util.h"
 #include "components/handoff/pref_names_ios.h"
-#include "components/payments/core/payment_prefs.h"
 #import "components/prefs/ios/pref_observer_bridge.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
@@ -46,7 +45,6 @@
 
 typedef NS_ENUM(NSInteger, ItemType) {
   ItemTypeOtherDevicesHandoff = kItemTypeEnumZero,
-  ItemTypeWebServicesPaymentSwitch,
   ItemTypeClearBrowsingDataClear,
   // Footer to suggest the user to open Sync and Google services settings.
   ItemTypeClearBrowsingDataFooter,
@@ -120,8 +118,6 @@
   [model addSectionWithIdentifier:SectionIdentifierWebServices];
   [model addItem:[self handoffDetailItem]
       toSectionWithIdentifier:SectionIdentifierWebServices];
-  [model addItem:[self canMakePaymentItem]
-      toSectionWithIdentifier:SectionIdentifierWebServices];
 
   // Clear Browsing Section
   [model addSectionWithIdentifier:SectionIdentifierClearBrowsingData];
@@ -165,25 +161,6 @@
                        detailText:nil];
 }
 
-- (TableViewItem*)canMakePaymentItem {
-  SettingsSwitchItem* canMakePaymentItem = [[SettingsSwitchItem alloc]
-      initWithType:ItemTypeWebServicesPaymentSwitch];
-  canMakePaymentItem.text =
-      l10n_util::GetNSString(IDS_SETTINGS_CAN_MAKE_PAYMENT_TOGGLE_LABEL);
-  canMakePaymentItem.on = [self isCanMakePaymentEnabled];
-  return canMakePaymentItem;
-}
-
-- (BOOL)isCanMakePaymentEnabled {
-  return _browserState->GetPrefs()->GetBoolean(
-      payments::kCanMakePaymentEnabled);
-}
-
-- (void)setCanMakePaymentEnabled:(BOOL)isEnabled {
-  _browserState->GetPrefs()->SetBoolean(payments::kCanMakePaymentEnabled,
-                                        isEnabled);
-}
-
 - (TableViewDetailIconItem*)detailItemWithType:(NSInteger)type
                                        titleId:(NSInteger)titleId
                                     detailText:(NSString*)detailText {
@@ -197,25 +174,6 @@
   return detailItem;
 }
 
-#pragma mark - UITableViewDataSource
-
-- (UITableViewCell*)tableView:(UITableView*)tableView
-        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
-  UITableViewCell* cell =
-      [super tableView:tableView cellForRowAtIndexPath:indexPath];
-
-  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
-
-  if (itemType == ItemTypeWebServicesPaymentSwitch) {
-    SettingsSwitchCell* switchCell =
-        base::mac::ObjCCastStrict<SettingsSwitchCell>(cell);
-    [switchCell.switchView addTarget:self
-                              action:@selector(canMakePaymentSwitchChanged:)
-                    forControlEvents:UIControlEventValueChanged];
-  }
-  return cell;
-}
-
 #pragma mark - UITableViewDelegate
 
 - (UIView*)tableView:(UITableView*)tableView
@@ -251,7 +209,6 @@
       controller = clearBrowsingDataViewController;
       break;
     }
-    case ItemTypeWebServicesPaymentSwitch:
     default:
       break;
   }
@@ -279,25 +236,6 @@
   [navigationController closeSettings];
 }
 
-#pragma mark - Actions
-
-- (void)canMakePaymentSwitchChanged:(UISwitch*)sender {
-  NSIndexPath* switchPath =
-      [self.tableViewModel indexPathForItemType:ItemTypeWebServicesPaymentSwitch
-                              sectionIdentifier:SectionIdentifierWebServices];
-
-  SettingsSwitchItem* switchItem =
-      base::mac::ObjCCastStrict<SettingsSwitchItem>(
-          [self.tableViewModel itemAtIndexPath:switchPath]);
-  SettingsSwitchCell* switchCell =
-      base::mac::ObjCCastStrict<SettingsSwitchCell>(
-          [self.tableView cellForRowAtIndexPath:switchPath]);
-
-  DCHECK_EQ(switchCell.switchView, sender);
-  switchItem.on = sender.isOn;
-  [self setCanMakePaymentEnabled:sender.isOn];
-}
-
 #pragma mark - PrefObserverDelegate
 
 - (void)onPreferenceChanged:(const std::string&)preferenceName {
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm
index 32b1fbd..3e30157 100644
--- a/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm
@@ -9,7 +9,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/handoff/pref_names_ios.h"
-#include "components/payments/core/payment_prefs.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync_preferences/pref_service_mock_factory.h"
@@ -43,10 +42,6 @@
     test_cbs_builder.SetPrefService(CreatePrefService());
     chrome_browser_state_ = test_cbs_builder.Build();
 
-    // Toggle off payments::kCanMakePaymentEnabled.
-    chrome_browser_state_->GetPrefs()->SetBoolean(
-        payments::kCanMakePaymentEnabled, false);
-
     NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
     initialValueForSpdyProxyEnabled_ =
         [[defaults valueForKey:kSpdyProxyEnabled] copy];
@@ -93,7 +88,7 @@
   EXPECT_EQ(2, NumberOfSections());
 
   // Sections[0].
-  EXPECT_EQ(2, NumberOfItemsInSection(0));
+  EXPECT_EQ(1, NumberOfItemsInSection(0));
   NSString* handoffSubtitle = chrome_browser_state_->GetPrefs()->GetBoolean(
                                   prefs::kIosHandoffToOtherDevices)
                                   ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
@@ -101,9 +96,6 @@
   CheckTextCellTextAndDetailText(
       l10n_util::GetNSString(IDS_IOS_OPTIONS_ENABLE_HANDOFF_TO_OTHER_DEVICES),
       handoffSubtitle, 0, 0);
-  CheckSwitchCellStateAndText(
-      NO, l10n_util::GetNSString(IDS_SETTINGS_CAN_MAKE_PAYMENT_TOGGLE_LABEL), 0,
-      1);
 
   // Sections[1].
   EXPECT_EQ(1, NumberOfItemsInSection(1));
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn
index 45308d3..921e5b02 100644
--- a/ios/chrome/browser/ui/tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -21,9 +21,7 @@
     "target_frame_cache.h",
     "target_frame_cache.mm",
   ]
-  public_deps = [
-    "//ios/chrome/browser/tabs",
-  ]
+  public_deps = [ "//ios/chrome/browser/tabs" ]
   deps = [
     "resources:open_new_tab_background",
     "resources:tabstrip_background_tab",
@@ -92,9 +90,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "tab_strip_controller_unittest.mm",
-  ]
+  sources = [ "tab_strip_controller_unittest.mm" ]
   deps = [
     ":tabs",
     "//base",
@@ -116,9 +112,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "tab_strip_egtest.mm",
-  ]
+  sources = [ "tab_strip_egtest.mm" ]
   deps = [
     ":tabs",
     "//ios/chrome/app/strings",
@@ -139,9 +133,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "tab_strip_egtest.mm",
-  ]
+  sources = [ "tab_strip_egtest.mm" ]
   deps = [
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
     "//ios/testing/earl_grey:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/tabs/resources/BUILD.gn b/ios/chrome/browser/ui/tabs/resources/BUILD.gn
index 281c64a6..1188d0ea 100644
--- a/ios/chrome/browser/ui/tabs/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/resources/BUILD.gn
@@ -82,13 +82,10 @@
 }
 
 colorset("tabstrip_inactive_tab_close_button_color") {
-  sources = [
-    "tabstrip_inactive_tab_close_button_color.colorset/Contents.json",
-  ]
+  sources =
+      [ "tabstrip_inactive_tab_close_button_color.colorset/Contents.json" ]
 }
 
 colorset("tabstrip_inactive_tab_text_color") {
-  sources = [
-    "tabstrip_inactive_tab_text_color.colorset/Contents.json",
-  ]
+  sources = [ "tabstrip_inactive_tab_text_color.colorset/Contents.json" ]
 }
diff --git a/ios/chrome/browser/ui/translate/BUILD.gn b/ios/chrome/browser/ui/translate/BUILD.gn
index bb3ed286..673bb1e 100644
--- a/ios/chrome/browser/ui/translate/BUILD.gn
+++ b/ios/chrome/browser/ui/translate/BUILD.gn
@@ -94,9 +94,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "translate_infobar_mediator_unittest.mm",
-  ]
+  sources = [ "translate_infobar_mediator_unittest.mm" ]
   deps = [
     ":legacy_translate",
     "//components/language/ios/browser",
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index 55c5fba..feb86c3 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -182,8 +182,6 @@
     [scripts addObject:GetPageScript(@"credential_manager")];
   }
 
-  [scripts addObject:GetPageScript(@"payment_request")];
-
   return [scripts componentsJoinedByString:@";"];
 }
 
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm
index 12ea75e1..7700e3c 100644
--- a/ios/chrome/browser/web/chrome_web_client_unittest.mm
+++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -179,20 +179,6 @@
                              web_view, @"typeof navigator.credentials"));
 }
 
-// Tests that ChromeWebClient provides payment request script for WKWebView.
-TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptPaymentRequest) {
-  // Chrome scripts rely on __gCrWeb object presence.
-  WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
-  web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
-
-  web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
-  NSString* script =
-      web_client.Get()->GetDocumentStartScriptForMainFrame(browser_state());
-  web::test::ExecuteJavaScript(web_view, script);
-  EXPECT_NSEQ(@"function", web::test::ExecuteJavaScript(
-                               web_view, @"typeof window.PaymentRequest"));
-}
-
 // Tests PrepareErrorPage wth non-post, not Off The Record error.
 TEST_F(ChromeWebClientTest, PrepareErrorPageNonPostNonOtr) {
   ChromeWebClient web_client;
diff --git a/ios/chrome/browser/web_state_list/web_usage_enabler/BUILD.gn b/ios/chrome/browser/web_state_list/web_usage_enabler/BUILD.gn
index d4bd4f10..1aa0e5e 100644
--- a/ios/chrome/browser/web_state_list/web_usage_enabler/BUILD.gn
+++ b/ios/chrome/browser/web_state_list/web_usage_enabler/BUILD.gn
@@ -41,9 +41,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "web_state_list_web_usage_enabler_impl_unittest.mm",
-  ]
+  sources = [ "web_state_list_web_usage_enabler_impl_unittest.mm" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 
diff --git a/ios/chrome/common/BUILD.gn b/ios/chrome/common/BUILD.gn
index 765e2f7..64d82dda 100644
--- a/ios/chrome/common/BUILD.gn
+++ b/ios/chrome/common/BUILD.gn
@@ -26,9 +26,7 @@
     "//url",
   ]
 
-  public_deps = [
-    ":timing",
-  ]
+  public_deps = [ ":timing" ]
 
   libs = [ "QuartzCore.framework" ]
 }
@@ -41,9 +39,7 @@
 
   libs = [ "UIKit.framework" ]
 
-  public_deps = [
-    ":timing",
-  ]
+  public_deps = [ ":timing" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 }
@@ -88,9 +84,7 @@
 source_set("noarc_unit_tests") {
   visibility = [ ":unit_tests" ]
   testonly = true
-  sources = [
-    "noarc_block_unittest.mm",
-  ]
+  sources = [ "noarc_block_unittest.mm" ]
   deps = [
     ":common",
     "//base",
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 08df728..4aa2a5b 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -38,7 +38,9 @@
     "testing_application_context.mm",
   ]
 
-  public_deps = [ ":block_cleanup_test" ]
+  public_deps = [
+    ":block_cleanup_test",
+  ]
 
   deps = [
     "//base",
@@ -117,7 +119,9 @@
 
 source_set("run_all_unittests") {
   testonly = true
-  sources = [ "run_all_unittests.cc" ]
+  sources = [
+    "run_all_unittests.cc",
+  ]
   deps = [
     ":test_support",
     "//base",
@@ -204,7 +208,6 @@
     "//ios/chrome/browser/overlays:unit_tests",
     "//ios/chrome/browser/overscroll_actions:unit_tests",
     "//ios/chrome/browser/passwords:unit_tests",
-    "//ios/chrome/browser/payments:unit_tests",
     "//ios/chrome/browser/prerender:unit_tests",
     "//ios/chrome/browser/reading_list:unit_tests",
     "//ios/chrome/browser/safe_mode:unit_tests",
@@ -270,8 +273,6 @@
     "//ios/chrome/browser/ui/overlays/web_content_area/app_launcher:unit_tests",
     "//ios/chrome/browser/ui/overlays/web_content_area/http_auth_dialogs:unit_tests",
     "//ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs:unit_tests",
-    "//ios/chrome/browser/ui/payments:unit_tests",
-    "//ios/chrome/browser/ui/payments/cells:unit_tests",
     "//ios/chrome/browser/ui/popup_menu:unit_tests",
     "//ios/chrome/browser/ui/presenters:unit_tests",
     "//ios/chrome/browser/ui/promos:unit_tests",
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index 4f4fd94..f6c31f4 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -37,7 +37,6 @@
     "//ios/chrome/browser/ui/autofill:eg_tests",
     "//ios/chrome/browser/ui/autofill/manual_fill:eg_tests",
     "//ios/chrome/browser/ui/content_suggestions:eg_tests",
-    "//ios/chrome/browser/ui/payments:eg_tests",
   ]
 }
 
@@ -223,7 +222,6 @@
     "//components/autofill/core/browser",
     "//components/browsing_data/core",
     "//components/content_settings/core/browser",
-    "//components/payments/core:core",
     "//components/strings",
     "//components/sync/base",
     "//components/translate/core/browser",
@@ -254,7 +252,6 @@
     "//ios/chrome/browser/ui/history:history_ui",
     "//ios/chrome/browser/ui/location_bar:location_bar",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
-    "//ios/chrome/browser/ui/payments:payments_ui",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/qr_scanner:test_support",
     "//ios/chrome/browser/ui/recent_tabs:recent_tabs_ui_constants",
@@ -360,7 +357,6 @@
     "//components/autofill/core/browser",
     "//components/browsing_data/core",
     "//components/content_settings/core/browser",
-    "//components/payments/core:core",
     "//components/strings",
     "//components/sync/base",
     "//components/translate/core/browser",
@@ -405,7 +401,6 @@
     "//ios/chrome/browser/ui/material_components",
     "//ios/chrome/browser/ui/omnibox:app_support+eg2",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
-    "//ios/chrome/browser/ui/payments:payments_ui",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/qr_scanner:eg_app_support+eg2",
     "//ios/chrome/browser/ui/reading_list:eg_app_support+eg2",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h
index 099f02b..b2575bf 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey.h
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -450,9 +450,6 @@
 // Returns YES if UKM feature is enabled.
 - (BOOL)isUKMEnabled WARN_UNUSED_RESULT;
 
-// Returns YES if WebPaymentsModifiers feature is enabled.
-- (BOOL)isWebPaymentsModifiersEnabled WARN_UNUSED_RESULT;
-
 // Returns YES if CreditCardScanner feature is enabled.
 - (BOOL)isCreditCardScannerEnabled WARN_UNUSED_RESULT;
 
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
index eae4c9b..1edf38971 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -788,10 +788,6 @@
   return [ChromeEarlGreyAppInterface isUKMEnabled];
 }
 
-- (BOOL)isWebPaymentsModifiersEnabled {
-  return [ChromeEarlGreyAppInterface isWebPaymentsModifiersEnabled];
-}
-
 - (BOOL)isCreditCardScannerEnabled {
   return [ChromeEarlGreyAppInterface isCreditCardScannerEnabled];
 }
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
index ccce1cb..b8dde4b 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
@@ -354,9 +354,6 @@
 // Returns YES if UKM feature is enabled.
 + (BOOL)isUKMEnabled WARN_UNUSED_RESULT;
 
-// Returns YES if WebPaymentsModifiers feature is enabled.
-+ (BOOL)isWebPaymentsModifiersEnabled WARN_UNUSED_RESULT;
-
 // Returns YES if CreditCardScanner feature is enabled.
 + (BOOL)isCreditCardScannerEnabled WARN_UNUSED_RESULT;
 
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
index 81396ca..f208cdf3 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -10,7 +10,6 @@
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
-#import "components/payments/core/features.h"
 #include "components/prefs/pref_service.h"
 #import "components/ukm/ios/features.h"
 #import "ios/chrome/app/main_controller.h"
@@ -621,11 +620,6 @@
   return base::FeatureList::IsEnabled(ukm::kUkmFeature);
 }
 
-+ (BOOL)isWebPaymentsModifiersEnabled {
-  return base::FeatureList::IsEnabled(
-      payments::features::kWebPaymentsModifiers);
-}
-
 + (BOOL)isCreditCardScannerEnabled {
   return base::FeatureList::IsEnabled(kCreditCardScanner);
 }
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
index d8357ef..aae1d6d3 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -26,10 +26,6 @@
 #import "ios/chrome/browser/ui/history/history_ui_constants.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_steady_view.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
-#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h"
-#import "ios/chrome/browser/ui/payments/payment_request_error_view_controller.h"
-#import "ios/chrome/browser/ui/payments/payment_request_picker_view_controller.h"
-#import "ios/chrome/browser/ui/payments/payment_request_view_controller.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h"
 #import "ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_view_controller.h"
@@ -568,13 +564,14 @@
       buttonWithAccessibilityLabelID:(IDS_IOS_PASSWORDS)];
 }
 
+// TODO(crbug.com/1021752): Remove this stub.
 + (id<GREYMatcher>)paymentRequestView {
-  return grey_accessibilityID(kPaymentRequestCollectionViewID);
+  return nil;
 }
 
-// Returns matcher for the error confirmation view for payment request.
+// TODO(crbug.com/1021752): Remove this stub.
 + (id<GREYMatcher>)paymentRequestErrorView {
-  return grey_accessibilityID(kPaymentRequestErrorCollectionViewID);
+  return nil;
 }
 
 + (id<GREYMatcher>)voiceSearchButton {
@@ -634,16 +631,19 @@
   return grey_accessibilityID(kContentSuggestionsCollectionIdentifier);
 }
 
+// TODO(crbug.com/1021752): Remove this stub.
 + (id<GREYMatcher>)warningMessageView {
-  return grey_accessibilityID(kWarningMessageAccessibilityID);
+  return nil;
 }
 
+// TODO(crbug.com/1021752): Remove this stub.
 + (id<GREYMatcher>)paymentRequestPickerRow {
-  return grey_accessibilityID(kPaymentRequestPickerRowAccessibilityID);
+  return nil;
 }
 
+// TODO(crbug.com/1021752): Remove this stub.
 + (id<GREYMatcher>)paymentRequestPickerSearchBar {
-  return grey_accessibilityID(kPaymentRequestPickerSearchBarAccessibilityID);
+  return nil;
 }
 
 + (id<GREYMatcher>)readingListMenuButton {
diff --git a/ios/net/BUILD.gn b/ios/net/BUILD.gn
index f8f3f1b..a09c0bb 100644
--- a/ios/net/BUILD.gn
+++ b/ios/net/BUILD.gn
@@ -15,9 +15,7 @@
 
 group("all_tests") {
   testonly = true
-  deps = [
-    ":ios_net_unittests",
-  ]
+  deps = [ ":ios_net_unittests" ]
 }
 
 source_set("net") {
diff --git a/ios/public/provider/chrome/browser/distribution/BUILD.gn b/ios/public/provider/chrome/browser/distribution/BUILD.gn
index e9af459..61c4e30f 100644
--- a/ios/public/provider/chrome/browser/distribution/BUILD.gn
+++ b/ios/public/provider/chrome/browser/distribution/BUILD.gn
@@ -8,9 +8,7 @@
     "app_distribution_provider.h",
     "app_distribution_provider.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("test_support") {
diff --git a/ios/public/provider/chrome/browser/images/BUILD.gn b/ios/public/provider/chrome/browser/images/BUILD.gn
index d5dd1c2..4d88b751 100644
--- a/ios/public/provider/chrome/browser/images/BUILD.gn
+++ b/ios/public/provider/chrome/browser/images/BUILD.gn
@@ -23,7 +23,5 @@
     "test_branded_image_provider.h",
     "test_branded_image_provider.mm",
   ]
-  deps = [
-    ":images",
-  ]
+  deps = [ ":images" ]
 }
diff --git a/ios/public/provider/chrome/browser/mailto/BUILD.gn b/ios/public/provider/chrome/browser/mailto/BUILD.gn
index a3a4775..12b2870 100644
--- a/ios/public/provider/chrome/browser/mailto/BUILD.gn
+++ b/ios/public/provider/chrome/browser/mailto/BUILD.gn
@@ -8,9 +8,7 @@
     "mailto_handler_provider.h",
     "mailto_handler_provider.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("test_support") {
@@ -20,7 +18,5 @@
     "test_mailto_handler_provider.h",
     "test_mailto_handler_provider.mm",
   ]
-  deps = [
-    ":mailto",
-  ]
+  deps = [ ":mailto" ]
 }
diff --git a/ios/public/provider/chrome/browser/omaha/BUILD.gn b/ios/public/provider/chrome/browser/omaha/BUILD.gn
index 6dabf3e8..f5c6e3c 100644
--- a/ios/public/provider/chrome/browser/omaha/BUILD.gn
+++ b/ios/public/provider/chrome/browser/omaha/BUILD.gn
@@ -22,7 +22,5 @@
     "test_omaha_service_provider.h",
     "test_omaha_service_provider.mm",
   ]
-  deps = [
-    ":omaha",
-  ]
+  deps = [ ":omaha" ]
 }
diff --git a/ios/public/provider/chrome/browser/spotlight/BUILD.gn b/ios/public/provider/chrome/browser/spotlight/BUILD.gn
index b98eae4e..a25e9bb 100644
--- a/ios/public/provider/chrome/browser/spotlight/BUILD.gn
+++ b/ios/public/provider/chrome/browser/spotlight/BUILD.gn
@@ -8,9 +8,7 @@
     "spotlight_provider.h",
     "spotlight_provider.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   libs = [ "Foundation.framework" ]
 }
 
@@ -21,7 +19,5 @@
     "test_spotlight_provider.h",
     "test_spotlight_provider.mm",
   ]
-  deps = [
-    ":spotlight",
-  ]
+  deps = [ ":spotlight" ]
 }
diff --git a/ios/public/provider/chrome/browser/user_feedback/BUILD.gn b/ios/public/provider/chrome/browser/user_feedback/BUILD.gn
index 245a42ad..60b685f 100644
--- a/ios/public/provider/chrome/browser/user_feedback/BUILD.gn
+++ b/ios/public/provider/chrome/browser/user_feedback/BUILD.gn
@@ -8,9 +8,7 @@
     "user_feedback_provider.h",
     "user_feedback_provider.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("test_support") {
diff --git a/ios/public/provider/chrome/browser/voice/BUILD.gn b/ios/public/provider/chrome/browser/voice/BUILD.gn
index 217f919..cb3a8d3 100644
--- a/ios/public/provider/chrome/browser/voice/BUILD.gn
+++ b/ios/public/provider/chrome/browser/voice/BUILD.gn
@@ -16,9 +16,7 @@
     "voice_search_provider.h",
     "voice_search_provider.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("test_support") {
diff --git a/ios/showcase/BUILD.gn b/ios/showcase/BUILD.gn
index b7766ae..34a5088 100644
--- a/ios/showcase/BUILD.gn
+++ b/ios/showcase/BUILD.gn
@@ -101,7 +101,6 @@
     "//ios/showcase/content_suggestions:eg_tests",
     "//ios/showcase/core:eg_tests",
     "//ios/showcase/infobars:eg_tests",
-    "//ios/showcase/payments:eg_tests",
     "//ios/showcase/text_badge_view:eg_tests",
   ]
 
diff --git a/ios/third_party/earl_grey/BUILD.gn b/ios/third_party/earl_grey/BUILD.gn
index fcb0d76..5927d539 100644
--- a/ios/third_party/earl_grey/BUILD.gn
+++ b/ios/third_party/earl_grey/BUILD.gn
@@ -292,9 +292,7 @@
     "//ios/third_party/fishhook",
     "//ios/third_party/webkit",
   ]
-  public_deps = [
-    "//ios/third_party/ochamcrest:ochamcrest+link",
-  ]
+  public_deps = [ "//ios/third_party/ochamcrest:ochamcrest+link" ]
 
   libs = [
     "CoreData.framework",
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index a26131c5..768d86d 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -487,9 +487,7 @@
 
   copy("mdc_components_ios_public_headers") {
     sources = _mdc_public_headers
-    outputs = [
-      "$root_gen_dir/frameworks/material_components_ios/MaterialComponents/{{source_file_part}}",
-    ]
+    outputs = [ "$root_gen_dir/frameworks/material_components_ios/MaterialComponents/{{source_file_part}}" ]
     public_configs = [ ":mdc_components_ios_public_headers_config" ]
   }
 } else {
@@ -1505,9 +1503,7 @@
   # TODO(crbug.com/1017165): remove once MaterialComponents is always built
   # as a framework
   if (ios_third_party_material_components_built_as_framework) {
-    public_deps = [
-      ":material_components_ios_public_headers",
-    ]
+    public_deps = [ ":material_components_ios_public_headers" ]
   }
 
   if (ios_third_party_material_components_built_as_framework) {
@@ -1536,15 +1532,11 @@
 # as a framework
 if (!ios_third_party_material_components_built_as_framework) {
   group("material_components_ios+link") {
-    public_deps = [
-      ":material_components_ios",
-    ]
+    public_deps = [ ":material_components_ios" ]
   }
 
   group("material_components_ios+bundle") {
-    public_deps = [
-      ":material_components_ios",
-    ]
+    public_deps = [ ":material_components_ios" ]
   }
 }
 
@@ -1582,13 +1574,10 @@
   foreach(_locale, _component_locales) {
     bundle_data("${target_name}_${_locale}") {
       visibility = [ ":*" ]
-      sources = [
-        "$_resources_path/$_locale.lproj/$_component_name.strings",
-      ]
-      outputs = [
-        "{{bundle_resources_dir}}/" +
-            "$_component_name.bundle/Resources/$_locale/{{source_file_part}}",
-      ]
+      sources = [ "$_resources_path/$_locale.lproj/$_component_name.strings" ]
+      outputs =
+          [ "{{bundle_resources_dir}}/" +
+            "$_component_name.bundle/Resources/$_locale/{{source_file_part}}" ]
     }
   }
 
@@ -1661,10 +1650,8 @@
       "$_icon_path@2x.png",
       "$_icon_path@3x.png",
     ]
-    outputs = [
-      "{{bundle_resources_dir}}/MaterialIcons_$_icon_name.bundle/" +
-          "{{source_file_part}}",
-    ]
+    outputs = [ "{{bundle_resources_dir}}/MaterialIcons_$_icon_name.bundle/" +
+                "{{source_file_part}}" ]
   }
 }
 
@@ -1700,17 +1687,13 @@
     "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png",
     "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/MaterialIcons_ic_arrow_back.bundle/" +
-        "{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/MaterialIcons_ic_arrow_back.bundle/" +
+              "{{source_file_part}}" ]
 }
 
 group("material_components_icons") {
   visibility = [ ":*" ]
-  deps = [
-    ":material_component_ic_arrow_back_bundle",
-  ]
+  deps = [ ":material_component_ic_arrow_back_bundle" ]
   foreach(_icon_name, _icon_names) {
     deps += [ ":material_component_${_icon_name}_bundle" ]
   }
diff --git a/ios/web/public/thread/BUILD.gn b/ios/web/public/thread/BUILD.gn
index 2e4525a..51252b2 100644
--- a/ios/web/public/thread/BUILD.gn
+++ b/ios/web/public/thread/BUILD.gn
@@ -4,9 +4,7 @@
 
 source_set("thread") {
   configs += [ "//build/config/compiler:enable_arc" ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   sources = [
     "web_task_traits.h",
     "web_thread.h",
diff --git a/ios/web/shell/BUILD.gn b/ios/web/shell/BUILD.gn
index 431f28f5..a19b6fc 100644
--- a/ios/web/shell/BUILD.gn
+++ b/ios/web/shell/BUILD.gn
@@ -11,9 +11,7 @@
 ios_app_bundle("ios_web_shell") {
   info_plist = "Info.plist"
 
-  deps = [
-    ":shell",
-  ]
+  deps = [ ":shell" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 
@@ -28,15 +26,11 @@
     "toolbar_back@2x.png",
     "toolbar_forward@2x.png",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 }
 
 mojom("shell_interfaces") {
-  sources = [
-    "web_usage_controller.mojom",
-  ]
+  sources = [ "web_usage_controller.mojom" ]
 }
 
 source_set("shell") {
diff --git a/ios/web/shell/test/BUILD.gn b/ios/web/shell/test/BUILD.gn
index 6bf2fcd..05dfca7 100644
--- a/ios/web/shell/test/BUILD.gn
+++ b/ios/web/shell/test/BUILD.gn
@@ -64,9 +64,7 @@
     "//url",
   ]
 
-  public_deps = [
-    "//build/config/ios:xctest",
-  ]
+  public_deps = [ "//build/config/ios:xctest" ]
 
   sources = [
     "app/navigation_test_util.h",
diff --git a/media/audio/audio_system_test_util.cc b/media/audio/audio_system_test_util.cc
index 3e1c6e3d..b408239 100644
--- a/media/audio/audio_system_test_util.cc
+++ b/media/audio/audio_system_test_util.cc
@@ -71,7 +71,7 @@
     base::OnceClosure on_cb_received,
     const base::Optional<AudioParameters>& expected,
     const base::Optional<AudioParameters>& received) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_) << from_here;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_, from_here);
   if (expected) {
     EXPECT_TRUE(received) << from_here;
     EXPECT_EQ(expected->AsHumanReadableString(),
@@ -87,7 +87,7 @@
                                              base::OnceClosure on_cb_received,
                                              bool expected,
                                              bool result) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_) << from_here;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_, from_here);
   EXPECT_EQ(expected, result) << from_here;
   std::move(on_cb_received).Run();
 }
@@ -97,7 +97,7 @@
     base::OnceClosure on_cb_received,
     const AudioDeviceDescriptions& expected_descriptions,
     AudioDeviceDescriptions descriptions) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_) << from_here;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   EXPECT_EQ(expected_descriptions, descriptions);
   std::move(on_cb_received).Run();
 }
@@ -109,7 +109,7 @@
     const base::Optional<std::string>& expected_associated_device_id,
     const base::Optional<AudioParameters>& input,
     const base::Optional<std::string>& associated_device_id) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_) << from_here;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_, from_here);
   EXPECT_TRUE(!input || input->IsValid());
   if (expected_input) {
     EXPECT_TRUE(input) << from_here;
@@ -134,7 +134,7 @@
     base::OnceClosure on_cb_received,
     const base::Optional<std::string>& expected_id,
     const base::Optional<std::string>& result_id) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_) << from_here;
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_, from_here);
   EXPECT_TRUE(!result_id || !result_id->empty());
   if (expected_id) {
     EXPECT_TRUE(result_id) << from_here;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 78f067a6..d746ab1 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -114,12 +114,8 @@
 set_sources_assignment_filter([])
 
 source_set("constants") {
-  sources = [
-    "base/trace_constants.h",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "base/trace_constants.h" ]
+  deps = [ "//base" ]
 }
 
 component("net") {
@@ -765,7 +761,6 @@
       "http2/platform/impl/http2_logging_impl.h",
       "http2/platform/impl/http2_macros_impl.h",
       "http2/platform/impl/http2_optional_impl.h",
-      "http2/platform/impl/http2_reconstruct_object_impl.h",
       "http2/platform/impl/http2_string_impl.h",
       "http2/platform/impl/http2_string_utils_impl.h",
       "log/file_net_log_observer.cc",
@@ -876,7 +871,6 @@
       "quic/platform/impl/quic_hostname_utils_impl.cc",
       "quic/platform/impl/quic_hostname_utils_impl.h",
       "quic/platform/impl/quic_iovec_impl.h",
-      "quic/platform/impl/quic_logging_impl.h",
       "quic/platform/impl/quic_macros_impl.h",
       "quic/platform/impl/quic_map_util_impl.h",
       "quic/platform/impl/quic_mem_slice_impl.cc",
@@ -1038,7 +1032,6 @@
       "spdy/platform/impl/spdy_mem_slice_impl.cc",
       "spdy/platform/impl/spdy_mem_slice_impl.h",
       "spdy/platform/impl/spdy_ptr_util_impl.h",
-      "spdy/platform/impl/spdy_string_piece_impl.h",
       "spdy/platform/impl/spdy_string_utils_impl.cc",
       "spdy/platform/impl/spdy_string_utils_impl.h",
       "spdy/platform/impl/spdy_test_utils_prod_impl.h",
@@ -1084,6 +1077,10 @@
       "third_party/quiche/src/common/platform/api/quiche_string_piece.h",
       "third_party/quiche/src/common/platform/api/quiche_text_utils.h",
       "third_party/quiche/src/common/platform/api/quiche_unordered_containers.h",
+      "third_party/quiche/src/common/quiche_data_reader.cc",
+      "third_party/quiche/src/common/quiche_data_reader.h",
+      "third_party/quiche/src/common/quiche_data_writer.cc",
+      "third_party/quiche/src/common/quiche_data_writer.h",
       "third_party/quiche/src/common/simple_linked_hash_map.h",
       "third_party/quiche/src/http2/decoder/decode_buffer.cc",
       "third_party/quiche/src/http2/decoder/decode_buffer.h",
@@ -1177,7 +1174,6 @@
       "third_party/quiche/src/http2/platform/api/http2_logging.h",
       "third_party/quiche/src/http2/platform/api/http2_macros.h",
       "third_party/quiche/src/http2/platform/api/http2_optional.h",
-      "third_party/quiche/src/http2/platform/api/http2_reconstruct_object.h",
       "third_party/quiche/src/http2/platform/api/http2_string_utils.h",
       "third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc",
       "third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h",
@@ -1470,6 +1466,8 @@
       "third_party/quiche/src/quic/core/quic_data_reader.h",
       "third_party/quiche/src/quic/core/quic_data_writer.cc",
       "third_party/quiche/src/quic/core/quic_data_writer.h",
+      "third_party/quiche/src/quic/core/quic_datagram_queue.cc",
+      "third_party/quiche/src/quic/core/quic_datagram_queue.h",
       "third_party/quiche/src/quic/core/quic_flow_controller.cc",
       "third_party/quiche/src/quic/core/quic_flow_controller.h",
       "third_party/quiche/src/quic/core/quic_framer.cc",
@@ -1651,7 +1649,6 @@
       "third_party/quiche/src/spdy/platform/api/spdy_map_util.h",
       "third_party/quiche/src/spdy/platform/api/spdy_mem_slice.h",
       "third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h",
-      "third_party/quiche/src/spdy/platform/api/spdy_string_piece.h",
       "third_party/quiche/src/spdy/platform/api/spdy_string_utils.h",
       "url_request/redirect_info.cc",
       "url_request/redirect_info.h",
@@ -2234,9 +2231,7 @@
 # net_export.h has its own build target so that code (eg
 # net_nqe_proto) can use it without depending on the whole of //net.
 source_set("net_export_header") {
-  sources = [
-    "base/net_export.h",
-  ]
+  sources = [ "base/net_export.h" ]
 }
 
 # Private dependencies for the //net component and for any build targets (e.g.
@@ -2343,9 +2338,7 @@
 
 if (is_android) {
   java_cpp_enum("effective_connection_type_java") {
-    sources = [
-      "//net/nqe/effective_connection_type.h",
-    ]
+    sources = [ "//net/nqe/effective_connection_type.h" ]
   }
 }
 
@@ -2360,16 +2353,12 @@
 proto_library("net_nqe_proto") {
   visibility = [ ":net_public_deps" ]
 
-  sources = [
-    "nqe/proto/network_id_proto.proto",
-  ]
+  sources = [ "nqe/proto/network_id_proto.proto" ]
   cc_generator_options = "dllexport_decl=NET_EXPORT_PRIVATE:"
   cc_include = "net/base/net_export.h"
   component_build_force_source_set = true
 
-  deps = [
-    ":net_export_header",
-  ]
+  deps = [ ":net_export_header" ]
 
   defines = [ "NET_IMPLEMENTATION" ]
 
@@ -2388,9 +2377,7 @@
   cc_include = "net/base/net_export.h"
   component_build_force_source_set = true
 
-  deps = [
-    ":net_export_header",
-  ]
+  deps = [ ":net_export_header" ]
 
   defines = [ "NET_IMPLEMENTATION" ]
 
@@ -2407,9 +2394,7 @@
   cc_include = "net/base/net_export.h"
   component_build_force_source_set = true
 
-  deps = [
-    ":net_export_header",
-  ]
+  deps = [ ":net_export_header" ]
 
   defines = [ "NET_IMPLEMENTATION" ]
 
@@ -2445,9 +2430,7 @@
     "extras/preload_data/decoder.cc",
     "extras/preload_data/decoder.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 if (!is_ios) {
@@ -2697,10 +2680,8 @@
     "data/ssl/certificates/www.ahrn.com.pem",
     "data/ssl/certificates/x509_verify_results.chain.pem",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 static_library("test_support") {
@@ -2858,9 +2839,7 @@
 
   allow_circular_includes_from = [ "//net/dns:test_support" ]
 
-  data = [
-    "data/",
-  ]
+  data = [ "data/" ]
 
   if (is_mac) {
     libs = [ "Security.framework" ]
@@ -2968,9 +2947,7 @@
 
   executable("crash_cache") {
     testonly = true
-    sources = [
-      "tools/crash_cache/crash_cache.cc",
-    ]
+    sources = [ "tools/crash_cache/crash_cache.cc" ]
 
     deps = [
       ":net",
@@ -2982,9 +2959,7 @@
 
   executable("dns_fuzz_stub") {
     testonly = true
-    sources = [
-      "tools/dns_fuzz_stub/dns_fuzz_stub.cc",
-    ]
+    sources = [ "tools/dns_fuzz_stub/dns_fuzz_stub.cc" ]
 
     deps = [
       ":net",
@@ -2995,9 +2970,7 @@
 
   executable("hpack_example_generator") {
     testonly = true
-    sources = [
-      "spdy/fuzzing/hpack_example_generator.cc",
-    ]
+    sources = [ "spdy/fuzzing/hpack_example_generator.cc" ]
 
     deps = [
       ":net",
@@ -3009,9 +2982,7 @@
 
   executable("net_watcher") {
     testonly = true
-    sources = [
-      "tools/net_watcher/net_watcher.cc",
-    ]
+    sources = [ "tools/net_watcher/net_watcher.cc" ]
     deps = [
       ":net",
       "//base",
@@ -3021,9 +2992,7 @@
 
   executable("run_testserver") {
     testonly = true
-    sources = [
-      "tools/testserver/run_testserver.cc",
-    ]
+    sources = [ "tools/testserver/run_testserver.cc" ]
     deps = [
       ":test_support",
       "//base",
@@ -3035,9 +3004,7 @@
 
   executable("stress_cache") {
     testonly = true
-    sources = [
-      "tools/stress_cache/stress_cache.cc",
-    ]
+    sources = [ "tools/stress_cache/stress_cache.cc" ]
 
     deps = [
       ":net",
@@ -3048,9 +3015,7 @@
   }
 
   executable("tld_cleanup") {
-    sources = [
-      "tools/tld_cleanup/tld_cleanup.cc",
-    ]
+    sources = [ "tools/tld_cleanup/tld_cleanup.cc" ]
 
     deps = [
       "//base",
@@ -3089,9 +3054,7 @@
 if (is_linux || is_mac) {
   executable("cachetool") {
     testonly = true
-    sources = [
-      "tools/cachetool/cachetool.cc",
-    ]
+    sources = [ "tools/cachetool/cachetool.cc" ]
     deps = [
       ":net",
       ":test_support",
@@ -3215,9 +3178,8 @@
 
   executable("quic_client_interop_test") {
     testonly = true
-    sources = [
-      "third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc",
-    ]
+    sources =
+        [ "third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc" ]
     deps = [
       ":epoll_quic_tools",
       ":net",
@@ -3261,9 +3223,7 @@
   }
 
   executable("masque_client") {
-    sources = [
-      "third_party/quiche/src/quic/masque/masque_client_bin.cc",
-    ]
+    sources = [ "third_party/quiche/src/quic/masque/masque_client_bin.cc" ]
     deps = [
       ":epoll_quic_tools",
       ":masque_tools",
@@ -3275,9 +3235,7 @@
   }
 
   executable("masque_server") {
-    sources = [
-      "third_party/quiche/src/quic/masque/masque_server_bin.cc",
-    ]
+    sources = [ "third_party/quiche/src/quic/masque/masque_server_bin.cc" ]
     deps = [
       ":epoll_quic_tools",
       ":masque_tools",
@@ -3322,9 +3280,7 @@
 if (is_android || is_linux) {
   executable("disk_cache_memory_test") {
     testonly = true
-    sources = [
-      "tools/disk_cache_memory_test/disk_cache_memory_test.cc",
-    ]
+    sources = [ "tools/disk_cache_memory_test/disk_cache_memory_test.cc" ]
     deps = [
       ":net",
       "//base",
@@ -3372,8 +3328,11 @@
   sources = [
     "quiche/common/platform/impl/quiche_test_impl.h",
     "third_party/quiche/src/common/platform/api/quiche_test.h",
+    "third_party/quiche/src/common/test_tools/quiche_test_utils.cc",
+    "third_party/quiche/src/common/test_tools/quiche_test_utils.h",
   ]
   deps = [
+    ":net",
     "//testing/gmock",
     "//testing/gtest",
   ]
@@ -3535,6 +3494,7 @@
   ]
   deps = [
     ":net",
+    ":quiche_test_tools",
     ":simple_quic_tools",
     ":test_support",
     "//base",
@@ -3690,9 +3650,7 @@
     ]
   }
   executable("quic_transport_simple_server") {
-    sources = [
-      "tools/quic/quic_transport_simple_server_bin.cc",
-    ]
+    sources = [ "tools/quic/quic_transport_simple_server_bin.cc" ]
     deps = [
       ":net",
       ":simple_quic_tools",
@@ -3703,9 +3661,7 @@
     ]
   }
   executable("quic_packet_printer") {
-    sources = [
-      "third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc",
-    ]
+    sources = [ "third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc" ]
     deps = [
       ":net",
       ":simple_quic_tools",
@@ -3757,9 +3713,7 @@
   }
 
   executable("crypto_message_printer") {
-    sources = [
-      "tools/quic/crypto_message_printer_bin.cc",
-    ]
+    sources = [ "tools/quic/crypto_message_printer_bin.cc" ]
     deps = [
       ":net",
       "//base",
@@ -5122,10 +5076,8 @@
     "third_party/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl",
     "third_party/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 test("net_unittests") {
@@ -5603,6 +5555,7 @@
     "third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc",
     "third_party/quiche/src/quic/core/quic_crypto_stream_test.cc",
     "third_party/quiche/src/quic/core/quic_data_writer_test.cc",
+    "third_party/quiche/src/quic/core/quic_datagram_queue_test.cc",
     "third_party/quiche/src/quic/core/quic_dispatcher_test.cc",
     "third_party/quiche/src/quic/core/quic_error_codes_test.cc",
     "third_party/quiche/src/quic/core/quic_flow_controller_test.cc",
@@ -5901,9 +5854,7 @@
   }
 
   data = []
-  data_deps = [
-    "third_party/nist-pkits/",
-  ]
+  data_deps = [ "third_party/nist-pkits/" ]
 
   if (is_linux || is_mac || is_win || is_fuchsia) {
     deps += [
@@ -6263,15 +6214,11 @@
 }
 
 proto_library("disk_cache_lpm_fuzzer_proto") {
-  sources = [
-    "disk_cache/disk_cache_fuzzer.proto",
-  ]
+  sources = [ "disk_cache/disk_cache_fuzzer.proto" ]
 }
 
 fuzzer_test("disk_cache_lpm_fuzzer") {
-  sources = [
-    "disk_cache/disk_cache_fuzzer.cc",
-  ]
+  sources = [ "disk_cache/disk_cache_fuzzer.cc" ]
   deps = [
     ":disk_cache_lpm_fuzzer_proto",
     ":test_support",
@@ -6282,9 +6229,7 @@
 }
 
 fuzzer_test("net_data_url_fuzzer") {
-  sources = [
-    "base/data_url_fuzzer.cc",
-  ]
+  sources = [ "base/data_url_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6298,9 +6243,7 @@
 }
 
 fuzzer_test("net_mime_sniffer_fuzzer") {
-  sources = [
-    "base/mime_sniffer_fuzzer.cc",
-  ]
+  sources = [ "base/mime_sniffer_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6310,9 +6253,7 @@
 }
 
 fuzzer_test("net_parse_proxy_list_pac_fuzzer") {
-  sources = [
-    "proxy_resolution/parse_proxy_list_pac_fuzzer.cc",
-  ]
+  sources = [ "proxy_resolution/parse_proxy_list_pac_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6320,9 +6261,7 @@
 }
 
 fuzzer_test("net_parse_proxy_list_fuzzer") {
-  sources = [
-    "proxy_resolution/parse_proxy_list_fuzzer.cc",
-  ]
+  sources = [ "proxy_resolution/parse_proxy_list_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6330,9 +6269,7 @@
 }
 
 fuzzer_test("net_parse_proxy_bypass_rules_fuzzer") {
-  sources = [
-    "proxy_resolution/parse_proxy_bypass_rules_fuzzer.cc",
-  ]
+  sources = [ "proxy_resolution/parse_proxy_bypass_rules_fuzzer.cc" ]
 
   libfuzzer_options = [
     # The proxy bypass rules aren't very complicated, so this is more than
@@ -6348,9 +6285,7 @@
 }
 
 fuzzer_test("net_parse_proxy_rules_fuzzer") {
-  sources = [
-    "proxy_resolution/parse_proxy_rules_fuzzer.cc",
-  ]
+  sources = [ "proxy_resolution/parse_proxy_rules_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6359,9 +6294,7 @@
 }
 
 fuzzer_test("net_parse_ip_pattern_fuzzer") {
-  sources = [
-    "base/parse_ip_pattern_fuzzer.cc",
-  ]
+  sources = [ "base/parse_ip_pattern_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6369,9 +6302,8 @@
 }
 
 fuzzer_test("net_get_domain_and_registry_fuzzer") {
-  sources = [
-    "base/registry_controlled_domains/get_domain_and_registry_fuzzer.cc",
-  ]
+  sources =
+      [ "base/registry_controlled_domains/get_domain_and_registry_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6381,9 +6313,7 @@
 }
 
 fuzzer_test("net_cert_ct_decode_signed_certificate_timestamp_fuzzer") {
-  sources = [
-    "cert/decode_signed_certificate_timestamp_fuzzer.cc",
-  ]
+  sources = [ "cert/decode_signed_certificate_timestamp_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6392,9 +6322,7 @@
 }
 
 fuzzer_test("net_cert_verify_name_match_fuzzer") {
-  sources = [
-    "cert/internal/verify_name_match_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/verify_name_match_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6403,9 +6331,7 @@
 }
 
 fuzzer_test("net_cert_normalize_name_fuzzer") {
-  sources = [
-    "cert/internal/verify_name_match_normalizename_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/verify_name_match_normalizename_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -6413,9 +6339,7 @@
 }
 
 fuzzer_test("net_cert_verify_name_in_subtree_fuzzer") {
-  sources = [
-    "cert/internal/verify_name_match_verifynameinsubtree_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/verify_name_match_verifynameinsubtree_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6424,9 +6348,7 @@
 }
 
 fuzzer_test("net_cert_crl_parse_crl_certificatelist_fuzzer") {
-  sources = [
-    "cert/internal/crl_parse_crl_certificatelist_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/crl_parse_crl_certificatelist_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/crl_parse_crl_certificatelist_fuzzer"
   deps = [
     "//base",
@@ -6435,9 +6357,7 @@
 }
 
 fuzzer_test("net_cert_crl_parse_crl_tbscertlist_fuzzer") {
-  sources = [
-    "cert/internal/crl_parse_crl_tbscertlist_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/crl_parse_crl_tbscertlist_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/crl_parse_crl_tbscertlist_fuzzer"
   deps = [
     "//base",
@@ -6446,9 +6366,7 @@
 }
 
 fuzzer_test("net_cert_crl_parse_issuing_distribution_point_fuzzer") {
-  sources = [
-    "cert/internal/crl_parse_issuing_distribution_point_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/crl_parse_issuing_distribution_point_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/crl_parse_issuing_distribution_point_fuzzer"
   deps = [
     "//base",
@@ -6457,9 +6375,7 @@
 }
 
 fuzzer_test("net_cert_crl_getcrlstatusforcert_fuzzer") {
-  sources = [
-    "cert/internal/crl_getcrlstatusforcert_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/crl_getcrlstatusforcert_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/crl_getcrlstatusforcert_fuzzer"
   deps = [
     "//base",
@@ -6468,9 +6384,7 @@
 }
 
 fuzzer_test("net_cert_ocsp_parse_ocsp_cert_id_fuzzer") {
-  sources = [
-    "cert/internal/ocsp_parse_ocsp_cert_id_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/ocsp_parse_ocsp_cert_id_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/parse_ocsp_cert_id_fuzzer"
   deps = [
     "//base",
@@ -6479,9 +6393,7 @@
 }
 
 fuzzer_test("net_cert_ocsp_parse_ocsp_single_response_fuzzer") {
-  sources = [
-    "cert/internal/ocsp_parse_ocsp_single_response_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/ocsp_parse_ocsp_single_response_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/parse_ocsp_single_response_fuzzer"
   deps = [
     "//base",
@@ -6490,9 +6402,7 @@
 }
 
 fuzzer_test("net_cert_ocsp_parse_ocsp_response_data_fuzzer") {
-  sources = [
-    "cert/internal/ocsp_parse_ocsp_response_data_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/ocsp_parse_ocsp_response_data_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/parse_ocsp_response_data_fuzzer"
   deps = [
     "//base",
@@ -6501,9 +6411,7 @@
 }
 
 fuzzer_test("net_cert_ocsp_parse_ocsp_response_fuzzer") {
-  sources = [
-    "cert/internal/ocsp_parse_ocsp_response_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/ocsp_parse_ocsp_response_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/parse_ocsp_response_fuzzer"
   deps = [
     "//base",
@@ -6512,9 +6420,7 @@
 }
 
 fuzzer_test("net_cert_parse_authority_key_identifier_fuzzer") {
-  sources = [
-    "cert/internal/parse_authority_key_identifier_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/parse_authority_key_identifier_fuzzer.cc" ]
   seed_corpus = "data/fuzzer_data/parse_authority_key_identifier_fuzzer"
   deps = [
     "//base",
@@ -6523,9 +6429,7 @@
 }
 
 fuzzer_test("net_cert_parse_certificate_fuzzer") {
-  sources = [
-    "cert/internal/parse_certificate_fuzzer.cc",
-  ]
+  sources = [ "cert/internal/parse_certificate_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -6533,9 +6437,7 @@
 }
 
 fuzzer_test("net_canonical_cookie_fuzzer") {
-  sources = [
-    "cookies/canonical_cookie_fuzzer.cc",
-  ]
+  sources = [ "cookies/canonical_cookie_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6544,9 +6446,7 @@
 }
 
 fuzzer_test("net_parse_cookie_line_fuzzer") {
-  sources = [
-    "cookies/parse_cookie_line_fuzzer.cc",
-  ]
+  sources = [ "cookies/parse_cookie_line_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6554,9 +6454,7 @@
 }
 
 fuzzer_test("net_http_stream_parser_fuzzer") {
-  sources = [
-    "http/http_stream_parser_fuzzer.cc",
-  ]
+  sources = [ "http/http_stream_parser_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6585,9 +6483,7 @@
 
 if (!disable_brotli_filter) {
   fuzzer_test("net_brotli_source_stream_fuzzer") {
-    sources = [
-      "filter/brotli_source_stream_fuzzer.cc",
-    ]
+    sources = [ "filter/brotli_source_stream_fuzzer.cc" ]
     deps = [
       ":net_fuzzer_test_support",
       ":test_support",
@@ -6598,9 +6494,7 @@
 }
 
 fuzzer_test("net_gzip_source_stream_fuzzer") {
-  sources = [
-    "filter/gzip_source_stream_fuzzer.cc",
-  ]
+  sources = [ "filter/gzip_source_stream_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6610,9 +6504,7 @@
 }
 
 fuzzer_test("net_crl_set_fuzzer") {
-  sources = [
-    "cert/crl_set_fuzzer.cc",
-  ]
+  sources = [ "cert/crl_set_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6624,9 +6516,7 @@
 
 if (!disable_ftp_support) {
   fuzzer_test("net_ftp_ctrl_response_fuzzer") {
-    sources = [
-      "ftp/ftp_ctrl_response_fuzzer.cc",
-    ]
+    sources = [ "ftp/ftp_ctrl_response_fuzzer.cc" ]
     deps = [
       ":net_fuzzer_test_support",
       "//base",
@@ -6635,9 +6525,7 @@
   }
 
   fuzzer_test("net_ftp_directory_listing_fuzzer") {
-    sources = [
-      "ftp/ftp_directory_listing_fuzzer.cc",
-    ]
+    sources = [ "ftp/ftp_directory_listing_fuzzer.cc" ]
     deps = [
       ":net_fuzzer_test_support",
       "//base",
@@ -6650,9 +6538,7 @@
   }
 
   fuzzer_test("net_url_request_ftp_fuzzer") {
-    sources = [
-      "url_request/url_request_ftp_fuzzer.cc",
-    ]
+    sources = [ "url_request/url_request_ftp_fuzzer.cc" ]
     deps = [
       ":net_fuzzer_test_support",
       ":test_support",
@@ -6669,9 +6555,7 @@
 }
 
 fuzzer_test("net_unescape_url_component_fuzzer") {
-  sources = [
-    "base/unescape_url_component_fuzzer.cc",
-  ]
+  sources = [ "base/unescape_url_component_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6682,9 +6566,7 @@
 }
 
 fuzzer_test("net_websocket_deflate_stream_fuzzer") {
-  sources = [
-    "websockets/websocket_deflate_stream_fuzzer.cc",
-  ]
+  sources = [ "websockets/websocket_deflate_stream_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6694,9 +6576,7 @@
 }
 
 fuzzer_test("net_websocket_extension_parser_fuzzer") {
-  sources = [
-    "websockets/websocket_extension_parser_fuzzer.cc",
-  ]
+  sources = [ "websockets/websocket_extension_parser_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6706,9 +6586,7 @@
 }
 
 fuzzer_test("net_websocket_frame_parser_fuzzer") {
-  sources = [
-    "websockets/websocket_frame_parser_fuzzer.cc",
-  ]
+  sources = [ "websockets/websocket_frame_parser_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6718,9 +6596,7 @@
 }
 
 fuzzer_test("net_http_chunked_decoder_fuzzer") {
-  sources = [
-    "http/http_chunked_decoder_fuzzer.cc",
-  ]
+  sources = [ "http/http_chunked_decoder_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6729,9 +6605,7 @@
 }
 
 fuzzer_test("net_http_auth_handler_basic_fuzzer") {
-  sources = [
-    "http/http_auth_handler_basic_fuzzer.cc",
-  ]
+  sources = [ "http/http_auth_handler_basic_fuzzer.cc" ]
   dict = "data/fuzzer_dictionaries/net_http_auth_handler_basic_fuzzer.dict"
   deps = [
     ":net_fuzzer_test_support",
@@ -6741,9 +6615,7 @@
 }
 
 fuzzer_test("net_http_auth_handler_digest_fuzzer") {
-  sources = [
-    "http/http_auth_handler_digest_fuzzer.cc",
-  ]
+  sources = [ "http/http_auth_handler_digest_fuzzer.cc" ]
   dict = "data/fuzzer_dictionaries/net_http_auth_handler_digest_fuzzer.dict"
   deps = [
     ":net_fuzzer_test_support",
@@ -6753,9 +6625,7 @@
 }
 
 fuzzer_test("net_http_content_disposition_fuzzer") {
-  sources = [
-    "http/http_content_disposition_fuzzer.cc",
-  ]
+  sources = [ "http/http_content_disposition_fuzzer.cc" ]
   dict = "data/fuzzer_dictionaries/net_http_content_disposition_fuzzer.dict"
   deps = [
     ":net_fuzzer_test_support",
@@ -6764,9 +6634,7 @@
 }
 
 fuzzer_test("net_http_proxy_client_socket_fuzzer") {
-  sources = [
-    "http/http_proxy_client_socket_fuzzer.cc",
-  ]
+  sources = [ "http/http_proxy_client_socket_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6777,9 +6645,7 @@
 }
 
 fuzzer_test("net_parse_url_hostname_to_address_fuzzer") {
-  sources = [
-    "base/parse_url_hostname_to_address_fuzzer.cc",
-  ]
+  sources = [ "base/parse_url_hostname_to_address_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6790,9 +6656,7 @@
 }
 
 fuzzer_test("net_quic_crypto_framer_parse_message_fuzzer") {
-  sources = [
-    "quic/quic_crypto_framer_parse_message_fuzzer.cc",
-  ]
+  sources = [ "quic/quic_crypto_framer_parse_message_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6801,9 +6665,7 @@
 }
 
 fuzzer_test("net_quic_transport_parameters_fuzzer") {
-  sources = [
-    "quic/quic_transport_parameters_fuzzer.cc",
-  ]
+  sources = [ "quic/quic_transport_parameters_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6812,9 +6674,7 @@
 }
 
 fuzzer_test("net_socks_client_socket_fuzzer") {
-  sources = [
-    "socket/socks_client_socket_fuzzer.cc",
-  ]
+  sources = [ "socket/socks_client_socket_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6824,9 +6684,7 @@
 }
 
 fuzzer_test("net_socks5_client_socket_fuzzer") {
-  sources = [
-    "socket/socks5_client_socket_fuzzer.cc",
-  ]
+  sources = [ "socket/socks5_client_socket_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6836,9 +6694,7 @@
 }
 
 fuzzer_test("net_url_request_fuzzer") {
-  sources = [
-    "url_request/url_request_fuzzer.cc",
-  ]
+  sources = [ "url_request/url_request_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6849,9 +6705,7 @@
 }
 
 fuzzer_test("net_auth_challenge_tokenizer_fuzzer") {
-  sources = [
-    "http/http_auth_challenge_tokenizer_fuzzer.cc",
-  ]
+  sources = [ "http/http_auth_challenge_tokenizer_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6861,9 +6715,7 @@
 }
 
 fuzzer_test("net_http_security_headers_expect_ct_fuzzer") {
-  sources = [
-    "http/http_security_headers_expect_ct_fuzzer.cc",
-  ]
+  sources = [ "http/http_security_headers_expect_ct_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -6875,9 +6727,7 @@
 }
 
 fuzzer_test("net_http_security_headers_hsts_fuzzer") {
-  sources = [
-    "http/http_security_headers_hsts_fuzzer.cc",
-  ]
+  sources = [ "http/http_security_headers_hsts_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -6887,9 +6737,7 @@
 }
 
 fuzzer_test("net_http_transport_security_state_static_fuzzer") {
-  sources = [
-    "http/transport_security_state_static_fuzzer.cc",
-  ]
+  sources = [ "http/transport_security_state_static_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//net",
@@ -6899,9 +6747,7 @@
 }
 
 fuzzer_test("net_spdy_session_fuzzer") {
-  sources = [
-    "spdy/spdy_session_fuzzer.cc",
-  ]
+  sources = [ "spdy/spdy_session_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6914,9 +6760,7 @@
 }
 
 fuzzer_test("net_http2_frame_decoder_fuzzer") {
-  sources = [
-    "spdy/fuzzing/http2_frame_decoder_fuzzer.cc",
-  ]
+  sources = [ "spdy/fuzzing/http2_frame_decoder_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6926,9 +6770,7 @@
 }
 
 fuzzer_test("net_hpack_decoder_fuzzer") {
-  sources = [
-    "spdy/fuzzing/hpack_decoder_fuzzer.cc",
-  ]
+  sources = [ "spdy/fuzzing/hpack_decoder_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":test_support",
@@ -6939,16 +6781,12 @@
 
 proto_library("reporting_policy_proto") {
   proto_in_dir = "//"
-  sources = [
-    "reporting/reporting_policy.proto",
-  ]
+  sources = [ "reporting/reporting_policy.proto" ]
   link_deps = [ "//testing/libfuzzer/proto:json_proto" ]
 }
 
 fuzzer_test("net_reporting_header_parser_fuzzer") {
-  sources = [
-    "reporting/reporting_header_parser_fuzzer.cc",
-  ]
+  sources = [ "reporting/reporting_header_parser_fuzzer.cc" ]
 
   deps = [
     ":net_fuzzer_test_support",
@@ -6963,9 +6801,7 @@
 }
 
 fuzzer_test("net_quic_stream_factory_fuzzer") {
-  sources = [
-    "quic/quic_stream_factory_fuzzer.cc",
-  ]
+  sources = [ "quic/quic_stream_factory_fuzzer.cc" ]
 
   deps = [
     ":net_fuzzer_test_support",
@@ -6977,9 +6813,8 @@
 }
 
 fuzzer_test("net_quic_framer_fuzzer") {
-  sources = [
-    "third_party/quiche/src/quic/test_tools/fuzzing/quic_framer_fuzzer.cc",
-  ]
+  sources =
+      [ "third_party/quiche/src/quic/test_tools/fuzzing/quic_framer_fuzzer.cc" ]
 
   deps = [
     ":net_fuzzer_test_support",
@@ -6991,9 +6826,7 @@
 }
 
 fuzzer_test("net_quic_framer_process_data_packet_fuzzer") {
-  sources = [
-    "third_party/quiche/src/quic/test_tools/fuzzing/quic_framer_process_data_packet_fuzzer.cc",
-  ]
+  sources = [ "third_party/quiche/src/quic/test_tools/fuzzing/quic_framer_process_data_packet_fuzzer.cc" ]
 
   deps = [
     ":net_fuzzer_test_support",
@@ -7005,9 +6838,7 @@
 }
 
 fuzzer_test("net_uri_template_fuzzer") {
-  sources = [
-    "third_party/uri_template/uri_template_fuzzer.cc",
-  ]
+  sources = [ "third_party/uri_template/uri_template_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -7031,9 +6862,7 @@
 }
 
 fuzzer_test("net_qpack_encoder_stream_receiver_fuzzer") {
-  sources = [
-    "third_party/quiche/src/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc",
-  ]
+  sources = [ "third_party/quiche/src/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     "//base",
@@ -7043,9 +6872,7 @@
 }
 
 fuzzer_test("net_qpack_encoder_stream_sender_fuzzer") {
-  sources = [
-    "third_party/quiche/src/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc",
-  ]
+  sources = [ "third_party/quiche/src/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc" ]
   deps = [
     ":net_fuzzer_test_support",
     ":quic_test_tools",
@@ -7072,9 +6899,7 @@
 
 if (is_linux) {
   fuzzer_test("net_base_address_tracker_linux_fuzzer") {
-    sources = [
-      "base/address_tracker_linux_fuzzer.cc",
-    ]
+    sources = [ "base/address_tracker_linux_fuzzer.cc" ]
     deps = [
       ":net_fuzzer_test_support",
       ":test_support",
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn
index e794104..76a53de2 100644
--- a/net/android/BUILD.gn
+++ b/net/android/BUILD.gn
@@ -43,9 +43,7 @@
 }
 
 android_library("net_thread_stats_uid_java") {
-  sources = [
-    "java/src/org/chromium/net/ThreadStatsUid.java",
-  ]
+  sources = [ "java/src/org/chromium/net/ThreadStatsUid.java" ]
 }
 
 android_aidl("embedded_test_server_aidl") {
@@ -58,9 +56,7 @@
 
 android_library("embedded_test_server_aidl_java") {
   testonly = true
-  deps = [
-    "//third_party/android_deps:androidx_annotation_annotation_java",
-  ]
+  deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ]
   srcjar_deps = [ ":embedded_test_server_aidl" ]
 }
 
@@ -103,9 +99,7 @@
     "//base:base_java_test_support",
   ]
 
-  data_deps = [
-    "//net:test_support",
-  ]
+  data_deps = [ "//net:test_support" ]
 }
 
 source_set("java_test_native_support") {
@@ -118,12 +112,8 @@
     "../test/embedded_test_server/android/embedded_test_server_android.h",
   ]
 
-  deps = [
-    "//net:test_support",
-  ]
-  public_deps = [
-    "//net:net_test_jni_headers",
-  ]
+  deps = [ "//net:test_support" ]
+  public_deps = [ "//net:net_test_jni_headers" ]
 }
 
 shared_library("net_java_test_native_support") {
@@ -192,12 +182,8 @@
 
 java_cpp_template("net_errors_java") {
   package_path = "org/chromium/net"
-  sources = [
-    "java/NetError.template",
-  ]
-  inputs = [
-    "../base/net_error_list.h",
-  ]
+  sources = [ "java/NetError.template" ]
+  inputs = [ "../base/net_error_list.h" ]
 }
 
 java_cpp_enum("net_java_test_support_enums_srcjar") {
@@ -220,9 +206,7 @@
 }
 
 junit_binary("net_junit_tests") {
-  sources = [
-    "junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java",
-  ]
+  sources = [ "junit/src/org/chromium/net/HttpNegotiateAuthenticatorTest.java" ]
   deps = [
     ":net_java",
     "//base:base_java",
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc
index b8ce2e0..30de285 100644
--- a/net/base/filename_util_internal.cc
+++ b/net/base/filename_util_internal.cc
@@ -155,14 +155,15 @@
 bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
   base::FilePath::StringType extension_lower = base::ToLowerASCII(extension);
 
-  // http://msdn.microsoft.com/en-us/library/ms811694.aspx
-  // Right-clicking on shortcuts can be magical.
+  // .lnk files may be used to execute arbitrary code (see
+  // https://nvd.nist.gov/vuln/detail/CVE-2010-2568). .local files are used by
+  // Windows to determine which DLLs to load for an application.
   if ((extension_lower == FILE_PATH_LITERAL("local")) ||
       (extension_lower == FILE_PATH_LITERAL("lnk")))
     return true;
 
-  // http://www.juniper.net/security/auto/vulnerabilities/vuln2612.html
-  // Files become magical if they end in a CLSID, so block such extensions.
+  // Setting a file's extension to a CLSID may conceal its actual file type on
+  // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
   if (!extension_lower.empty() &&
       (extension_lower.front() == FILE_PATH_LITERAL('{')) &&
       (extension_lower.back() == FILE_PATH_LITERAL('}')))
diff --git a/net/data/ssl/certificates/BUILD.gn b/net/data/ssl/certificates/BUILD.gn
index 5677d35..b4ea35d 100644
--- a/net/data/ssl/certificates/BUILD.gn
+++ b/net/data/ssl/certificates/BUILD.gn
@@ -8,8 +8,6 @@
     "spdy_pooling.pem",
     "wildcard.pem",
   ]
-  outputs = [
-    "$target_gen_dir/{{source_name_part}}.inc",
-  ]
+  outputs = [ "$target_gen_dir/{{source_name_part}}.inc" ]
   args = [ "{{source}}" ] + rebase_path(outputs, root_build_dir)
 }
diff --git a/net/http/BUILD.gn b/net/http/BUILD.gn
index 22ec5de..3bdcf9d 100644
--- a/net/http/BUILD.gn
+++ b/net/http/BUILD.gn
@@ -15,9 +15,7 @@
     "transport_security_state_static.pins",
     "transport_security_state_static.template",
   ]
-  outputs = [
-    "$target_gen_dir/transport_security_state_static.h",
-  ]
+  outputs = [ "$target_gen_dir/transport_security_state_static.h" ]
   args =
       rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
 }
@@ -32,9 +30,8 @@
     "transport_security_state_static_unittest_default.pins",
     "transport_security_state_static_unittest.template",
   ]
-  outputs = [
-    "$target_gen_dir/transport_security_state_static_unittest_default.h",
-  ]
+  outputs =
+      [ "$target_gen_dir/transport_security_state_static_unittest_default.h" ]
   args =
       rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
 }
@@ -54,9 +51,7 @@
     "transport_security_state_static_unittest.pins",
     "transport_security_state_static_unittest.template",
   ]
-  outputs = [
-    "$target_gen_dir/{{source_name_part}}.h",
-  ]
+  outputs = [ "$target_gen_dir/{{source_name_part}}.h" ]
   args =
       [ rebase_path("{{source_name_part}}.json", root_build_dir) ] +
       rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
@@ -68,9 +63,7 @@
   # Do not publicize any header to remove build dependency.
   public = []
 
-  sources = [
-    "transport_security_state.cc",
-  ]
+  sources = [ "transport_security_state.cc" ]
 
   deps = [
     "//build:branding_buildflags",
diff --git a/net/http2/platform/impl/http2_reconstruct_object_impl.h b/net/http2/platform/impl/http2_reconstruct_object_impl.h
deleted file mode 100644
index 4f4588f..0000000
--- a/net/http2/platform/impl/http2_reconstruct_object_impl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_
-#define NET_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_
-
-#include <utility>
-
-namespace http2 {
-namespace test {
-
-class Http2Random;
-
-// Reconstruct an object so that it is initialized as when it was first
-// constructed. Runs the destructor to handle objects that might own resources,
-// and runs the constructor with the provided arguments, if any.
-template <class T, class... Args>
-void Http2ReconstructObjectImpl(T* ptr, Http2Random* rng, Args&&... args) {
-  ptr->~T();
-  ::new (ptr) T(std::forward<Args>(args)...);
-}
-
-// This version applies default-initialization to the object.
-template <class T>
-void Http2DefaultReconstructObjectImpl(T* ptr, Http2Random* rng) {
-  ptr->~T();
-  ::new (ptr) T;
-}
-
-}  // namespace test
-}  // namespace http2
-
-#endif  // NET_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index 45f1a52..2c240aa 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -99,6 +99,11 @@
   quic::ParsedQuicVersionVector all_supported_versions =
       quic::AllSupportedVersions();
   for (const auto& version : all_supported_versions) {
+    // Test fails for soon to be deprecated Q099, so skip it.
+    if (version.transport_version == quic::QUIC_VERSION_99 &&
+        version.handshake_protocol == quic::PROTOCOL_QUIC_CRYPTO) {
+      continue;
+    }
     params.push_back(TestParams{version, false});
     params.push_back(TestParams{version, true});
   }
diff --git a/net/quic/mock_crypto_client_stream.cc b/net/quic/mock_crypto_client_stream.cc
index 198932a..431f65b 100644
--- a/net/quic/mock_crypto_client_stream.cc
+++ b/net/quic/mock_crypto_client_stream.cc
@@ -302,10 +302,8 @@
       QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
       QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs));
   config.SetBytesForConnectionIdToSend(PACKET_8BYTE_CONNECTION_ID);
-  config.SetMaxIncomingBidirectionalStreamsToSend(
-      kDefaultMaxStreamsPerConnection / 2);
-  config.SetMaxIncomingUnidirectionalStreamsToSend(
-      kDefaultMaxStreamsPerConnection / 2);
+  config.SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2);
+  config.SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2);
   config.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
       quic::kMinimumFlowControlSendWindow);
   config.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
diff --git a/net/quic/platform/impl/quic_logging_impl.h b/net/quic/platform/impl/quic_logging_impl.h
deleted file mode 100644
index ff72671..0000000
--- a/net/quic/platform/impl/quic_logging_impl.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_LOGGING_IMPL_H_
-#define NET_QUIC_PLATFORM_IMPL_QUIC_LOGGING_IMPL_H_
-
-#include "base/logging.h"
-#include "net/base/net_export.h"
-
-#define QUIC_LOG_IMPL(severity) QUIC_CHROMIUM_LOG_##severity
-#define QUIC_VLOG_IMPL(verbose_level) VLOG(verbose_level)
-#define QUIC_LOG_EVERY_N_SEC_IMPL(severity, seconds) QUIC_LOG_IMPL(severity)
-#define QUIC_LOG_FIRST_N_IMPL(severity, n) QUIC_LOG_IMPL(severity)
-#define QUIC_DLOG_IMPL(severity) QUIC_CHROMIUM_DLOG_##severity
-#define QUIC_DLOG_IF_IMPL(severity, condition) \
-  QUIC_CHROMIUM_DLOG_IF_##severity(condition)
-#define QUIC_LOG_IF_IMPL(severity, condition) \
-  QUIC_CHROMIUM_LOG_IF_##severity(condition)
-
-#define QUIC_CHROMIUM_LOG_INFO VLOG(1)
-#define QUIC_CHROMIUM_LOG_WARNING DLOG(WARNING)
-#define QUIC_CHROMIUM_LOG_ERROR DLOG(ERROR)
-#define QUIC_CHROMIUM_LOG_FATAL LOG(FATAL)
-#define QUIC_CHROMIUM_LOG_DFATAL LOG(DFATAL)
-
-#define QUIC_CHROMIUM_DLOG_INFO DVLOG(1)
-#define QUIC_CHROMIUM_DLOG_WARNING DLOG(WARNING)
-#define QUIC_CHROMIUM_DLOG_ERROR DLOG(ERROR)
-#define QUIC_CHROMIUM_DLOG_FATAL DLOG(FATAL)
-#define QUIC_CHROMIUM_DLOG_DFATAL DLOG(DFATAL)
-
-#define QUIC_CHROMIUM_LOG_IF_INFO(condition) VLOG_IF(1, condition)
-#define QUIC_CHROMIUM_LOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
-#define QUIC_CHROMIUM_LOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
-#define QUIC_CHROMIUM_LOG_IF_FATAL(condition) LOG_IF(FATAL, condition)
-#define QUIC_CHROMIUM_LOG_IF_DFATAL(condition) LOG_IF(DFATAL, condition)
-
-#define QUIC_CHROMIUM_DLOG_IF_INFO(condition) DVLOG_IF(1, condition)
-#define QUIC_CHROMIUM_DLOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
-#define QUIC_CHROMIUM_DLOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
-#define QUIC_CHROMIUM_DLOG_IF_FATAL(condition) DLOG_IF(FATAL, condition)
-#define QUIC_CHROMIUM_DLOG_IF_DFATAL(condition) DLOG_IF(DFATAL, condition)
-
-#define QUIC_DVLOG_IMPL(verbose_level) DVLOG(verbose_level)
-#define QUIC_DVLOG_IF_IMPL(verbose_level, condition) \
-  DVLOG_IF(verbose_level, condition)
-
-#define QUIC_LOG_INFO_IS_ON_IMPL() 0
-#ifdef NDEBUG
-#define QUIC_LOG_WARNING_IS_ON_IMPL() 0
-#define QUIC_LOG_ERROR_IS_ON_IMPL() 0
-#else
-#define QUIC_LOG_WARNING_IS_ON_IMPL() 1
-#define QUIC_LOG_ERROR_IS_ON_IMPL() 1
-#endif
-#define QUIC_DLOG_INFO_IS_ON_IMPL() 0
-
-#if defined(OS_WIN)
-// wingdi.h defines ERROR to be 0. When we call QUIC_DLOG(ERROR), it gets
-// substituted with 0, and it expands to QUIC_CHROMIUM_DLOG_0. To allow us to
-// keep using this syntax, we define this macro to do the same thing as
-// QUIC_CHROMIUM_DLOG_ERROR.
-#define QUIC_CHROMIUM_LOG_0 QUIC_CHROMIUM_LOG_ERROR
-#define QUIC_CHROMIUM_DLOG_0 QUIC_CHROMIUM_DLOG_ERROR
-#define QUIC_CHROMIUM_LOG_IF_0 QUIC_CHROMIUM_LOG_IF_ERROR
-#define QUIC_CHROMIUM_DLOG_IF_0 QUIC_CHROMIUM_DLOG_IF_ERROR
-#endif
-
-#define QUIC_PREDICT_FALSE_IMPL(x) x
-#define QUIC_PREDICT_TRUE_IMPL(x) x
-
-#define QUIC_NOTREACHED_IMPL() NOTREACHED()
-
-#define QUIC_PLOG_IMPL(severity) DVLOG(1)
-
-namespace quic {
-template <typename T>
-NET_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
-                                                   const std::vector<T>& v) {
-  out << "[";
-  const char* sep = "";
-  for (size_t i = 0; i < v.size(); ++i) {
-    out << sep << v[i];
-    sep = ", ";
-  }
-  return out << "]";
-}
-}  // namespace quic
-
-#endif  // NET_QUIC_PLATFORM_IMPL_QUIC_LOGGING_IMPL_H_
diff --git a/net/quic/platform/impl/quic_mem_slice_impl.h b/net/quic/platform/impl/quic_mem_slice_impl.h
index bf550d4..8134a06 100644
--- a/net/quic/platform/impl/quic_mem_slice_impl.h
+++ b/net/quic/platform/impl/quic_mem_slice_impl.h
@@ -51,7 +51,7 @@
  private:
   scoped_refptr<net::IOBuffer> io_buffer_;
   // Length of io_buffer_.
-  size_t length_;
+  size_t length_ = 0;
 };
 
 }  // namespace quic
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index a97b0e60..107b364 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -1000,15 +1000,6 @@
       if (!VersionUsesHttp3(connection()->transport_version())) {
         WritePriority(update.id, update.parent_stream_id, update.weight,
                       update.exclusive);
-      } else if (FLAGS_quic_allow_http3_priority) {
-        quic::PriorityFrame frame;
-        frame.weight = update.weight;
-        frame.exclusive = update.exclusive;
-        frame.prioritized_element_id = update.id;
-        frame.prioritized_type = quic::REQUEST_STREAM;
-        frame.dependency_type = quic::REQUEST_STREAM;
-        frame.element_dependency_id = update.parent_stream_id;
-        WriteH3Priority(frame);
       }
     }
   }
@@ -3177,15 +3168,6 @@
           promised_id, priority, &parent_stream_id, &weight, &exclusive);
       if (!VersionUsesHttp3(connection()->transport_version())) {
         WritePriority(promised_id, parent_stream_id, weight, exclusive);
-      } else if (FLAGS_quic_allow_http3_priority) {
-        quic::PriorityFrame frame;
-        frame.weight = weight;
-        frame.exclusive = exclusive;
-        frame.prioritized_type = quic::PUSH_STREAM;
-        frame.prioritized_element_id = promised_id;
-        frame.dependency_type = quic::REQUEST_STREAM;
-        frame.element_dependency_id = parent_stream_id;
-        WriteH3Priority(frame);
       }
     }
   }
diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc
index f959b47..89f4161b 100644
--- a/net/quic/quic_chromium_client_stream_test.cc
+++ b/net/quic/quic_chromium_client_stream_test.cc
@@ -170,7 +170,7 @@
     quic::test::QuicConfigPeer::
         SetReceivedInitialMaxStreamDataBytesOutgoingBidirectional(
             session_.config(), quic::kMinimumFlowControlSendWindow);
-    quic::test::QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+    quic::test::QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(
         session_.config(), 10);
     session_.OnConfigNegotiated();
     stream_ = new QuicChromiumClientStream(
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index e2ef441..5d4e1daf 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -208,12 +208,6 @@
           FLAGS_quic_reloadable_flag_quic_use_http2_priority_write_scheduler,
           true)
 
-// If true and FIFO connection option is received, write_blocked_streams uses
-// FIFO(stream with smallest ID has highest priority) write scheduler.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_enable_fifo_write_scheduler,
-          true)
-
 // If true and LIFO connection option is received, write_blocked_streams uses
 // LIFO(stream with largest ID has highest priority) write scheduler.
 QUIC_FLAG(bool,
@@ -239,14 +233,6 @@
 // If true, enable HTTP/2 default scheduling(round robin).
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_rr_write_scheduler, true)
 
-// Call NeuterHandshakePackets() at most once per connection.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_neuter_handshake_packets_once2,
-          true)
-
-// If true, support HTTP/3 priority in v99.
-QUIC_FLAG(bool, FLAGS_quic_allow_http3_priority, false)
-
 // If the bandwidth during ack aggregation is smaller than (estimated
 // bandwidth * this flag), consider the current aggregation completed
 // and starts a new one.
@@ -271,12 +257,6 @@
           FLAGS_quic_reloadable_flag_quic_bbr_donot_inject_bandwidth,
           true)
 
-// If true, close connection if CreateAndSerializeStreamFrame fails.
-QUIC_FLAG(
-    bool,
-    FLAGS_quic_reloadable_flag_quic_close_connection_on_failed_consume_data_fast_path,
-    true)
-
 // If true, add a up call when N packet numbers get skipped.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_on_packet_numbers_skipped,
@@ -303,13 +283,6 @@
 // upon high loss.
 QUIC_FLAG(double, FLAGS_quic_bbr2_default_inflight_hi_headroom, 0.01)
 
-// If true, when a stream receives data with wrong close offset, it closes the
-// connection. And the stream frame data will be discarded.
-QUIC_FLAG(
-    bool,
-    FLAGS_quic_reloadable_flag_quic_close_connection_and_discard_data_on_wrong_offset,
-    true)
-
 // If true, log number of ack aggregation epochs in QUIC transport connection
 // stats.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_log_ack_aggregation_stats, true)
@@ -358,7 +331,7 @@
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_q050, false)
 
 // If true, enable QUIC version Q099.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_q099, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_q099, false)
 
 // If true, enable QUIC version T050.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_t050, true)
@@ -395,7 +368,7 @@
 // If true, QUIC will call bandwidth sampler once per ack event, instead of once
 // per acked packet.
 QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_one_bw_sample_per_ack_event,
+          FLAGS_quic_reloadable_flag_quic_one_bw_sample_per_ack_event2,
           false)
 
 // If true, QUIC will call bandwidth sampler once per ack event, instead of once
@@ -417,3 +390,11 @@
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_log_coalesce_stream_frame_frequency,
           true)
+
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_ip_bandwidth_module, false)
+
+// In BBR, slow pacing rate if it is likely causing overshoot.
+QUIC_FLAG(
+    bool,
+    FLAGS_quic_reloadable_flag_quic_bbr_mitigate_overly_large_bandwidth_sample,
+    false)
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index e17a6a0..b0a0f99 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -109,6 +109,11 @@
   quic::ParsedQuicVersionVector all_supported_versions =
       quic::AllSupportedVersions();
   for (const auto& version : all_supported_versions) {
+    // Test fails for soon to be deprecated Q099, so skip it.
+    // TODO(bnc): Re-enable T099 when PRIORITY_UPDATE is added.
+    if (version.transport_version == quic::QUIC_VERSION_99) {
+      continue;
+    }
     params.push_back(TestParams{version, false});
     params.push_back(TestParams{version, true});
   }
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 066452d..380ecc5c 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -3393,7 +3393,6 @@
     client_maker_.RemoveSavedStreamFrames(
         GetNthClientInitiatedBidirectionalStreamId(0));
 
-    if (FLAGS_quic_allow_http3_priority) {
       // TLP 1
       quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
                                           1, packet_number++, true));
@@ -3425,41 +3424,6 @@
                          client_maker_.MakeConnectionClosePacket(
                              packet_number++, true, quic::QUIC_TOO_MANY_RTOS,
                              "5 consecutive retransmission timeouts"));
-    } else {
-      // When PRIORITY is disabled, packet 2 only contains request headers. And
-      // since the request stream is reset, packet 2 will not be retransmitted.
-      // TLP 1
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          1, packet_number++, true));
-      // TLP 2
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          3, packet_number++, true));
-      // RTO 1
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          4, packet_number++, true));
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          1, packet_number++, true));
-      // RTO 2
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          3, packet_number++, true));
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          4, packet_number++, true));
-      // RTO 3
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          1, packet_number++, true));
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          3, packet_number++, true));
-      // RTO 4
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          4, packet_number++, true));
-      quic_data.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
-                                          1, packet_number++, true));
-      // RTO 5
-      quic_data.AddWrite(SYNCHRONOUS,
-                         client_maker_.MakeConnectionClosePacket(
-                             packet_number++, true, quic::QUIC_TOO_MANY_RTOS,
-                             "5 consecutive retransmission timeouts"));
-    }
   }
 
   quic_data.AddRead(ASYNC, OK);
@@ -6853,9 +6817,7 @@
           GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
   if ((client_headers_include_h2_stream_dependency_ &&
        version_.transport_version >= quic::QUIC_VERSION_43 &&
-       !VersionUsesHttp3(version_.transport_version)) ||
-      (VersionUsesHttp3(version_.transport_version) &&
-       FLAGS_quic_allow_http3_priority)) {
+       !VersionUsesHttp3(version_.transport_version))) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientPriorityPacket(
@@ -6949,9 +6911,7 @@
           GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_));
   if ((client_headers_include_h2_stream_dependency_ &&
        version_.transport_version >= quic::QUIC_VERSION_43 &&
-       !VersionUsesHttp3(version_.transport_version)) ||
-      (VersionUsesHttp3(version_.transport_version) &&
-       FLAGS_quic_allow_http3_priority)) {
+       !VersionUsesHttp3(version_.transport_version))) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientPriorityPacket(
@@ -7221,9 +7181,7 @@
 
   if ((client_headers_include_h2_stream_dependency_ &&
        version_.transport_version >= quic::QUIC_VERSION_43 &&
-       !VersionUsesHttp3(version_.transport_version)) ||
-      (VersionUsesHttp3(version_.transport_version) &&
-       (FLAGS_quic_allow_http3_priority))) {
+       !VersionUsesHttp3(version_.transport_version))) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientPriorityPacket(
@@ -7901,9 +7859,7 @@
 
   if ((client_headers_include_h2_stream_dependency_ &&
        version_.transport_version >= quic::QUIC_VERSION_43 &&
-       !VersionUsesHttp3(version_.transport_version)) ||
-      (VersionUsesHttp3(version_.transport_version) &&
-       FLAGS_quic_allow_http3_priority)) {
+       !VersionUsesHttp3(version_.transport_version))) {
     mock_quic_data.AddWrite(
         SYNCHRONOUS,
         ConstructClientPriorityPacket(
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc
index 79b932f..d73eb07 100644
--- a/net/quic/quic_test_packet_maker.cc
+++ b/net/quic/quic_test_packet_maker.cc
@@ -542,11 +542,8 @@
   if (quic::VersionUsesHttp3(version_.transport_version)) {
     MaybeAddHttp3SettingsFrames();
 
-    if (FLAGS_quic_allow_http3_priority) {
-      std::string priority_data =
-          GenerateHttp3PriorityData(priority, stream_id);
-      AddQuicStreamFrame(2, false, priority_data);
-    }
+    std::string priority_data = GenerateHttp3PriorityData(priority, stream_id);
+    AddQuicStreamFrame(2, false, priority_data);
 
     std::string data = QpackEncodeHeaders(stream_id, std::move(headers),
                                           spdy_headers_frame_length);
@@ -592,11 +589,8 @@
   if (quic::VersionUsesHttp3(version_.transport_version)) {
     MaybeAddHttp3SettingsFrames();
 
-    if (FLAGS_quic_allow_http3_priority) {
-      std::string priority_data =
-          GenerateHttp3PriorityData(priority, stream_id);
-      AddQuicStreamFrame(2, false, priority_data);
-    }
+    std::string priority_data = GenerateHttp3PriorityData(priority, stream_id);
+    AddQuicStreamFrame(2, false, priority_data);
 
     std::string data = QpackEncodeHeaders(stream_id, std::move(headers),
                                           spdy_headers_frame_length);
@@ -632,11 +626,8 @@
   if (quic::VersionUsesHttp3(version_.transport_version)) {
     MaybeAddHttp3SettingsFrames();
 
-    if (FLAGS_quic_allow_http3_priority) {
-      std::string priority_data =
-          GenerateHttp3PriorityData(priority, stream_id);
-      AddQuicStreamFrame(2, false, priority_data);
-    }
+    std::string priority_data = GenerateHttp3PriorityData(priority, stream_id);
+    AddQuicStreamFrame(2, false, priority_data);
 
     std::string data = QpackEncodeHeaders(stream_id, std::move(headers),
                                           spdy_headers_frame_length);
@@ -794,22 +785,6 @@
     return BuildPacket();
   }
 
-  quic::PriorityFrame frame;
-  frame.weight = weight;
-  frame.exclusive = true;
-  frame.prioritized_element_id = id;
-  frame.element_dependency_id = parent_stream_id;
-  frame.dependency_type = quic::REQUEST_STREAM;
-  frame.prioritized_type =
-      quic::QuicUtils::IsServerInitiatedStreamId(version_.transport_version, id)
-          ? quic::PUSH_STREAM
-          : quic::REQUEST_STREAM;
-  std::unique_ptr<char[]> buffer;
-  quic::QuicByteCount frame_length =
-      quic::HttpEncoder::SerializePriorityFrame(frame, &buffer);
-  std::string priority_data = std::string(buffer.get(), frame_length);
-  AddQuicStreamFrame(2, false, priority_data);
-
   return BuildPacket();
 }
 
@@ -1311,15 +1286,14 @@
 std::string QuicTestPacketMaker::GenerateHttp3PriorityData(
     spdy::SpdyPriority priority,
     quic::QuicStreamId stream_id) {
-  quic::PriorityFrame frame;
-  frame.weight = priority;
-  frame.dependency_type = quic::ROOT_OF_TREE;
-  frame.prioritized_type = quic::REQUEST_STREAM;
-  frame.prioritized_element_id = stream_id;
-
+  quic::PriorityUpdateFrame priority_update;
+  priority_update.prioritized_element_type = quic::REQUEST_STREAM;
+  priority_update.prioritized_element_id = stream_id;
+  priority_update.priority_field_value =
+      quiche::QuicheStrCat("u=", static_cast<int>(priority));
   std::unique_ptr<char[]> buffer;
   quic::QuicByteCount frame_length =
-      quic::HttpEncoder::SerializePriorityFrame(frame, &buffer);
+      quic::HttpEncoder::SerializePriorityUpdateFrame(priority_update, &buffer);
   return std::string(buffer.get(), frame_length);
 }
 
diff --git a/net/quic/quic_transport_client.cc b/net/quic/quic_transport_client.cc
index 7227f73..ffa8244 100644
--- a/net/quic/quic_transport_client.cc
+++ b/net/quic/quic_transport_client.cc
@@ -316,6 +316,12 @@
   visitor_->OnIncomingUnidirectionalStreamAvailable();
 }
 
+void QuicTransportClient::OnIncomingDatagramAvailable() {}
+
+void QuicTransportClient::OnCanCreateNewOutgoingBidirectionalStream() {}
+
+void QuicTransportClient::OnCanCreateNewOutgoingUnidirectionalStream() {}
+
 void QuicTransportClient::OnReadError(int result,
                                       const DatagramClientSocket* socket) {
   error_.net_error = result;
diff --git a/net/quic/quic_transport_client.h b/net/quic/quic_transport_client.h
index 92cd808..1bb0fdb 100644
--- a/net/quic/quic_transport_client.h
+++ b/net/quic/quic_transport_client.h
@@ -114,6 +114,9 @@
   void OnSessionReady() override;
   void OnIncomingBidirectionalStreamAvailable() override;
   void OnIncomingUnidirectionalStreamAvailable() override;
+  void OnIncomingDatagramAvailable() override;
+  void OnCanCreateNewOutgoingBidirectionalStream() override;
+  void OnCanCreateNewOutgoingUnidirectionalStream() override;
 
   // QuicChromiumPacketReader::Visitor methods.
   void OnReadError(int result, const DatagramClientSocket* socket) override;
diff --git a/net/quiche/common/platform/impl/quiche_logging_impl.h b/net/quiche/common/platform/impl/quiche_logging_impl.h
index 5362e69..d3261b0 100644
--- a/net/quiche/common/platform/impl/quiche_logging_impl.h
+++ b/net/quiche/common/platform/impl/quiche_logging_impl.h
@@ -6,5 +6,87 @@
 #define NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_
 
 #include "base/logging.h"
+#include "build/build_config.h"
+#include "net/base/net_export.h"
+
+#define QUICHE_LOG_IMPL(severity) QUICHE_CHROMIUM_LOG_##severity
+#define QUICHE_VLOG_IMPL(verbose_level) VLOG(verbose_level)
+#define QUICHE_LOG_EVERY_N_SEC_IMPL(severity, seconds) QUICHE_LOG_IMPL(severity)
+#define QUICHE_LOG_FIRST_N_IMPL(severity, n) QUICHE_LOG_IMPL(severity)
+#define QUICHE_DLOG_IMPL(severity) QUICHE_CHROMIUM_DLOG_##severity
+#define QUICHE_DLOG_IF_IMPL(severity, condition) \
+  QUICHE_CHROMIUM_DLOG_IF_##severity(condition)
+#define QUICHE_LOG_IF_IMPL(severity, condition) \
+  QUICHE_CHROMIUM_LOG_IF_##severity(condition)
+
+#define QUICHE_CHROMIUM_LOG_INFO VLOG(1)
+#define QUICHE_CHROMIUM_LOG_WARNING DLOG(WARNING)
+#define QUICHE_CHROMIUM_LOG_ERROR DLOG(ERROR)
+#define QUICHE_CHROMIUM_LOG_FATAL LOG(FATAL)
+#define QUICHE_CHROMIUM_LOG_DFATAL LOG(DFATAL)
+
+#define QUICHE_CHROMIUM_DLOG_INFO DVLOG(1)
+#define QUICHE_CHROMIUM_DLOG_WARNING DLOG(WARNING)
+#define QUICHE_CHROMIUM_DLOG_ERROR DLOG(ERROR)
+#define QUICHE_CHROMIUM_DLOG_FATAL DLOG(FATAL)
+#define QUICHE_CHROMIUM_DLOG_DFATAL DLOG(DFATAL)
+
+#define QUICHE_CHROMIUM_LOG_IF_INFO(condition) VLOG_IF(1, condition)
+#define QUICHE_CHROMIUM_LOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
+#define QUICHE_CHROMIUM_LOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
+#define QUICHE_CHROMIUM_LOG_IF_FATAL(condition) LOG_IF(FATAL, condition)
+#define QUICHE_CHROMIUM_LOG_IF_DFATAL(condition) LOG_IF(DFATAL, condition)
+
+#define QUICHE_CHROMIUM_DLOG_IF_INFO(condition) DVLOG_IF(1, condition)
+#define QUICHE_CHROMIUM_DLOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
+#define QUICHE_CHROMIUM_DLOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
+#define QUICHE_CHROMIUM_DLOG_IF_FATAL(condition) DLOG_IF(FATAL, condition)
+#define QUICHE_CHROMIUM_DLOG_IF_DFATAL(condition) DLOG_IF(DFATAL, condition)
+
+#define QUICHE_DVLOG_IMPL(verbose_level) DVLOG(verbose_level)
+#define QUICHE_DVLOG_IF_IMPL(verbose_level, condition) \
+  DVLOG_IF(verbose_level, condition)
+
+#define QUICHE_LOG_INFO_IS_ON_IMPL() 0
+#ifdef NDEBUG
+#define QUICHE_LOG_WARNING_IS_ON_IMPL() 0
+#define QUICHE_LOG_ERROR_IS_ON_IMPL() 0
+#else
+#define QUICHE_LOG_WARNING_IS_ON_IMPL() 1
+#define QUICHE_LOG_ERROR_IS_ON_IMPL() 1
+#endif
+#define QUICHE_DLOG_INFO_IS_ON_IMPL() 0
+
+#if defined(OS_WIN)
+// wingdi.h defines ERROR to be 0. When we call QUICHE_DLOG(ERROR), it gets
+// substituted with 0, and it expands to QUICHE_CHROMIUM_DLOG_0. To allow us to
+// keep using this syntax, we define this macro to do the same thing as
+// QUICHE_CHROMIUM_DLOG_ERROR.
+#define QUICHE_CHROMIUM_LOG_0 QUICHE_CHROMIUM_LOG_ERROR
+#define QUICHE_CHROMIUM_DLOG_0 QUICHE_CHROMIUM_DLOG_ERROR
+#define QUICHE_CHROMIUM_LOG_IF_0 QUICHE_CHROMIUM_LOG_IF_ERROR
+#define QUICHE_CHROMIUM_DLOG_IF_0 QUICHE_CHROMIUM_DLOG_IF_ERROR
+#endif
+
+#define QUICHE_PREDICT_FALSE_IMPL(x) x
+#define QUICHE_PREDICT_TRUE_IMPL(x) x
+
+#define QUICHE_NOTREACHED_IMPL() NOTREACHED()
+
+#define QUICHE_PLOG_IMPL(severity) DVLOG(1)
+
+namespace quic {
+template <typename T>
+NET_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
+                                                   const std::vector<T>& v) {
+  out << "[";
+  const char* sep = "";
+  for (size_t i = 0; i < v.size(); ++i) {
+    out << sep << v[i];
+    sep = ", ";
+  }
+  return out << "]";
+}
+}  // namespace quic
 
 #endif  // NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_
diff --git a/net/quiche/common/platform/impl/quiche_string_piece_impl.h b/net/quiche/common/platform/impl/quiche_string_piece_impl.h
index 0de4c40..9488b87 100644
--- a/net/quiche/common/platform/impl/quiche_string_piece_impl.h
+++ b/net/quiche/common/platform/impl/quiche_string_piece_impl.h
@@ -11,6 +11,13 @@
 
 using QuicheStringPieceImpl = base::StringPiece;
 
+using QuicheStringPieceHashImpl = base::StringPieceHash;
+
+inline size_t QuicheHashStringPairImpl(QuicheStringPieceImpl a,
+                                       QuicheStringPieceImpl b) {
+  return base::StringPieceHash()(a) ^ base::StringPieceHash()(b);
+}
+
 }  // namespace quiche
 
 #endif  // NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_STRING_PIECE_IMPL_H_
diff --git a/net/quiche/common/platform/impl/quiche_test_impl.h b/net/quiche/common/platform/impl/quiche_test_impl.h
index 705a250f..a505bcc 100644
--- a/net/quiche/common/platform/impl/quiche_test_impl.h
+++ b/net/quiche/common/platform/impl/quiche_test_impl.h
@@ -11,6 +11,9 @@
 namespace quiche {
 namespace test {
 class QuicheTest : public ::testing::Test {};
+
+template <class T>
+class QuicheTestWithParamImpl : public ::testing::TestWithParam<T> {};
 }  // namespace test
 }  // namespace quiche
 
diff --git a/net/server/BUILD.gn b/net/server/BUILD.gn
index 1f3e3cb..8ee35c5 100644
--- a/net/server/BUILD.gn
+++ b/net/server/BUILD.gn
@@ -70,9 +70,7 @@
 
 if (enable_websockets) {
   fuzzer_test("net_http_server_fuzzer") {
-    sources = [
-      "http_server_fuzzer.cc",
-    ]
+    sources = [ "http_server_fuzzer.cc" ]
     deps = [
       ":http_server",
       "//base",
diff --git a/net/spdy/fuzzing/hpack_fuzz_util.cc b/net/spdy/fuzzing/hpack_fuzz_util.cc
index 1434dad..d9e8b69 100644
--- a/net/spdy/fuzzing/hpack_fuzz_util.cc
+++ b/net/spdy/fuzzing/hpack_fuzz_util.cc
@@ -108,7 +108,8 @@
 }
 
 // static
-bool HpackFuzzUtil::NextHeaderBlock(Input* input, SpdyStringPiece* out) {
+bool HpackFuzzUtil::NextHeaderBlock(Input* input,
+                                    quiche::QuicheStringPiece* out) {
   // ClusterFuzz may truncate input files if the fuzzer ran out of allocated
   // disk space. Be tolerant of these.
   CHECK_LE(input->offset, input->input.size());
@@ -123,7 +124,7 @@
   if (input->remaining() < length) {
     return false;
   }
-  *out = SpdyStringPiece(input->ptr(), length);
+  *out = quiche::QuicheStringPiece(input->ptr(), length);
   input->offset += length;
   return true;
 }
@@ -145,7 +146,7 @@
 // static
 bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(
     FuzzerContext* context,
-    SpdyStringPiece input_block) {
+    quiche::QuicheStringPiece input_block) {
   // First stage: Decode the input header block. This may fail on invalid input.
   if (!context->first_stage->HandleControlFrameHeadersData(
           input_block.data(), input_block.size())) {
diff --git a/net/spdy/fuzzing/hpack_fuzz_util.h b/net/spdy/fuzzing/hpack_fuzz_util.h
index f581e46..124b889 100644
--- a/net/spdy/fuzzing/hpack_fuzz_util.h
+++ b/net/spdy/fuzzing/hpack_fuzz_util.h
@@ -11,10 +11,10 @@
 #include <memory>
 #include <vector>
 
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
 #include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
 #include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
 #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
 
 namespace spdy {
 
@@ -53,7 +53,7 @@
 
   // Returns true if the next header block was set at |out|. Returns
   // false if no input header blocks remain.
-  static bool NextHeaderBlock(Input* input, SpdyStringPiece* out);
+  static bool NextHeaderBlock(Input* input, quiche::QuicheStringPiece* out);
 
   // Returns the serialized header block length prefix for a block of
   // |block_size| bytes.
@@ -74,8 +74,9 @@
   // Runs |input_block| through |first_stage| and, iff that succeeds,
   // |second_stage| and |third_stage| as well. Returns whether all stages
   // processed the input without error.
-  static bool RunHeaderBlockThroughFuzzerStages(FuzzerContext* context,
-                                                SpdyStringPiece input_block);
+  static bool RunHeaderBlockThroughFuzzerStages(
+      FuzzerContext* context,
+      quiche::QuicheStringPiece input_block);
 
   // Flips random bits within |buffer|. The total number of flips is
   // |flip_per_thousand| bits for every 1,024 bytes of |buffer_length|,
diff --git a/net/spdy/fuzzing/hpack_fuzz_util_test.cc b/net/spdy/fuzzing/hpack_fuzz_util_test.cc
index 5036b1e..670301dd 100644
--- a/net/spdy/fuzzing/hpack_fuzz_util_test.cc
+++ b/net/spdy/fuzzing/hpack_fuzz_util_test.cc
@@ -71,7 +71,7 @@
   HpackFuzzUtil::Input input;
   input.input.assign(fixture, base::size(fixture) - 1);
 
-  SpdyStringPiece block;
+  quiche::QuicheStringPiece block;
 
   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
   EXPECT_EQ("aaaaa", block);
@@ -132,7 +132,7 @@
   HpackFuzzUtil::FuzzerContext context;
   HpackFuzzUtil::InitializeFuzzerContext(&context);
 
-  SpdyStringPiece block;
+  quiche::QuicheStringPiece block;
   while (HpackFuzzUtil::NextHeaderBlock(&input, &block)) {
     // As these are valid examples, all fuzz stages should succeed.
     EXPECT_TRUE(
diff --git a/net/spdy/platform/impl/spdy_containers_impl.h b/net/spdy/platform/impl/spdy_containers_impl.h
index 0e9689d..434b32fc 100644
--- a/net/spdy/platform/impl/spdy_containers_impl.h
+++ b/net/spdy/platform/impl/spdy_containers_impl.h
@@ -29,12 +29,6 @@
 template <typename T, size_t N, typename A = std::allocator<T>>
 using SpdyInlinedVectorImpl = std::vector<T, A>;
 
-using SpdyStringPieceHashImpl = base::StringPieceHash;
-
-inline size_t SpdyHashStringPairImpl(SpdyStringPiece a, SpdyStringPiece b) {
-  return base::StringPieceHash()(a) ^ base::StringPieceHash()(b);
-}
-
 // A map which is faster than (for example) hash_map for a certain number of
 // unique key-value-pair elements, and upgrades itself to unordered_map when
 // runs out of space.
diff --git a/net/spdy/platform/impl/spdy_string_piece_impl.h b/net/spdy/platform/impl/spdy_string_piece_impl.h
deleted file mode 100644
index e6edcd3..0000000
--- a/net/spdy/platform/impl/spdy_string_piece_impl.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SPDY_PLATFORM_IMPL_SPDY_STRING_PIECE_IMPL_H_
-#define NET_SPDY_PLATFORM_IMPL_SPDY_STRING_PIECE_IMPL_H_
-
-#include "base/strings/string_piece.h"
-
-namespace spdy {
-
-using SpdyStringPieceImpl = base::StringPiece;
-
-}  // namespace spdy
-
-#endif  // NET_SPDY_PLATFORM_IMPL_SPDY_STRING_PIECE_IMPL_H_
diff --git a/net/spdy/platform/impl/spdy_string_utils_impl.cc b/net/spdy/platform/impl/spdy_string_utils_impl.cc
index ffc90d56..50c34554 100644
--- a/net/spdy/platform/impl/spdy_string_utils_impl.cc
+++ b/net/spdy/platform/impl/spdy_string_utils_impl.cc
@@ -8,7 +8,7 @@
 
 namespace spdy {
 
-bool SpdyHexDecodeToUInt32Impl(SpdyStringPiece data, uint32_t* out) {
+bool SpdyHexDecodeToUInt32Impl(quiche::QuicheStringPiece data, uint32_t* out) {
   if (data.empty() || data.size() > 8u)
     return false;
   // Pad with leading zeros.
diff --git a/net/spdy/platform/impl/spdy_string_utils_impl.h b/net/spdy/platform/impl/spdy_string_utils_impl.h
index 6c7408ae..d1cc1621 100644
--- a/net/spdy/platform/impl/spdy_string_utils_impl.h
+++ b/net/spdy/platform/impl/spdy_string_utils_impl.h
@@ -12,8 +12,8 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "net/base/hex_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
 #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
 
 namespace spdy {
 
@@ -34,15 +34,16 @@
   return base::HexDigitToInt(c);
 }
 
-inline std::string SpdyHexDecodeImpl(SpdyStringPiece data) {
+inline std::string SpdyHexDecodeImpl(quiche::QuicheStringPiece data) {
   std::string result;
   if (!base::HexStringToString(data, &result))
     result.clear();
   return result;
 }
 
-NET_EXPORT_PRIVATE bool SpdyHexDecodeToUInt32Impl(SpdyStringPiece data,
-                                                  uint32_t* out);
+NET_EXPORT_PRIVATE bool SpdyHexDecodeToUInt32Impl(
+    quiche::QuicheStringPiece data,
+    uint32_t* out);
 
 inline std::string SpdyHexEncodeImpl(const char* bytes, size_t size) {
   return base::ToLowerASCII(base::HexEncode(bytes, size));
@@ -52,12 +53,12 @@
   return base::StringPrintf("%x", data);
 }
 
-inline std::string SpdyHexDumpImpl(SpdyStringPiece data) {
+inline std::string SpdyHexDumpImpl(quiche::QuicheStringPiece data) {
   return net::HexDump(data);
 }
 
 struct SpdyStringPieceCaseHashImpl {
-  size_t operator()(SpdyStringPiece data) const {
+  size_t operator()(quiche::QuicheStringPiece data) const {
     std::string lower = ToLowerASCII(data);
     base::StringPieceHash hasher;
     return hasher(lower);
@@ -65,7 +66,8 @@
 };
 
 struct SpdyStringPieceCaseEqImpl {
-  bool operator()(SpdyStringPiece piece1, SpdyStringPiece piece2) const {
+  bool operator()(quiche::QuicheStringPiece piece1,
+                  quiche::QuicheStringPiece piece2) const {
     return base::EqualsCaseInsensitiveASCII(piece1, piece2);
   }
 };
diff --git a/net/third_party/quiche/OWNERS b/net/third_party/quiche/OWNERS
deleted file mode 100644
index e2c377d2..0000000
--- a/net/third_party/quiche/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-file://net/quic/OWNERS
-
-# COMPONENT: Internals>Network>QUIC
diff --git a/net/tools/huffman_trie/BUILD.gn b/net/tools/huffman_trie/BUILD.gn
index c172af0f2..efa731b1 100644
--- a/net/tools/huffman_trie/BUILD.gn
+++ b/net/tools/huffman_trie/BUILD.gn
@@ -15,9 +15,7 @@
     "trie_entry.cc",
     "trie_entry.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("huffman_trie_generator_test_sources") {
diff --git a/net/tools/transport_security_state_generator/BUILD.gn b/net/tools/transport_security_state_generator/BUILD.gn
index 9c80262..1c01def 100644
--- a/net/tools/transport_security_state_generator/BUILD.gn
+++ b/net/tools/transport_security_state_generator/BUILD.gn
@@ -46,9 +46,7 @@
 }
 
 executable("transport_security_state_generator") {
-  sources = [
-    "transport_security_state_generator.cc",
-  ]
+  sources = [ "transport_security_state_generator.cc" ]
   deps = [
     ":transport_security_state_generator_sources",
     "//base",
diff --git a/net/traffic_annotation/BUILD.gn b/net/traffic_annotation/BUILD.gn
index 771970a0..dcaede5 100644
--- a/net/traffic_annotation/BUILD.gn
+++ b/net/traffic_annotation/BUILD.gn
@@ -1,18 +1,10 @@
 source_set("traffic_annotation") {
-  sources = [
-    "network_traffic_annotation.h",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "network_traffic_annotation.h" ]
+  deps = [ "//base" ]
 }
 
 source_set("test_support") {
   testonly = true
-  sources = [
-    "network_traffic_annotation_test_helper.h",
-  ]
-  public_deps = [
-    ":traffic_annotation",
-  ]
+  sources = [ "network_traffic_annotation_test_helper.h" ]
+  public_deps = [ ":traffic_annotation" ]
 }
diff --git a/net/trust_tokens/BUILD.gn b/net/trust_tokens/BUILD.gn
index 48e6e55..9aec1d17 100644
--- a/net/trust_tokens/BUILD.gn
+++ b/net/trust_tokens/BUILD.gn
@@ -33,9 +33,7 @@
 source_set("tests") {
   testonly = true
 
-  sources = [
-    "trust_token_persister_unittest.cc",
-  ]
+  sources = [ "trust_token_persister_unittest.cc" ]
 
   deps = [
     ":public_proto",
@@ -51,9 +49,7 @@
 # public.proto contains datatypes intended
 # to be exposed to //net consumers.
 proto_library("public_proto") {
-  sources = [
-    "proto/public.proto",
-  ]
+  sources = [ "proto/public.proto" ]
 }
 
 # storage.proto contains datatypes internal
@@ -64,10 +60,6 @@
     ":trust_tokens",
     ":tests",
   ]
-  sources = [
-    "proto/storage.proto",
-  ]
-  deps = [
-    ":public_proto",
-  ]
+  sources = [ "proto/storage.proto" ]
+  deps = [ ":public_proto" ]
 }
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index b00a88cf..7942d60 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -34,9 +34,7 @@
 # the setuid sandbox and is its own target.
 
 group("sandbox") {
-  public_deps = [
-    ":sandbox_services",
-  ]
+  public_deps = [ ":sandbox_services" ]
   if (compile_suid_client || is_nacl_nonsfi) {
     public_deps += [ ":suid_sandbox_client" ]
   }
@@ -59,9 +57,7 @@
     "tests/unit_tests.h",
   ]
 
-  deps = [
-    "//testing/gtest",
-  ]
+  deps = [ "//testing/gtest" ]
 
   if (!is_nacl_nonsfi) {
     sources += [
@@ -191,17 +187,13 @@
     "bpf_dsl/golden/x86-64/NegativeConstantsPolicy.txt",
     "bpf_dsl/golden/x86-64/SwitchPolicy.txt",
   ]
-  outputs = [
-    "$target_gen_dir/bpf_dsl/golden/golden_files.h",
-  ]
+  outputs = [ "$target_gen_dir/bpf_dsl/golden/golden_files.h" ]
   args =
       rebase_path(outputs, root_build_dir) + rebase_path(inputs, root_build_dir)
 }
 
 test("sandbox_linux_unittests") {
-  deps = [
-    ":sandbox_linux_unittests_sources",
-  ]
+  deps = [ ":sandbox_linux_unittests_sources" ]
   if (is_android) {
     use_raw_android_executable = true
   }
@@ -358,9 +350,7 @@
 
   defines = [ "SANDBOX_IMPLEMENTATION" ]
 
-  public_deps = [
-    "//sandbox:sandbox_export",
-  ]
+  public_deps = [ "//sandbox:sandbox_export" ]
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
@@ -445,9 +435,7 @@
       "suid/common/suid_unsafe_environment_variables.h",
     ]
     defines = [ "SANDBOX_IMPLEMENTATION" ]
-    public_deps = [
-      "//sandbox:sandbox_export",
-    ]
+    public_deps = [ "//sandbox:sandbox_export" ]
     deps = [
       ":sandbox_services",
       "//base",
diff --git a/services/device/public/cpp/bluetooth/BUILD.gn b/services/device/public/cpp/bluetooth/BUILD.gn
index b7418d5bf..cef8c766 100644
--- a/services/device/public/cpp/bluetooth/BUILD.gn
+++ b/services/device/public/cpp/bluetooth/BUILD.gn
@@ -20,9 +20,7 @@
 source_set("bluetooth_tests") {
   testonly = true
 
-  sources = [
-    "bluetooth_utils_unittest.cc",
-  ]
+  sources = [ "bluetooth_utils_unittest.cc" ]
 
   deps = [
     ":bluetooth",
diff --git a/services/preferences/public/mojom/BUILD.gn b/services/preferences/public/mojom/BUILD.gn
index 8c6fcd0..b33aca2c 100644
--- a/services/preferences/public/mojom/BUILD.gn
+++ b/services/preferences/public/mojom/BUILD.gn
@@ -9,7 +9,5 @@
     "preferences.mojom",
     "tracked_preference_validation_delegate.mojom",
   ]
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/services/service_manager/BUILD.gn b/services/service_manager/BUILD.gn
index 544b248b..25d7a7c 100644
--- a/services/service_manager/BUILD.gn
+++ b/services/service_manager/BUILD.gn
@@ -6,9 +6,7 @@
 
 group("all") {
   testonly = true
-  deps = [
-    ":service_manager",
-  ]
+  deps = [ ":service_manager" ]
 
   if (!is_ios) {
     deps += [
diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn
index 5ab17d3..b125e59 100644
--- a/services/service_manager/embedder/BUILD.gn
+++ b/services/service_manager/embedder/BUILD.gn
@@ -67,14 +67,10 @@
     "switches.cc",
     "switches.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   defines = [ "IS_SERVICE_MANAGER_EMBEDDER_SWITCHES_IMPL" ]
 }
 
 source_set("embedder_result_codes") {
-  sources = [
-    "result_codes.h",
-  ]
+  sources = [ "result_codes.h" ]
 }
diff --git a/services/service_manager/public/cpp/BUILD.gn b/services/service_manager/public/cpp/BUILD.gn
index 344e326..8cb04e2e 100644
--- a/services/service_manager/public/cpp/BUILD.gn
+++ b/services/service_manager/public/cpp/BUILD.gn
@@ -48,9 +48,7 @@
     "//url",
   ]
 
-  deps = [
-    "//services/tracing/public/cpp:traced_process",
-  ]
+  deps = [ "//services/tracing/public/cpp:traced_process" ]
 
   defines = [
     "IS_SERVICE_MANAGER_CPP_IMPL",
@@ -80,9 +78,7 @@
 
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-  deps = [
-    "//services/service_manager/public/mojom:constants",
-  ]
+  deps = [ "//services/service_manager/public/mojom:constants" ]
 
   defines = [
     "IS_SERVICE_MANAGER_CPP_TYPES_IMPL",
@@ -131,7 +127,5 @@
 
 mojom("test_mojom") {
   testonly = true
-  sources = [
-    "standalone_connector_impl_unittest.test-mojom",
-  ]
+  sources = [ "standalone_connector_impl_unittest.test-mojom" ]
 }
diff --git a/services/service_manager/public/cpp/service_executable/BUILD.gn b/services/service_manager/public/cpp/service_executable/BUILD.gn
index 3dff0e5..d62e2b3 100644
--- a/services/service_manager/public/cpp/service_executable/BUILD.gn
+++ b/services/service_manager/public/cpp/service_executable/BUILD.gn
@@ -47,17 +47,11 @@
 # Note that GN targets based on the service_executable() template defined in
 # service_executable.gni implicitly link against this.
 source_set("main") {
-  public = [
-    "service_main.h",
-  ]
+  public = [ "service_main.h" ]
 
-  sources = [
-    "main.cc",
-  ]
+  sources = [ "main.cc" ]
 
-  public_deps = [
-    "//services/service_manager/public/mojom",
-  ]
+  public_deps = [ "//services/service_manager/public/mojom" ]
 
   deps = [
     ":support",
diff --git a/services/service_manager/public/cpp/test/BUILD.gn b/services/service_manager/public/cpp/test/BUILD.gn
index 53edf5d..0150193 100644
--- a/services/service_manager/public/cpp/test/BUILD.gn
+++ b/services/service_manager/public/cpp/test/BUILD.gn
@@ -21,7 +21,5 @@
     "//services/service_manager/public/mojom",
   ]
 
-  deps = [
-    "//mojo/public/cpp/bindings",
-  ]
+  deps = [ "//mojo/public/cpp/bindings" ]
 }
diff --git a/services/service_manager/public/mojom/BUILD.gn b/services/service_manager/public/mojom/BUILD.gn
index 0ca4819..a9e2eca0 100644
--- a/services/service_manager/public/mojom/BUILD.gn
+++ b/services/service_manager/public/mojom/BUILD.gn
@@ -29,7 +29,5 @@
   generate_java = true
   output_prefix = "service_manager_mojom_constants"
   macro_prefix = "SERVICE_MANAGER_MOJOM_CONSTANTS"
-  sources = [
-    "constants.mojom",
-  ]
+  sources = [ "constants.mojom" ]
 }
diff --git a/services/service_manager/tests/BUILD.gn b/services/service_manager/tests/BUILD.gn
index 40e8889..b6d2e77 100644
--- a/services/service_manager/tests/BUILD.gn
+++ b/services/service_manager/tests/BUILD.gn
@@ -8,9 +8,7 @@
 
 group("tests") {
   testonly = true
-  deps = [
-    ":service_manager_unittests",
-  ]
+  deps = [ ":service_manager_unittests" ]
 }
 
 test("service_manager_unittests") {
@@ -39,9 +37,7 @@
     "//testing/gtest",
   ]
 
-  data_deps = [
-    ":background_service_manager_test_service",
-  ]
+  data_deps = [ ":background_service_manager_test_service" ]
 
   if (!is_ios) {
     sources += [ "service_process_launcher_unittest.cc" ]
@@ -77,9 +73,7 @@
 service_executable("background_service_manager_test_service") {
   testonly = true
 
-  sources = [
-    "background_service_manager_test_service_main.cc",
-  ]
+  sources = [ "background_service_manager_test_service_main.cc" ]
 
   deps = [
     ":interfaces",
@@ -93,7 +87,5 @@
 service_executable("service_process_launcher_test_service") {
   testonly = true
 
-  sources = [
-    "service_process_launcher_test_service_main.cc",
-  ]
+  sources = [ "service_process_launcher_test_service_main.cc" ]
 }
diff --git a/services/service_manager/tests/connect/BUILD.gn b/services/service_manager/tests/connect/BUILD.gn
index b7499748..4008adf 100644
--- a/services/service_manager/tests/connect/BUILD.gn
+++ b/services/service_manager/tests/connect/BUILD.gn
@@ -8,9 +8,7 @@
 
 source_set("connect") {
   testonly = true
-  sources = [
-    "connect_unittest.cc",
-  ]
+  sources = [ "connect_unittest.cc" ]
   deps = [
     ":interfaces",
     "//base",
@@ -33,9 +31,7 @@
 
 mojom("interfaces") {
   testonly = true
-  sources = [
-    "connect.test-mojom",
-  ]
+  sources = [ "connect.test-mojom" ]
   deps = [
     "//mojo/public/mojom/base",
     "//services/service_manager/public/mojom",
@@ -44,9 +40,7 @@
 
 service_executable("connect_test_package") {
   testonly = true
-  sources = [
-    "connect_test_package.cc",
-  ]
+  sources = [ "connect_test_package.cc" ]
   deps = [
     ":interfaces",
     "//base",
@@ -58,9 +52,7 @@
 
 service_executable("connect_test_app") {
   testonly = true
-  sources = [
-    "connect_test_app.cc",
-  ]
+  sources = [ "connect_test_app.cc" ]
   deps = [
     ":interfaces",
     "//base",
@@ -72,9 +64,7 @@
 
 service_executable("connect_test_class_app") {
   testonly = true
-  sources = [
-    "connect_test_class_app.cc",
-  ]
+  sources = [ "connect_test_class_app.cc" ]
   deps = [
     ":interfaces",
     "//base",
@@ -86,9 +76,7 @@
 
 service_executable("connect_test_singleton_app") {
   testonly = true
-  sources = [
-    "connect_test_singleton_app.cc",
-  ]
+  sources = [ "connect_test_singleton_app.cc" ]
   deps = [
     "//base",
     "//mojo/public/cpp/system",
@@ -99,9 +87,7 @@
 executable("connect_test_exe") {
   testonly = true
 
-  sources = [
-    "connect_test_exe.cc",
-  ]
+  sources = [ "connect_test_exe.cc" ]
 
   deps = [
     ":interfaces",
diff --git a/services/service_manager/tests/lifecycle/BUILD.gn b/services/service_manager/tests/lifecycle/BUILD.gn
index e8a2fc3..6e41cc3 100644
--- a/services/service_manager/tests/lifecycle/BUILD.gn
+++ b/services/service_manager/tests/lifecycle/BUILD.gn
@@ -8,9 +8,7 @@
 
 source_set("lifecycle") {
   testonly = true
-  sources = [
-    "lifecycle_unittest.cc",
-  ]
+  sources = [ "lifecycle_unittest.cc" ]
   deps = [
     ":interfaces",
     "//base",
@@ -30,9 +28,7 @@
 
 mojom("interfaces") {
   testonly = true
-  sources = [
-    "lifecycle.test-mojom",
-  ]
+  sources = [ "lifecycle.test-mojom" ]
 }
 
 source_set("app_client") {
@@ -51,9 +47,7 @@
 
 service_executable("lifecycle_unittest_package") {
   testonly = true
-  sources = [
-    "package.cc",
-  ]
+  sources = [ "package.cc" ]
   deps = [
     ":app_client",
     ":interfaces",
@@ -65,9 +59,7 @@
 
 service_executable("lifecycle_unittest_app") {
   testonly = true
-  sources = [
-    "app.cc",
-  ]
+  sources = [ "app.cc" ]
   deps = [
     ":app_client",
     ":interfaces",
@@ -78,9 +70,7 @@
 
 service_executable("lifecycle_unittest_parent") {
   testonly = true
-  sources = [
-    "parent.cc",
-  ]
+  sources = [ "parent.cc" ]
   deps = [
     ":interfaces",
     "//base",
diff --git a/services/service_manager/tests/sandbox/BUILD.gn b/services/service_manager/tests/sandbox/BUILD.gn
index ff7a6b4..3905b0e 100644
--- a/services/service_manager/tests/sandbox/BUILD.gn
+++ b/services/service_manager/tests/sandbox/BUILD.gn
@@ -4,9 +4,7 @@
 
 source_set("sandbox") {
   testonly = true
-  sources = [
-    "sandbox_type_unittest.cc",
-  ]
+  sources = [ "sandbox_type_unittest.cc" ]
   deps = [
     "//base",
     "//services/service_manager/sandbox",
diff --git a/services/service_manager/tests/service_manager/BUILD.gn b/services/service_manager/tests/service_manager/BUILD.gn
index 43dedc31..ec04b72b 100644
--- a/services/service_manager/tests/service_manager/BUILD.gn
+++ b/services/service_manager/tests/service_manager/BUILD.gn
@@ -36,13 +36,9 @@
 
 mojom("interfaces") {
   testonly = true
-  sources = [
-    "service_manager.test-mojom",
-  ]
+  sources = [ "service_manager.test-mojom" ]
 
-  deps = [
-    "//services/service_manager/public/mojom",
-  ]
+  deps = [ "//services/service_manager/public/mojom" ]
 }
 
 source_set("test_manifests") {
@@ -62,9 +58,7 @@
 executable("service_manager_unittest_target") {
   testonly = true
 
-  sources = [
-    "target.cc",
-  ]
+  sources = [ "target.cc" ]
 
   deps = [
     ":interfaces",
@@ -78,9 +72,7 @@
 
 service_executable("service_manager_unittest_embedder") {
   testonly = true
-  sources = [
-    "embedder.cc",
-  ]
+  sources = [ "embedder.cc" ]
 
   deps = [
     ":interfaces",
diff --git a/services/service_manager/tests/shutdown/BUILD.gn b/services/service_manager/tests/shutdown/BUILD.gn
index 249b590a..553afd9 100644
--- a/services/service_manager/tests/shutdown/BUILD.gn
+++ b/services/service_manager/tests/shutdown/BUILD.gn
@@ -8,9 +8,7 @@
 
 source_set("shutdown") {
   testonly = true
-  sources = [
-    "shutdown_unittest.cc",
-  ]
+  sources = [ "shutdown_unittest.cc" ]
 
   deps = [
     ":interfaces",
@@ -33,16 +31,12 @@
 
 mojom("interfaces") {
   testonly = true
-  sources = [
-    "shutdown.test-mojom",
-  ]
+  sources = [ "shutdown.test-mojom" ]
 }
 
 service_executable("shutdown_service") {
   testonly = true
-  sources = [
-    "shutdown_service_app.cc",
-  ]
+  sources = [ "shutdown_service_app.cc" ]
   deps = [
     ":interfaces",
     "//base",
@@ -53,9 +47,7 @@
 
 service_executable("shutdown_client") {
   testonly = true
-  sources = [
-    "shutdown_client_app.cc",
-  ]
+  sources = [ "shutdown_client_app.cc" ]
   deps = [
     ":interfaces",
     "//base",
diff --git a/services/tracing/public/cpp/BUILD.gn b/services/tracing/public/cpp/BUILD.gn
index 37aa9b7..b412100 100644
--- a/services/tracing/public/cpp/BUILD.gn
+++ b/services/tracing/public/cpp/BUILD.gn
@@ -17,14 +17,42 @@
 
   public_deps = [ "//services/tracing/public/mojom" ]
 
-  if (!is_nacl && !is_ios) {
-    deps = [ ":cpp" ]
-  }
+  deps = [ ":cpp" ]
 }
 
+# On IOS and NACL we don't support tracing so we only include the minimum needed
+# to support a fake typed TRACE_EVENT macro. However this means we don't have
+# any .cc files and thus on iOS and NaCl it needs to be a source_set and not a
+# component. |tracing_lib_type| decides which version to build.
 if (!is_nacl && !is_ios) {
-  component("cpp") {
-    sources = [
+  tracing_lib_type = "component"
+} else {
+  tracing_lib_type = "source_set"
+}
+
+target(tracing_lib_type, "cpp") {
+  sources = [
+    "perfetto/event_context.h",
+    "perfetto/macros.h",
+    "perfetto/macros_internal.h",
+  ]
+
+  defines = [ "IS_TRACING_CPP_IMPL" ]
+  output_name = "tracing_cpp"
+
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
+  public_deps = [
+    "//base",
+    "//third_party/perfetto:libperfetto",
+  ]
+
+  deps = [ "//third_party/perfetto/include/perfetto/protozero" ]
+
+  all_dependent_configs = [ "//third_party/perfetto/gn:public_config" ]
+
+  if (!is_nacl && !is_ios) {
+    sources += [
       "base_agent.cc",
       "base_agent.h",
       "perfetto/dummy_producer.cc",
@@ -40,9 +68,7 @@
       "perfetto/java_heap_profiler/hprof_parser_android.h",
       "perfetto/java_heap_profiler/java_heap_profiler_android.cc",
       "perfetto/java_heap_profiler/java_heap_profiler_android.h",
-      "perfetto/macros.h",
       "perfetto/macros_internal.cc",
-      "perfetto/macros_internal.h",
       "perfetto/perfetto_config.cc",
       "perfetto/perfetto_config.h",
       "perfetto/perfetto_producer.cc",
@@ -79,24 +105,14 @@
       "tracing_features.h",
     ]
 
-    defines = [ "IS_TRACING_CPP_IMPL" ]
-    output_name = "tracing_cpp"
-
-    configs += [ "//build/config/compiler:wexit_time_destructors" ]
-
-    public_deps = [
-      "//base",
+    public_deps += [
       "//components/tracing:startup_tracing",
       "//mojo/public/cpp/bindings",
       "//services/tracing/public/mojom",
-      "//third_party/perfetto:libperfetto",
     ]
 
-    all_dependent_configs = [ "//third_party/perfetto/gn:public_config" ]
-
-    deps = [
+    deps += [
       "//build:chromecast_buildflags",
-      "//third_party/perfetto/include/perfetto/protozero",
       "//third_party/perfetto/protos/perfetto/trace/chrome:minimal_complete_lite",
     ]
 
@@ -122,5 +138,5 @@
       # stack_unwinder_android.cc overrides the dl_unwind_find_exidx function.
       all_dependent_configs += [ ":wrap_find_exidx" ]
     }
-  }
-}  # !is_nacl && !is_ios
+  }  # !is_ios && !is_nacl
+}
diff --git a/services/tracing/public/cpp/perfetto/macros.h b/services/tracing/public/cpp/perfetto/macros.h
index 28a72abd..0ee1edac 100644
--- a/services/tracing/public/cpp/perfetto/macros.h
+++ b/services/tracing/public/cpp/perfetto/macros.h
@@ -8,6 +8,11 @@
 #include "base/trace_event/trace_event.h"
 #include "services/tracing/public/cpp/perfetto/macros_internal.h"
 
+// Needed not for this file but for every user of the TRACE_EVENT macros for the
+// lambda definition. So included here for convenience.
+#include "services/tracing/public/cpp/perfetto/event_context.h"
+#include "third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h"
+
 #if defined(TRACE_EVENT_BEGIN)
 #error "Another copy of perfetto tracing macros have been included"
 #endif
diff --git a/services/tracing/public/cpp/perfetto/macros_internal.h b/services/tracing/public/cpp/perfetto/macros_internal.h
index d30d7d7..cbe0240 100644
--- a/services/tracing/public/cpp/perfetto/macros_internal.h
+++ b/services/tracing/public/cpp/perfetto/macros_internal.h
@@ -5,14 +5,18 @@
 #ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_INTERNAL_H_
 #define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_INTERNAL_H_
 
+#include "build/build_config.h"
+
+namespace perfetto {
+class EventContext;
+}
+
+#if !defined(OS_IOS) && !defined(OS_NACL)
+
 #include "base/component_export.h"
 #include "base/trace_event/trace_event.h"
 #include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
 
-namespace perfetto {
-class TrackEventContext;
-}
-
 namespace tracing {
 namespace internal {
 base::Optional<base::trace_event::TraceEvent> COMPONENT_EXPORT(TRACING_CPP)
@@ -24,7 +28,7 @@
 // A simple function that will add the TraceEvent requested and will call the
 // |argument_func| after the track_event has been filled in.
 template <
-    typename TrackEventArgumentFunction = void (*)(perfetto::TrackEventContext)>
+    typename TrackEventArgumentFunction = void (*)(perfetto::EventContext)>
 static inline base::trace_event::TraceEventHandle AddTraceEvent(
     char phase,
     const unsigned char* category_group_enabled,
@@ -87,4 +91,33 @@
     return 0;                                                                 \
   }()};
 
+#else  // !defined(OS_IOS) && !defined(OS_NACL)
+
+// Tracing isn't supported on IOS or NACL so we just black hole all the
+// parameters into a function that doesn't do anything. This ensures that no
+// warnings about unused parameters are generated.
+
+namespace tracing {
+namespace internal {
+template <
+    typename TrackEventArgumentFunction = void (*)(perfetto::EventContext)>
+static inline base::trace_event::TraceEventHandle AddTraceEvent(
+    char,
+    const unsigned char*,
+    const char*,
+    unsigned int,
+    TrackEventArgumentFunction) {
+  return {0, 0, 0};
+}
+}  // namespace internal
+}  // namespace tracing
+
+#define TRACING_INTERNAL_ADD_TRACE_EVENT(phase, category, name, flags, ...) \
+  tracing::internal::AddTraceEvent(phase, nullptr, name, flags, ##__VA_ARGS__);
+
+#define TRACING_INTERNAL_SCOPED_ADD_TRACE_EVENT(category, name, ...)           \
+  TRACING_INTERNAL_ADD_TRACE_EVENT('B', category, name, TRACE_EVENT_FLAG_NONE, \
+                                   ##__VA_ARGS__);
+#endif  // else of !defined(OS_IOS) && !defined(OS_NACL)
+
 #endif  // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_INTERNAL_H_
diff --git a/services/viz/privileged/mojom/BUILD.gn b/services/viz/privileged/mojom/BUILD.gn
index d6af03a..3ce7105 100644
--- a/services/viz/privileged/mojom/BUILD.gn
+++ b/services/viz/privileged/mojom/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "viz_main.mojom",
-  ]
+  sources = [ "viz_main.mojom" ]
 
   public_deps = [
     "//components/discardable_memory/public/mojom",
@@ -22,9 +20,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "mojom_traits_unittest.cc",
-  ]
+  sources = [ "mojom_traits_unittest.cc" ]
 
   deps = [
     "//base/test:test_support",
diff --git a/services/viz/public/cpp/compositing/BUILD.gn b/services/viz/public/cpp/compositing/BUILD.gn
index 96a1b79..1a42aed 100644
--- a/services/viz/public/cpp/compositing/BUILD.gn
+++ b/services/viz/public/cpp/compositing/BUILD.gn
@@ -5,9 +5,7 @@
 source_set("tests") {
   testonly = true
 
-  sources = [
-    "mojom_traits_unittest.cc",
-  ]
+  sources = [ "mojom_traits_unittest.cc" ]
 
   deps = [
     "//base/test:test_support",
@@ -30,9 +28,7 @@
 source_set("perftests") {
   testonly = true
 
-  sources = [
-    "mojom_traits_perftest.cc",
-  ]
+  sources = [ "mojom_traits_perftest.cc" ]
 
   deps = [
     "//base",
diff --git a/services/viz/public/cpp/hit_test/BUILD.gn b/services/viz/public/cpp/hit_test/BUILD.gn
index fbb9801..3201f17 100644
--- a/services/viz/public/cpp/hit_test/BUILD.gn
+++ b/services/viz/public/cpp/hit_test/BUILD.gn
@@ -5,9 +5,7 @@
 source_set("tests") {
   testonly = true
 
-  sources = [
-    "mojom_traits_unittest.cc",
-  ]
+  sources = [ "mojom_traits_unittest.cc" ]
 
   deps = [
     "//base/test:test_support",
diff --git a/testing/perf/BUILD.gn b/testing/perf/BUILD.gn
index 9ada240..1fd16d19 100644
--- a/testing/perf/BUILD.gn
+++ b/testing/perf/BUILD.gn
@@ -20,9 +20,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "luci_test_result_unittest.cc",
-  ]
+  sources = [ "luci_test_result_unittest.cc" ]
   deps = [
     ":perf",
     "//base",
diff --git a/third_party/android_media/BUILD.gn b/third_party/android_media/BUILD.gn
index 00d59cda..ef15782 100644
--- a/third_party/android_media/BUILD.gn
+++ b/third_party/android_media/BUILD.gn
@@ -16,9 +16,8 @@
 }
 
 android_library("android_media_java") {
-  sources = [
-    "java/src/org/chromium/third_party/android/media/MediaController.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/third_party/android/media/MediaController.java" ]
   deps = [
     ":android_media_resources",
     "//third_party/android_deps:android_support_v7_appcompat_java",
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index b003d6e..bcc9ab1 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -88,6 +88,7 @@
     "origin_trials/trial_token_validator.cc",
     "page/page_zoom.cc",
     "peerconnection/webrtc_ip_handling_policy.cc",
+    "permissions/permission_utils.cc",
     "scheduler/web_scheduler_tracked_feature.cc",
     "service_worker/service_worker_status_code.cc",
     "service_worker/service_worker_type_converters.cc",
diff --git a/third_party/blink/common/permissions/OWNERS b/third_party/blink/common/permissions/OWNERS
new file mode 100644
index 0000000..d83a9c5
--- /dev/null
+++ b/third_party/blink/common/permissions/OWNERS
@@ -0,0 +1,3 @@
+file://third_party/blink/renderer/modules/permissions/OWNERS
+
+# COMPONENT: Blink>PermissionsAPI
diff --git a/third_party/blink/common/permissions/permission_utils.cc b/third_party/blink/common/permissions/permission_utils.cc
new file mode 100644
index 0000000..fffd8eef
--- /dev/null
+++ b/third_party/blink/common/permissions/permission_utils.cc
@@ -0,0 +1,22 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/permissions/permission_utils.h"
+
+#include "base/logging.h"
+
+namespace blink {
+
+mojom::PermissionStatus ToPermissionStatus(const std::string& status) {
+  if (status == "granted")
+    return mojom::PermissionStatus::GRANTED;
+  if (status == "prompt")
+    return mojom::PermissionStatus::ASK;
+  if (status == "denied")
+    return mojom::PermissionStatus::DENIED;
+  NOTREACHED();
+  return mojom::PermissionStatus::DENIED;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index 754e90b1..11b861d 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -133,6 +133,7 @@
     "page/page_visibility_state.h",
     "page/page_zoom.h",
     "peerconnection/webrtc_ip_handling_policy.h",
+    "permissions/permission_utils.h",
     "plugin/plugin_action.h",
     "prerender/prerender_rel_type.h",
     "presentation/presentation_receiver_flags.h",
diff --git a/third_party/blink/public/common/permissions/OWNERS b/third_party/blink/public/common/permissions/OWNERS
new file mode 100644
index 0000000..d83a9c5
--- /dev/null
+++ b/third_party/blink/public/common/permissions/OWNERS
@@ -0,0 +1,3 @@
+file://third_party/blink/renderer/modules/permissions/OWNERS
+
+# COMPONENT: Blink>PermissionsAPI
diff --git a/third_party/blink/public/common/permissions/permission_utils.h b/third_party/blink/public/common/permissions/permission_utils.h
new file mode 100644
index 0000000..d623fc6
--- /dev/null
+++ b/third_party/blink/public/common/permissions/permission_utils.h
@@ -0,0 +1,22 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PERMISSIONS_PERMISSION_UTILS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PERMISSIONS_PERMISSION_UTILS_H_
+
+#include <string>
+
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom-shared.h"
+
+namespace blink {
+
+// Converts a permission string ("granted", "denied", "prompt") into a
+// PermissionStatus.
+BLINK_COMMON_EXPORT mojom::PermissionStatus ToPermissionStatus(
+    const std::string& status);
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PERMISSIONS_PERMISSION_UTILS_H_
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 0a20300..15059dc 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -95,6 +95,7 @@
     "payments/payment_app.mojom",
     "peerconnection/peer_connection_tracker.mojom",
     "permissions/permission.mojom",
+    "permissions/permission_automation.mojom",
     "permissions/permission_status.mojom",
     "picture_in_picture/picture_in_picture.mojom",
     "plugins/plugin_registry.mojom",
diff --git a/third_party/blink/public/mojom/permissions/permission_automation.mojom b/third_party/blink/public/mojom/permissions/permission_automation.mojom
new file mode 100644
index 0000000..9442f56
--- /dev/null
+++ b/third_party/blink/public/mojom/permissions/permission_automation.mojom
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.test.mojom;
+
+import "third_party/blink/public/mojom/permissions/permission.mojom";
+import "third_party/blink/public/mojom/permissions/permission_status.mojom";
+import "url/mojom/url.mojom";
+
+// Provides a way for tests to change the permission returned to permission
+// requests of a certain type (via the PermissionService interface).
+// See https://w3c.github.io/permissions/#automation
+interface PermissionAutomation {
+  // Sets the permission for |descriptor| to |status| when queried or requested
+  // in |origin| from |embedding_origin|.
+  SetPermission(blink.mojom.PermissionDescriptor descriptor,
+                blink.mojom.PermissionStatus status,
+                url.mojom.Url origin,
+                url.mojom.Url embedding_origin) => (bool success);
+};
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits.h
index 09c4a775..b0d747e04 100644
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits.h
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits.h
@@ -15,33 +15,6 @@
 
 class ExceptionState;
 
-// NativeValueTraitsBase is supposed to be inherited by NativeValueTraits
-// classes. They serve as a way to hold the ImplType typedef without requiring
-// all NativeValueTraits specializations to declare it.
-//
-// The primary template below is used by NativeValueTraits specializations with
-// types that do not inherit from IDLBase, in which case it is assumed the type
-// of the specialization is also |ImplType|. The NativeValueTraitsBase
-// specialization is used for IDLBase-based types, which are supposed to have
-// their own |ImplType| typedefs.
-//
-// If present, |NullValue()| will be used when converting from the nullable type
-// T?, and should be used if the impl type has an existing "null" state. If not
-// present, WTF::Optional will be used to wrap the type.
-template <typename T, typename SFINAEHelper = void>
-struct NativeValueTraitsBase {
-  using ImplType = T;
-  STATIC_ONLY(NativeValueTraitsBase);
-};
-
-template <typename T>
-struct NativeValueTraitsBase<
-    T,
-    std::enable_if_t<std::is_base_of<IDLBase, T>::value>> {
-  using ImplType = typename T::ImplType;
-  STATIC_ONLY(NativeValueTraitsBase);
-};
-
 // Primary template for NativeValueTraits. It is not supposed to be used
 // directly: there needs to be a specialization for each type which represents
 // a JavaScript type that will be converted to a C++ representation.
@@ -70,6 +43,49 @@
 //   NativeValue(v8::Isolate*, v8::Local<v8::Value>, ExceptionState&);
 // };
 
+// NativeValueTraitsBase is supposed to be inherited by NativeValueTraits
+// classes. They serve as a way to hold the ImplType typedef without requiring
+// all NativeValueTraits specializations to declare it.
+//
+// The primary template below is used by NativeValueTraits specializations with
+// types that do not inherit from IDLBase, in which case it is assumed the type
+// of the specialization is also |ImplType|. The NativeValueTraitsBase
+// specialization is used for IDLBase-based types, which are supposed to have
+// their own |ImplType| typedefs.
+//
+// If present, |NullValue()| will be used when converting from the nullable type
+// T?, and should be used if the impl type has an existing "null" state. If not
+// present, WTF::Optional will be used to wrap the type.
+template <typename T, typename SFINAEHelper = void>
+struct NativeValueTraitsBase {
+  STATIC_ONLY(NativeValueTraitsBase);
+
+  using ImplType = T;
+
+  static decltype(auto) ArgumentValue(v8::Isolate* isolate,
+                                      int argument_index,
+                                      v8::Local<v8::Value> value,
+                                      ExceptionState& exception_state) {
+    return NativeValueTraits<T>::NativeValue(isolate, value, exception_state);
+  }
+};
+
+template <typename T>
+struct NativeValueTraitsBase<
+    T,
+    std::enable_if_t<std::is_base_of<IDLBase, T>::value>> {
+  STATIC_ONLY(NativeValueTraitsBase);
+
+  using ImplType = typename T::ImplType;
+
+  static decltype(auto) ArgumentValue(v8::Isolate* isolate,
+                                      int argument_index,
+                                      v8::Local<v8::Value> value,
+                                      ExceptionState& exception_state) {
+    return NativeValueTraits<T>::NativeValue(isolate, value, exception_state);
+  }
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
index a6f69cd..6336464 100644
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -50,13 +50,6 @@
                           ExceptionState& exception_state) {
     return ToBoolean(isolate, value, exception_state);
   }
-
-  static bool ArgumentValue(v8::Isolate* isolate,
-                            int argument_index,
-                            v8::Local<v8::Value> value,
-                            ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // Integers
@@ -68,13 +61,6 @@
                             ExceptionState& exception_state) {
     return ToInt8(isolate, value, kNormalConversion, exception_state);
   }
-
-  static int8_t ArgumentValue(v8::Isolate* isolate,
-                              int argument_index,
-                              v8::Local<v8::Value> value,
-                              ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -85,13 +71,6 @@
                              ExceptionState& exception_state) {
     return ToUInt8(isolate, value, kNormalConversion, exception_state);
   }
-
-  static uint8_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -102,13 +81,6 @@
                              ExceptionState& exception_state) {
     return ToInt16(isolate, value, kNormalConversion, exception_state);
   }
-
-  static int16_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -119,13 +91,6 @@
                               ExceptionState& exception_state) {
     return ToUInt16(isolate, value, kNormalConversion, exception_state);
   }
-
-  static uint16_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -136,13 +101,6 @@
                              ExceptionState& exception_state) {
     return ToInt32(isolate, value, kNormalConversion, exception_state);
   }
-
-  static int32_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -153,13 +111,6 @@
                               ExceptionState& exception_state) {
     return ToUInt32(isolate, value, kNormalConversion, exception_state);
   }
-
-  static uint32_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -170,13 +121,6 @@
                              ExceptionState& exception_state) {
     return ToInt64(isolate, value, kNormalConversion, exception_state);
   }
-
-  static int64_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -187,13 +131,6 @@
                               ExceptionState& exception_state) {
     return ToUInt64(isolate, value, kNormalConversion, exception_state);
   }
-
-  static uint64_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // [Clamp] Integers
@@ -205,13 +142,6 @@
                             ExceptionState& exception_state) {
     return ToInt8(isolate, value, kClamp, exception_state);
   }
-
-  static int8_t ArgumentValue(v8::Isolate* isolate,
-                              int argument_index,
-                              v8::Local<v8::Value> value,
-                              ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -222,13 +152,6 @@
                              ExceptionState& exception_state) {
     return ToUInt8(isolate, value, kClamp, exception_state);
   }
-
-  static uint8_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -239,13 +162,6 @@
                              ExceptionState& exception_state) {
     return ToInt16(isolate, value, kClamp, exception_state);
   }
-
-  static int16_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -256,13 +172,6 @@
                               ExceptionState& exception_state) {
     return ToUInt16(isolate, value, kClamp, exception_state);
   }
-
-  static uint16_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -273,13 +182,6 @@
                              ExceptionState& exception_state) {
     return ToInt32(isolate, value, kClamp, exception_state);
   }
-
-  static int32_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -290,13 +192,6 @@
                               ExceptionState& exception_state) {
     return ToUInt32(isolate, value, kClamp, exception_state);
   }
-
-  static uint32_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -307,13 +202,6 @@
                              ExceptionState& exception_state) {
     return ToInt64(isolate, value, kClamp, exception_state);
   }
-
-  static int64_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -324,13 +212,6 @@
                               ExceptionState& exception_state) {
     return ToUInt64(isolate, value, kClamp, exception_state);
   }
-
-  static uint64_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // [EnforceRange] Integers
@@ -342,13 +223,6 @@
                             ExceptionState& exception_state) {
     return ToInt8(isolate, value, kEnforceRange, exception_state);
   }
-
-  static int8_t ArgumentValue(v8::Isolate* isolate,
-                              int argument_index,
-                              v8::Local<v8::Value> value,
-                              ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -359,13 +233,6 @@
                              ExceptionState& exception_state) {
     return ToUInt8(isolate, value, kEnforceRange, exception_state);
   }
-
-  static uint8_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -376,13 +243,6 @@
                              ExceptionState& exception_state) {
     return ToInt16(isolate, value, kEnforceRange, exception_state);
   }
-
-  static int16_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -393,13 +253,6 @@
                               ExceptionState& exception_state) {
     return ToUInt16(isolate, value, kEnforceRange, exception_state);
   }
-
-  static uint16_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -410,13 +263,6 @@
                              ExceptionState& exception_state) {
     return ToInt32(isolate, value, kEnforceRange, exception_state);
   }
-
-  static int32_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -427,13 +273,6 @@
                               ExceptionState& exception_state) {
     return ToUInt32(isolate, value, kEnforceRange, exception_state);
   }
-
-  static uint32_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -444,13 +283,6 @@
                              ExceptionState& exception_state) {
     return ToInt64(isolate, value, kEnforceRange, exception_state);
   }
-
-  static int64_t ArgumentValue(v8::Isolate* isolate,
-                               int argument_index,
-                               v8::Local<v8::Value> value,
-                               ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -461,13 +293,6 @@
                               ExceptionState& exception_state) {
     return ToUInt64(isolate, value, kEnforceRange, exception_state);
   }
-
-  static uint64_t ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // Strings
@@ -618,14 +443,6 @@
     return bindings::NativeValueTraitsStringAdapter(v8_string);
   }
 
-  static bindings::NativeValueTraitsStringAdapter ArgumentValue(
-      v8::Isolate* isolate,
-      int argument_index,
-      v8::Local<v8::Value> value,
-      ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
-
   static bindings::NativeValueTraitsStringAdapter NullValue() {
     return bindings::NativeValueTraitsStringAdapter();
   }
@@ -664,14 +481,6 @@
     return bindings::NativeValueTraitsStringAdapter(v8_string);
   }
 
-  static bindings::NativeValueTraitsStringAdapter ArgumentValue(
-      v8::Isolate* isolate,
-      int argument_index,
-      v8::Local<v8::Value> value,
-      ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
-
   static bindings::NativeValueTraitsStringAdapter NullValue() {
     return bindings::NativeValueTraitsStringAdapter();
   }
@@ -692,13 +501,6 @@
     return ReplaceUnmatchedSurrogates(string);
   }
 
-  static String ArgumentValue(v8::Isolate* isolate,
-                              int argument_index,
-                              v8::Local<v8::Value> value,
-                              ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
-
   static String NullValue() { return String(); }
 };
 
@@ -711,13 +513,6 @@
                             ExceptionState& exception_state) {
     return ToRestrictedDouble(isolate, value, exception_state);
   }
-
-  static double ArgumentValue(v8::Isolate* isolate,
-                              int argument_index,
-                              v8::Local<v8::Value> value,
-                              ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -728,13 +523,6 @@
                             ExceptionState& exception_state) {
     return ToDouble(isolate, value, exception_state);
   }
-
-  static double ArgumentValue(v8::Isolate* isolate,
-                              int argument_index,
-                              v8::Local<v8::Value> value,
-                              ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -745,13 +533,6 @@
                            ExceptionState& exception_state) {
     return ToRestrictedFloat(isolate, value, exception_state);
   }
-
-  static float ArgumentValue(v8::Isolate* isolate,
-                             int argument_index,
-                             v8::Local<v8::Value> value,
-                             ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 template <>
@@ -762,13 +543,6 @@
                            ExceptionState& exception_state) {
     return ToFloat(isolate, value, exception_state);
   }
-
-  static float ArgumentValue(v8::Isolate* isolate,
-                             int argument_index,
-                             v8::Local<v8::Value> value,
-                             ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // Buffer source types
@@ -802,12 +576,8 @@
   static ScriptPromise NativeValue(v8::Isolate* isolate,
                                    v8::Local<v8::Value> value,
                                    ExceptionState& exception_state) {
-    return NativeValue(isolate, value);
-  }
-
-  static ScriptPromise NativeValue(v8::Isolate* isolate,
-                                   v8::Local<v8::Value> value) {
-    return ScriptPromise::Cast(ScriptState::Current(isolate), value);
+    return ScriptPromise::Cast(ScriptState::From(isolate->GetCurrentContext()),
+                               value);
   }
 };
 
@@ -886,13 +656,6 @@
     return result;
   }
 
-  static ImplType ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
-
  private:
   // Fast case: we're interating over an Array that adheres to
   // %ArrayIteratorPrototype%'s protocol.
@@ -1080,13 +843,6 @@
     // "5. Return result."
     return result;
   }
-
-  static ImplType ArgumentValue(v8::Isolate* isolate,
-                                int argument_index,
-                                v8::Local<v8::Value> value,
-                                ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // Callback functions
@@ -1107,13 +863,6 @@
         << "is not yet implemented.";
     return nullptr;
   }
-
-  static T* ArgumentValue(v8::Isolate* isolate,
-                          int argument_index,
-                          v8::Local<v8::Value> value,
-                          ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // Dictionary
@@ -1128,13 +877,6 @@
                         ExceptionState& exception_state) {
     return T::Create(isolate, value, exception_state);
   }
-
-  static T* ArgumentValue(v8::Isolate* isolate,
-                          int argument_index,
-                          v8::Local<v8::Value> value,
-                          ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // Interface
@@ -1178,14 +920,6 @@
     return NativeValueTraits<InnerType>::NativeValue(isolate, v8_value,
                                                      exception_state);
   }
-
-  static typename IDLNullable<InnerType>::ResultType ArgumentValue(
-      v8::Isolate* isolate,
-      int argument_index,
-      v8::Local<v8::Value> value,
-      ExceptionState& exception_state) {
-    return NativeValue(isolate, value, exception_state);
-  }
 };
 
 // EventHandler
diff --git a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
index c1ce714..c3a8c9d05 100644
--- a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
+++ b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
@@ -62,6 +62,7 @@
     'V0',
     'V8',
     'v8',
+    'XR',
 ]
 
 _SPECIAL_TOKENS_WITH_NUMBERS = [token for token in SPECIAL_TOKENS if re.search(r'[0-9]', token)]
diff --git a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py
index 85ba650b..e8379b0 100644
--- a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py
+++ b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py
@@ -117,6 +117,8 @@
 
         self.assertEqual(tokenize_name('FileURLs'), ['File', 'URLs'])
 
+        self.assertEqual(tokenize_name('XRDOMOverlay'), ['XR', 'DOM', 'Overlay'])
+
     def test_ignoring_characters(self):
         self.assertEqual(tokenize_name('Animation.idl'), ['Animation', 'idl'])
         self.assertEqual(tokenize_name('-webkit-appearance'), ['webkit', 'appearance'])
diff --git a/third_party/blink/renderer/controller/BUILD.gn b/third_party/blink/renderer/controller/BUILD.gn
index afb2259..d63d26a 100644
--- a/third_party/blink/renderer/controller/BUILD.gn
+++ b/third_party/blink/renderer/controller/BUILD.gn
@@ -84,15 +84,11 @@
   visibility = []  # Allow re-assignment of list.
   visibility = [ "*" ]
   testonly = true
-  deps = [
-    ":blink_unittests",
-  ]
+  deps = [ ":blink_unittests" ]
 }
 
 test("blink_unittests") {
-  deps = [
-    ":blink_unittests_sources",
-  ]
+  deps = [ ":blink_unittests_sources" ]
 
   data_deps = [
     ":blink_unittests_data",
@@ -114,9 +110,7 @@
 }
 
 test("blink_perf_tests") {
-  deps = [
-    ":blink_perf_tests_sources",
-  ]
+  deps = [ ":blink_perf_tests_sources" ]
 }
 
 jumbo_source_set("blink_perf_tests_sources") {
@@ -124,9 +118,7 @@
   visibility = [ "*" ]
   testonly = true
 
-  sources = [
-    "tests/run_all_tests.cc",
-  ]
+  sources = [ "tests/run_all_tests.cc" ]
 
   deps = [
     ":controller",
@@ -147,9 +139,7 @@
   visibility = [ "*" ]
   testonly = true
 
-  sources = [
-    "tests/run_all_tests.cc",
-  ]
+  sources = [ "tests/run_all_tests.cc" ]
   sources += bindings_unittest_files
   if (is_android) {
     sources += [
diff --git a/third_party/blink/renderer/core/dom/processing_instruction.cc b/third_party/blink/renderer/core/dom/processing_instruction.cc
index 1fab73ee..9306280 100644
--- a/third_party/blink/renderer/core/dom/processing_instruction.cc
+++ b/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -198,7 +198,7 @@
   if (is_xsl_) {
     sheet_ = MakeGarbageCollected<XSLStyleSheet>(
         this, resource->Url(), resource->GetResponse().ResponseUrl(), false);
-    ToXSLStyleSheet(sheet_.Get())
+    To<XSLStyleSheet>(sheet_.Get())
         ->ParseString(ToXSLStyleSheetResource(resource)->Sheet());
   } else {
     DCHECK(is_css_);
@@ -233,7 +233,7 @@
   if (is_css_)
     To<CSSStyleSheet>(sheet_.Get())->Contents()->CheckLoaded();
   else if (is_xsl_)
-    ToXSLStyleSheet(sheet_.Get())->CheckLoaded();
+    To<XSLStyleSheet>(sheet_.Get())->CheckLoaded();
 }
 
 Node::InsertionNotificationRequest ProcessingInstruction::InsertedInto(
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
index 45c81c83..afa7e435 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -379,8 +379,9 @@
     Thread::Current()->RemoveTaskObserver(this);
 }
 
-void WebDevToolsAgentImpl::InspectElement(const WebPoint& point_in_local_root) {
-  WebFloatRect rect(point_in_local_root.x, point_in_local_root.y, 0, 0);
+void WebDevToolsAgentImpl::InspectElement(
+    const gfx::Point& point_in_local_root) {
+  WebFloatRect rect(point_in_local_root.x(), point_in_local_root.y(), 0, 0);
   web_local_frame_impl_->FrameWidgetImpl()->Client()->ConvertWindowToViewport(
       &rect);
   WebPoint point(rect.x, rect.y);
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
index 864aef64..ee5a028a 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
@@ -97,7 +97,7 @@
   // DevToolsAgent::Client implementation.
   void AttachSession(DevToolsSession*, bool restore) override;
   void DetachSession(DevToolsSession*) override;
-  void InspectElement(const WebPoint& point_in_local_root) override;
+  void InspectElement(const gfx::Point& point_in_local_root) override;
   void DebuggerTaskStarted() override;
   void DebuggerTaskFinished() override;
 
diff --git a/third_party/blink/renderer/core/exported/web_frame.cc b/third_party/blink/renderer/core/exported/web_frame.cc
index 6e095c46..e74bb9e6 100644
--- a/third_party/blink/renderer/core/exported/web_frame.cc
+++ b/third_party/blink/renderer/core/exported/web_frame.cc
@@ -128,7 +128,7 @@
                            ToTraceValue(&local_frame));
     }
   } else {
-    ToWebRemoteFrameImpl(frame)->InitializeCoreFrame(
+    To<WebRemoteFrameImpl>(frame)->InitializeCoreFrame(
         *page, owner, name, &old_frame->window_agent_factory());
   }
 
@@ -341,7 +341,7 @@
   if (auto* web_local_frame = DynamicTo<WebLocalFrameImpl>(frame))
     visitor->Trace(web_local_frame);
   else
-    visitor->Trace(ToWebRemoteFrameImpl(frame));
+    visitor->Trace(To<WebRemoteFrameImpl>(frame));
 }
 
 void WebFrame::TraceFrames(Visitor* visitor, WebFrame* frame) {
@@ -373,7 +373,7 @@
   if (auto* web_local_frame = DynamicTo<WebLocalFrameImpl>(&frame))
     return web_local_frame->GetFrame();
   if (frame.IsWebRemoteFrame())
-    return ToWebRemoteFrameImpl(frame).GetFrame();
+    return To<WebRemoteFrameImpl>(frame).GetFrame();
   NOTREACHED();
   return nullptr;
 }
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 00910e1b..b8df6b9 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -8421,19 +8421,21 @@
       web_widget_client.layer_tree_host();
 
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
-
   Document* document = frame->GetDocument();
-  EXPECT_FALSE(document->IsImmersiveArOverlay());
-  document->SetIsImmersiveArOverlay(true);
-  EXPECT_TRUE(document->IsImmersiveArOverlay());
 
   Element* overlay = document->getElementById("overlay");
   EXPECT_FALSE(Fullscreen::IsFullscreenElement(*overlay));
   EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
 
-  // Fullscreen should work without separate user activation while in ArOverlay
-  // mode.
+  // It's not legal to switch the fullscreen element while in immersive-ar mode,
+  // so set the fullscreen element first before activating that. This requires
+  // user activation.
+  LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*overlay);
+  EXPECT_FALSE(document->IsImmersiveArOverlay());
+  document->SetIsImmersiveArOverlay(true);
+  EXPECT_TRUE(document->IsImmersiveArOverlay());
+
   web_view_impl->MainFrameWidget()->DidEnterFullscreen();
   UpdateAllLifecyclePhases(web_view_impl);
   EXPECT_TRUE(Fullscreen::IsFullscreenElement(*overlay));
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
index fdefaeb7..5acc4339 100644
--- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -364,7 +364,7 @@
 void WebRemoteFrameImpl::TransferUserActivationFrom(
     blink::WebRemoteFrame* source_frame) {
   GetFrame()->TransferUserActivationFrom(
-      ToWebRemoteFrameImpl(source_frame)->GetFrame());
+      To<WebRemoteFrameImpl>(source_frame)->GetFrame());
 }
 
 void WebRemoteFrameImpl::ScrollRectToVisible(
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
index 113ffb77..a922c86 100644
--- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
+++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/frame/remote_frame.h"
 #include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace cc {
 class Layer;
@@ -142,11 +143,12 @@
   SelfKeepAlive<WebRemoteFrameImpl> self_keep_alive_;
 };
 
-DEFINE_TYPE_CASTS(WebRemoteFrameImpl,
-                  WebFrame,
-                  frame,
-                  frame->IsWebRemoteFrame(),
-                  frame.IsWebRemoteFrame());
+template <>
+struct DowncastTraits<WebRemoteFrameImpl> {
+  static bool AllowFrom(const WebFrame& frame) {
+    return frame.IsWebRemoteFrame();
+  }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 9d0ac92..34ff617 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -2305,7 +2305,7 @@
                                            WebLocalFrame* to) {
   // TODO(alexmos): Pass in proper with sourceCapabilities.
   GetPage()->GetFocusController().AdvanceFocusAcrossFrames(
-      type, ToWebRemoteFrameImpl(from)->GetFrame(),
+      type, To<WebRemoteFrameImpl>(from)->GetFrame(),
       To<WebLocalFrameImpl>(to)->GetFrame());
 }
 
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 5460b3ae..a18cb9052 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -4396,8 +4396,8 @@
     font_size_ = unhandled_tap_info->font_size_in_pixels;
   }
   bool WasUnhandledTap() const { return was_unhandled_tap_; }
-  int GetTappedXPos() const { return tapped_position_.X(); }
-  int GetTappedYPos() const { return tapped_position_.Y(); }
+  int GetTappedXPos() const { return tapped_position_.x(); }
+  int GetTappedYPos() const { return tapped_position_.y(); }
   int GetFontSize() const { return font_size_; }
   int GetElementTextRunLength() const { return element_text_run_length_; }
   void Reset() {
@@ -4410,7 +4410,7 @@
 
  private:
   bool was_unhandled_tap_ = false;
-  IntPoint tapped_position_;
+  gfx::Point tapped_position_;
   int element_text_run_length_ = 0;
   int font_size_ = 0;
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index b3ed9c0..f4d7c97 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -304,7 +304,7 @@
     TestWebRemoteFrameClient* client) {
   std::unique_ptr<TestWebRemoteFrameClient> owned_client;
   client = CreateDefaultClientIfNeeded(client, owned_client);
-  auto* frame = ToWebRemoteFrameImpl(parent.CreateRemoteChild(
+  auto* frame = To<WebRemoteFrameImpl>(parent.CreateRemoteChild(
       WebTreeScopeType::kDocument, name, FramePolicy(),
       FrameOwnerElementType::kIframe, client,
       InterfaceRegistry::GetEmptyInterfaceRegistry(),
@@ -463,7 +463,7 @@
 }
 
 WebRemoteFrameImpl* WebViewHelper::RemoteMainFrame() const {
-  return ToWebRemoteFrameImpl(web_view_->MainFrame());
+  return To<WebRemoteFrameImpl>(web_view_->MainFrame());
 }
 
 void WebViewHelper::Resize(WebSize size) {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 6e3cecb..a9588c9 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1917,12 +1917,12 @@
   base::UnguessableToken portal_token;
   std::tie(portal_frame, portal_token) = client_->CreatePortal(
       portal_receiver.PassHandle(), portal_client.PassHandle(), portal);
-  return {ToWebRemoteFrameImpl(portal_frame)->GetFrame(), portal_token};
+  return {To<WebRemoteFrameImpl>(portal_frame)->GetFrame(), portal_token};
 }
 
 RemoteFrame* WebLocalFrameImpl::AdoptPortal(HTMLPortalElement* portal) {
-  WebRemoteFrameImpl* portal_frame =
-      ToWebRemoteFrameImpl(client_->AdoptPortal(portal->GetToken(), portal));
+  auto* portal_frame =
+      To<WebRemoteFrameImpl>(client_->AdoptPortal(portal->GetToken(), portal));
   return portal_frame->GetFrame();
 }
 
diff --git a/third_party/blink/renderer/core/html/html_collection.cc b/third_party/blink/renderer/core/html/html_collection.cc
index 750ee45c..f2645f8 100644
--- a/third_party/blink/renderer/core/html/html_collection.cc
+++ b/third_party/blink/renderer/core/html/html_collection.cc
@@ -285,7 +285,7 @@
     case kTagCollectionNSType:
       return To<TagCollectionNS>(*this).ElementMatches(element);
     case kWindowNamedItems:
-      return ToWindowNameCollection(*this).ElementMatches(element);
+      return To<WindowNameCollection>(*this).ElementMatches(element);
     case kDocumentAllNamedItems:
       return ToDocumentAllNameCollection(*this).ElementMatches(element);
     default:
diff --git a/third_party/blink/renderer/core/html/window_name_collection.h b/third_party/blink/renderer/core/html/window_name_collection.h
index 36139c9..5b5ee581 100644
--- a/third_party/blink/renderer/core/html/window_name_collection.h
+++ b/third_party/blink/renderer/core/html/window_name_collection.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_WINDOW_NAME_COLLECTION_H_
 
 #include "third_party/blink/renderer/core/html/html_name_collection.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
 
@@ -19,11 +20,12 @@
   bool ElementMatches(const Element&) const;
 };
 
-DEFINE_TYPE_CASTS(WindowNameCollection,
-                  LiveNodeListBase,
-                  collection,
-                  collection->GetType() == kWindowNamedItems,
-                  collection.GetType() == kWindowNamedItems);
+template <>
+struct DowncastTraits<WindowNameCollection> {
+  static bool AllowFrom(const LiveNodeListBase& collection) {
+    return collection.GetType() == kWindowNamedItems;
+  }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc
index ac1fdd67..e72cc69 100644
--- a/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -486,10 +486,8 @@
     // e.g. style->GetFontWeight() to return bold.  Need italic, color, etc.
 
     // Notify the Browser.
-    WebPoint point(tapped_position_in_viewport.X(),
-                   tapped_position_in_viewport.Y());
-    auto tapped_info =
-        mojom::blink::UnhandledTapInfo::New(point, font_size, text_run_length);
+    auto tapped_info = mojom::blink::UnhandledTapInfo::New(
+        tapped_position_in_viewport, font_size, text_run_length);
     provider->ShowUnhandledTapUIIfNeeded(std::move(tapped_info));
   }
 #endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.cc b/third_party/blink/renderer/core/inspector/devtools_agent.cc
index 99f3b27..baac8ec 100644
--- a/third_party/blink/renderer/core/inspector/devtools_agent.cc
+++ b/third_party/blink/renderer/core/inspector/devtools_agent.cc
@@ -116,7 +116,7 @@
   client_->DebuggerTaskFinished();
 }
 
-void DevToolsAgent::InspectElement(const WebPoint& point) {
+void DevToolsAgent::InspectElement(const gfx::Point& point) {
   client_->InspectElement(point);
 }
 
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.h b/third_party/blink/renderer/core/inspector/devtools_agent.h
index 78c07bc..92b7126c 100644
--- a/third_party/blink/renderer/core/inspector/devtools_agent.h
+++ b/third_party/blink/renderer/core/inspector/devtools_agent.h
@@ -37,7 +37,7 @@
     virtual ~Client() {}
     virtual void AttachSession(DevToolsSession*, bool restore) = 0;
     virtual void DetachSession(DevToolsSession*) = 0;
-    virtual void InspectElement(const WebPoint&) = 0;
+    virtual void InspectElement(const gfx::Point&) = 0;
     virtual void DebuggerTaskStarted() = 0;
     virtual void DebuggerTaskFinished() = 0;
   };
@@ -79,7 +79,7 @@
       mojo::PendingReceiver<mojom::blink::DevToolsSession> io_session,
       mojom::blink::DevToolsSessionStatePtr reattach_session_state,
       bool client_expects_binary_responses) override;
-  void InspectElement(const WebPoint& point) override;
+  void InspectElement(const gfx::Point& point) override;
   void ReportChildWorkers(bool report,
                           bool wait_for_debugger,
                           base::OnceClosure callback) override;
diff --git a/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc b/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
index b1c87944..e5baa33 100644
--- a/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
+++ b/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
@@ -122,7 +122,7 @@
     thread_->GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this);
 }
 
-void WorkerInspectorController::InspectElement(const WebPoint&) {
+void WorkerInspectorController::InspectElement(const gfx::Point&) {
   NOTREACHED();
 }
 
diff --git a/third_party/blink/renderer/core/inspector/worker_inspector_controller.h b/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
index 75203c5..7e6c9ef 100644
--- a/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
+++ b/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
@@ -92,7 +92,7 @@
   // DevToolsAgent::Client implementation.
   void AttachSession(DevToolsSession*, bool restore) override;
   void DetachSession(DevToolsSession*) override;
-  void InspectElement(const WebPoint&) override;
+  void InspectElement(const gfx::Point&) override;
   void DebuggerTaskStarted() override;
   void DebuggerTaskFinished() override;
 
diff --git a/third_party/blink/renderer/core/loader/BUILD.gn b/third_party/blink/renderer/core/loader/BUILD.gn
index 0b517e74..105ad696 100644
--- a/third_party/blink/renderer/core/loader/BUILD.gn
+++ b/third_party/blink/renderer/core/loader/BUILD.gn
@@ -158,7 +158,5 @@
     "worker_resource_timing_notifier_impl.h",
   ]
 
-  public_deps = [
-    "//third_party/blink/renderer/platform",
-  ]
+  public_deps = [ "//third_party/blink/renderer/platform" ]
 }
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index ac1213a..71f5e57 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -391,7 +391,7 @@
 static void RestoreSVGImageAnimations() {
   for (const Page* page : AllPages()) {
     if (auto* svg_image_chrome_client =
-            ToSVGImageChromeClientOrNull(page->GetChromeClient()))
+            DynamicTo<SVGImageChromeClient>(page->GetChromeClient()))
       svg_image_chrome_client->RestoreAnimationIfNeeded();
   }
 }
diff --git a/third_party/blink/renderer/core/probe/BUILD.gn b/third_party/blink/renderer/core/probe/BUILD.gn
index 93ef592..6e85e2b 100644
--- a/third_party/blink/renderer/core/probe/BUILD.gn
+++ b/third_party/blink/renderer/core/probe/BUILD.gn
@@ -31,9 +31,7 @@
 }
 
 source_set("generated") {
-  deps = [
-    ":instrumentation_probes",
-  ]
+  deps = [ ":instrumentation_probes" ]
 }
 
 # Compiles the sources generated above.
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
index 6460951..69506e8 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
 
@@ -76,11 +77,12 @@
   FRIEND_TEST_ALL_PREFIXES(SVGImageSimTest, PageVisibilityHiddenToVisible);
 };
 
-DEFINE_TYPE_CASTS(SVGImageChromeClient,
-                  ChromeClient,
-                  client,
-                  client->IsSVGImageChromeClient(),
-                  client.IsSVGImageChromeClient());
+template <>
+struct DowncastTraits<SVGImageChromeClient> {
+  static bool AllowFrom(const ChromeClient& client) {
+    return client.IsSVGImageChromeClient();
+  }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/xml/document_xslt.cc b/third_party/blink/renderer/core/xml/document_xslt.cc
index 80f672af..71ec3bb5 100644
--- a/third_party/blink/renderer/core/xml/document_xslt.cc
+++ b/third_party/blink/renderer/core/xml/document_xslt.cc
@@ -75,7 +75,7 @@
   DCHECK(!pi->IsLoading());
   UseCounter::Count(document, WebFeature::kXSLProcessingInstruction);
   XSLTProcessor* processor = XSLTProcessor::Create(document);
-  processor->SetXSLStyleSheet(ToXSLStyleSheet(pi->sheet()));
+  processor->SetXSLStyleSheet(To<XSLStyleSheet>(pi->sheet()));
   String result_mime_type;
   String new_source;
   String result_encoding;
diff --git a/third_party/blink/renderer/core/xml/xsl_style_sheet.h b/third_party/blink/renderer/core/xml/xsl_style_sheet.h
index 5b709cd..22fb4f3 100644
--- a/third_party/blink/renderer/core/xml/xsl_style_sheet.h
+++ b/third_party/blink/renderer/core/xml/xsl_style_sheet.h
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/css/style_sheet.h"
 #include "third_party/blink/renderer/core/dom/processing_instruction.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
 
@@ -105,11 +106,12 @@
   Member<Document> owner_document_;
 };
 
-DEFINE_TYPE_CASTS(XSLStyleSheet,
-                  StyleSheet,
-                  sheet,
-                  !sheet->IsCSSStyleSheet(),
-                  !sheet.IsCSSStyleSheet());
+template <>
+struct DowncastTraits<XSLStyleSheet> {
+  static bool AllowFrom(const StyleSheet& sheet) {
+    return !sheet.IsCSSStyleSheet();
+  }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 800cbb1..94cb7b1 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -208,6 +208,8 @@
     "peerconnection/testing/internals_rtc_certificate.h",
     "peerconnection/testing/internals_rtc_peer_connection.cc",
     "peerconnection/testing/internals_rtc_peer_connection.h",
+    "permissions/testing/internals_permission.cc",
+    "permissions/testing/internals_permission.h",
     "service_worker/testing/internals_service_worker.cc",
     "service_worker/testing/internals_service_worker.h",
     "speech/testing/internals_speech_synthesis.cc",
diff --git a/third_party/blink/renderer/modules/bluetooth/BUILD.gn b/third_party/blink/renderer/modules/bluetooth/BUILD.gn
index eb3b1c8..23ac86b9 100644
--- a/third_party/blink/renderer/modules/bluetooth/BUILD.gn
+++ b/third_party/blink/renderer/modules/bluetooth/BUILD.gn
@@ -40,7 +40,5 @@
     "navigator_bluetooth.h",
   ]
 
-  deps = [
-    "//device/bluetooth/public/mojom:mojom_blink",
-  ]
+  deps = [ "//device/bluetooth/public/mojom:mojom_blink" ]
 }
diff --git a/third_party/blink/renderer/modules/launch/BUILD.gn b/third_party/blink/renderer/modules/launch/BUILD.gn
index 86215df8..c156969 100644
--- a/third_party/blink/renderer/modules/launch/BUILD.gn
+++ b/third_party/blink/renderer/modules/launch/BUILD.gn
@@ -16,7 +16,5 @@
     "web_launch_service_impl.h",
   ]
 
-  deps = [
-    "//third_party/blink/renderer/modules/filesystem",
-  ]
+  deps = [ "//third_party/blink/renderer/modules/filesystem" ]
 }
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index da826ed..97ea453c 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -513,6 +513,7 @@
           "xr/xr_anchor.idl",
           "xr/xr_anchor_set.idl",
           "xr/xr_bounded_reference_space.idl",
+          "xr/xr_dom_overlay_state.idl",
           "xr/xr_frame.idl",
           "xr/xr_hit_result.idl",
           "xr/xr_input_source.idl",
@@ -892,6 +893,7 @@
           "webusb/usb_control_transfer_parameters.idl",
           "webusb/usb_device_filter.idl",
           "webusb/usb_device_request_options.idl",
+          "xr/xr_dom_overlay_init.idl",
           "xr/xr_hit_test_options_init.idl",
           "xr/xr_input_source_event_init.idl",
           "xr/xr_input_sources_change_event_init.idl",
@@ -1067,6 +1069,7 @@
                     "netinfo/testing/internals_net_info.idl",
                     "peerconnection/testing/internals_rtc_certificate.idl",
                     "peerconnection/testing/internals_rtc_peer_connection.idl",
+                    "permissions/testing/internals_permission.idl",
                     "service_worker/testing/internals_service_worker.idl",
                     "speech/testing/internals_speech_synthesis.idl",
                     "vibration/testing/internals_vibration.idl",
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h
index b0b9c97..82abb43 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h
@@ -21,7 +21,7 @@
       quic::QuicCryptoClientConfig* crypto_config,
       quic::QuicCryptoClientStream::ProofHandler* proof_handler) = 0;
 
-  virtual std::unique_ptr<quic::QuicCryptoServerStream>
+  virtual std::unique_ptr<quic::QuicCryptoServerStreamBase>
   CreateServerCryptoStream(
       const quic::QuicCryptoServerConfig* crypto_config,
       quic::QuicCompressedCertsCache* compressed_certs_cache,
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc
index 35bd6c1..41d68a6 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc
@@ -24,14 +24,14 @@
       proof_handler);
 }
 
-std::unique_ptr<quic::QuicCryptoServerStream>
+std::unique_ptr<quic::QuicCryptoServerStreamBase>
 P2PQuicCryptoStreamFactoryImpl::CreateServerCryptoStream(
     const quic::QuicCryptoServerConfig* crypto_config,
     quic::QuicCompressedCertsCache* compressed_certs_cache,
     quic::QuicSession* session,
     quic::QuicCryptoServerStream::Helper* helper) {
-  return std::make_unique<quic::QuicCryptoServerStream>(
-      crypto_config, compressed_certs_cache, session, helper);
+  return quic::CreateCryptoServerStream(crypto_config, compressed_certs_cache,
+                                        session, helper);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h
index e4ee2aa..ebc6582 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h
@@ -24,7 +24,7 @@
       quic::QuicCryptoClientConfig* crypto_config,
       quic::QuicCryptoClientStream::ProofHandler* proof_handler) override;
 
-  std::unique_ptr<quic::QuicCryptoServerStream> CreateServerCryptoStream(
+  std::unique_ptr<quic::QuicCryptoServerStreamBase> CreateServerCryptoStream(
       const quic::QuicCryptoServerConfig* crypto_config,
       quic::QuicCompressedCertsCache* compressed_certs_cache,
       quic::QuicSession* session,
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
index d4b3300..9016fb6 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
@@ -219,10 +219,8 @@
   // TODO(shampson): Consider setting larger initial flow control window sizes
   // so that the default limit doesn't cause initial undersending.
   quic::QuicConfig quic_config;
-  quic_config.SetMaxIncomingBidirectionalStreamsToSend(
-      kMaxIncomingDynamicStreams);
-  quic_config.SetMaxIncomingUnidirectionalStreamsToSend(
-      kMaxIncomingDynamicStreams);
+  quic_config.SetMaxBidirectionalStreamsToSend(kMaxIncomingDynamicStreams);
+  quic_config.SetMaxUnidirectionalStreamsToSend(kMaxIncomingDynamicStreams);
   // The handshake network timeouts are configured to large values to prevent
   // the QUIC connection from being closed on a slow connection. This can occur
   // if signaling is slow and one side begins the handshake early.
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
index 51159a3..b422fb5b 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
@@ -470,9 +470,9 @@
         quic::QuicTime::Delta::FromSeconds(2 * quic::kMaximumIdleTimeoutSecs),
         quic::QuicTime::Delta::FromSeconds(quic::kMaximumIdleTimeoutSecs));
     config.SetBytesForConnectionIdToSend(quic::PACKET_8BYTE_CONNECTION_ID);
-    config.SetMaxIncomingBidirectionalStreamsToSend(
+    config.SetMaxBidirectionalStreamsToSend(
         quic::kDefaultMaxStreamsPerConnection / 2);
-    config.SetMaxIncomingUnidirectionalStreamsToSend(
+    config.SetMaxUnidirectionalStreamsToSend(
         quic::kDefaultMaxStreamsPerConnection / 2);
     quic::CryptoHandshakeMessage message;
     config.ToHandshakeMessage(&message,
@@ -524,13 +524,13 @@
   }
 
   // Creates a real quic::QuiCryptoServerStream.
-  std::unique_ptr<quic::QuicCryptoServerStream> CreateServerCryptoStream(
+  std::unique_ptr<quic::QuicCryptoServerStreamBase> CreateServerCryptoStream(
       const quic::QuicCryptoServerConfig* crypto_config,
       quic::QuicCompressedCertsCache* compressed_certs_cache,
       quic::QuicSession* session,
       quic::QuicCryptoServerStream::Helper* helper) override {
-    return std::make_unique<quic::QuicCryptoServerStream>(
-        crypto_config, compressed_certs_cache, session, helper);
+    return quic::CreateCryptoServerStream(crypto_config, compressed_certs_cache,
+                                          session, helper);
   }
 };
 
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
index f8e6f7a..adb3ab87 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
@@ -41,13 +41,6 @@
  public:
   static PeerConnectionTracker* GetInstance();
 
-  // TODO(crbug.com/787254): Make these ctors private, and accessible to
-  // tests only.
-  explicit PeerConnectionTracker(
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
-  PeerConnectionTracker(
-      mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost> host,
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
   ~PeerConnectionTracker() override;
 
   enum Source { SOURCE_LOCAL, SOURCE_REMOTE };
@@ -225,8 +218,19 @@
                                      const WTF::Vector<uint8_t>& output);
 
  private:
+  // For tests.
+  friend class PeerConnectionTrackerTest;
+  friend class MockPeerConnectionTracker;
+
+  FRIEND_TEST_ALL_PREFIXES(PeerConnectionTrackerTest, CreatingObject);
   FRIEND_TEST_ALL_PREFIXES(PeerConnectionTrackerTest, OnSuspend);
 
+  explicit PeerConnectionTracker(
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
+  PeerConnectionTracker(
+      mojo::Remote<mojom::blink::PeerConnectionTrackerHost> host,
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
+
   // Assign a local ID to a peer connection so that the browser process can
   // uniquely identify a peer connection in the renderer process.
   // The return value will always be positive.
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
index a1eeda3..9c714d3 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
@@ -131,6 +131,8 @@
   MockRTCPeerConnectionHandlerClient client_;
 };
 
+}  // namespace
+
 class PeerConnectionTrackerTest : public ::testing::Test {
  public:
   void CreateTrackerWithMocks() {
@@ -156,8 +158,6 @@
   std::unique_ptr<MockPeerConnectionHandler> mock_handler_;
 };
 
-}  // namespace
-
 TEST_F(PeerConnectionTrackerTest, CreatingObject) {
   PeerConnectionTracker tracker(
       blink::scheduler::GetSingleThreadTaskRunnerForTesting());
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
index 114ab47..3cf4be9 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -892,11 +892,9 @@
   // When an RTC event log is sent back from PeerConnection, it arrives here.
   void OnWebRtcEventLogWrite(const WTF::Vector<uint8_t>& output) override {
     if (!main_thread_->BelongsToCurrentThread()) {
-      // TODO(crbug.com/787254): Convert this call to PostCrossThreadTask,
-      // after crrev.com/c/1976250 lands.
-      main_thread_->PostTask(
-          FROM_HERE,
-          base::BindOnce(
+      PostCrossThreadTask(
+          *main_thread_.get(), FROM_HERE,
+          CrossThreadBindOnce(
               &RTCPeerConnectionHandler::Observer::OnWebRtcEventLogWrite,
               WrapCrossThreadPersistent(this), output));
     } else if (handler_) {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
index 9f1de7e..71767228 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
@@ -377,9 +377,7 @@
     "a=ssrc:4092260337 mslabel:46f8615e-7599-49f3-9a45-3cf0faf58614\r\n"
     "a=ssrc:4092260337 label:6b5f436e-f85d-40a1-83e4-acec63ca4b82\r\n";
 
-template <typename PlatformSupportType>
-class RTCPeerConnectionTestWithPlatformTestingPlatformType
-    : public testing::Test {
+class RTCPeerConnectionTest : public testing::Test {
  public:
   RTCPeerConnection* CreatePC(V8TestingScope& scope,
                               const String& sdpSemantics = String()) {
@@ -392,8 +390,7 @@
     config->setIceServers(ice_servers);
     RTCPeerConnection::SetRtcPeerConnectionHandlerFactoryForTesting(
         base::BindRepeating(
-            &RTCPeerConnectionTestWithPlatformTestingPlatformType::
-                CreateRTCPeerConnectionHandler,
+            &RTCPeerConnectionTest::CreateRTCPeerConnectionHandler,
             base::Unretained(this)));
     return RTCPeerConnection::Create(scope.GetExecutionContext(), config,
                                      Dictionary(), scope.GetExceptionState());
@@ -436,15 +433,9 @@
   }
 
  protected:
-  ScopedTestingPlatformSupport<PlatformSupportType> platform_;
+  ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
 };
 
-// TODO(crbug.com/787254): Consider removing or simplifying the inheritance
-// altogether.
-class RTCPeerConnectionTest
-    : public RTCPeerConnectionTestWithPlatformTestingPlatformType<
-          TestingPlatformSupport> {};
-
 TEST_F(RTCPeerConnectionTest, GetAudioTrack) {
   V8TestingScope scope;
   RTCPeerConnection* pc = CreatePC(scope);
@@ -761,11 +752,7 @@
 // completed. Without fakes we would have had to await promises and callbacks,
 // passing SDP returned by one operation to the next.
 //
-// TODO(crbug.com/787254): Consider removing or simplifying the inheritance
-// altogether.
-class RTCPeerConnectionCallSetupStateTest
-    : public RTCPeerConnectionTestWithPlatformTestingPlatformType<
-          TestingPlatformSupport> {
+class RTCPeerConnectionCallSetupStateTest : public RTCPeerConnectionTest {
  public:
   std::unique_ptr<RTCPeerConnectionHandlerPlatform>
   CreateRTCPeerConnectionHandler() override {
diff --git a/third_party/blink/renderer/modules/permissions/permission_utils.cc b/third_party/blink/renderer/modules/permissions/permission_utils.cc
index 6f3c445..5bc3d90 100644
--- a/third_party/blink/renderer/modules/permissions/permission_utils.cc
+++ b/third_party/blink/renderer/modules/permissions/permission_utils.cc
@@ -7,11 +7,20 @@
 #include <utility>
 
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_clipboard_permission_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_midi_permission_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_permission_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_push_permission_descriptor.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_permission_descriptor.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
 #include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -81,4 +90,130 @@
   return descriptor;
 }
 
+PermissionDescriptorPtr ParsePermissionDescriptor(
+    ScriptState* script_state,
+    const ScriptValue& raw_descriptor,
+    ExceptionState& exception_state) {
+  PermissionDescriptor* permission =
+      NativeValueTraits<PermissionDescriptor>::NativeValue(
+          script_state->GetIsolate(), raw_descriptor.V8Value(),
+          exception_state);
+
+  if (exception_state.HadException())
+    return nullptr;
+
+  const String& name = permission->name();
+  if (name == "geolocation")
+    return CreatePermissionDescriptor(PermissionName::GEOLOCATION);
+  if (name == "camera")
+    return CreatePermissionDescriptor(PermissionName::VIDEO_CAPTURE);
+  if (name == "microphone")
+    return CreatePermissionDescriptor(PermissionName::AUDIO_CAPTURE);
+  if (name == "notifications")
+    return CreatePermissionDescriptor(PermissionName::NOTIFICATIONS);
+  if (name == "persistent-storage")
+    return CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE);
+  if (name == "push") {
+    PushPermissionDescriptor* push_permission =
+        NativeValueTraits<PushPermissionDescriptor>::NativeValue(
+            script_state->GetIsolate(), raw_descriptor.V8Value(),
+            exception_state);
+    if (exception_state.HadException())
+      return nullptr;
+
+    // Only "userVisibleOnly" push is supported for now.
+    if (!push_permission->userVisibleOnly()) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kNotSupportedError,
+          "Push Permission without userVisibleOnly:true isn't supported yet.");
+      return nullptr;
+    }
+
+    return CreatePermissionDescriptor(PermissionName::NOTIFICATIONS);
+  }
+  if (name == "midi") {
+    MidiPermissionDescriptor* midi_permission =
+        NativeValueTraits<MidiPermissionDescriptor>::NativeValue(
+            script_state->GetIsolate(), raw_descriptor.V8Value(),
+            exception_state);
+    return CreateMidiPermissionDescriptor(midi_permission->sysex());
+  }
+  if (name == "background-sync")
+    return CreatePermissionDescriptor(PermissionName::BACKGROUND_SYNC);
+  if (name == "ambient-light-sensor" || name == "accelerometer" ||
+      name == "gyroscope" || name == "magnetometer") {
+    // ALS requires an extra flag.
+    if (name == "ambient-light-sensor") {
+      if (!RuntimeEnabledFeatures::SensorExtraClassesEnabled()) {
+        exception_state.ThrowTypeError(
+            "GenericSensorExtraClasses flag is not enabled.");
+        return nullptr;
+      }
+    }
+
+    return CreatePermissionDescriptor(PermissionName::SENSORS);
+  }
+  if (name == "accessibility-events") {
+    if (!RuntimeEnabledFeatures::AccessibilityObjectModelEnabled()) {
+      exception_state.ThrowTypeError(
+          "Accessibility Object Model is not enabled.");
+      return nullptr;
+    }
+    return CreatePermissionDescriptor(PermissionName::ACCESSIBILITY_EVENTS);
+  }
+  if (name == "clipboard-read" || name == "clipboard-write") {
+    PermissionName permission_name = PermissionName::CLIPBOARD_READ;
+    if (name == "clipboard-write")
+      permission_name = PermissionName::CLIPBOARD_WRITE;
+
+    ClipboardPermissionDescriptor* clipboard_permission =
+        NativeValueTraits<ClipboardPermissionDescriptor>::NativeValue(
+            script_state->GetIsolate(), raw_descriptor.V8Value(),
+            exception_state);
+    return CreateClipboardPermissionDescriptor(
+        permission_name, clipboard_permission->allowWithoutGesture(),
+        clipboard_permission->allowWithoutSanitization());
+  }
+  if (name == "payment-handler")
+    return CreatePermissionDescriptor(PermissionName::PAYMENT_HANDLER);
+  if (name == "background-fetch")
+    return CreatePermissionDescriptor(PermissionName::BACKGROUND_FETCH);
+  if (name == "idle-detection")
+    return CreatePermissionDescriptor(PermissionName::IDLE_DETECTION);
+  if (name == "periodic-background-sync")
+    return CreatePermissionDescriptor(PermissionName::PERIODIC_BACKGROUND_SYNC);
+  if (name == "wake-lock") {
+    if (!RuntimeEnabledFeatures::WakeLockEnabled(
+            ExecutionContext::From(script_state))) {
+      exception_state.ThrowTypeError("Wake Lock is not enabled.");
+      return nullptr;
+    }
+    WakeLockPermissionDescriptor* wake_lock_permission =
+        NativeValueTraits<WakeLockPermissionDescriptor>::NativeValue(
+            script_state->GetIsolate(), raw_descriptor.V8Value(),
+            exception_state);
+    if (exception_state.HadException())
+      return nullptr;
+    const String& type = wake_lock_permission->type();
+    if (type == "screen") {
+      return CreateWakeLockPermissionDescriptor(
+          mojom::blink::WakeLockType::kScreen);
+    } else if (type == "system") {
+      return CreateWakeLockPermissionDescriptor(
+          mojom::blink::WakeLockType::kSystem);
+    } else {
+      NOTREACHED();
+    }
+  }
+  if (name == "nfc") {
+    if (!RuntimeEnabledFeatures::WebNFCEnabled(
+            ExecutionContext::From(script_state))) {
+      exception_state.ThrowTypeError("Web NFC is not enabled.");
+      return nullptr;
+    }
+    return CreatePermissionDescriptor(PermissionName::NFC);
+  }
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/permission_utils.h b/third_party/blink/renderer/modules/permissions/permission_utils.h
index 50248b2..e790055c 100644
--- a/third_party/blink/renderer/modules/permissions/permission_utils.h
+++ b/third_party/blink/renderer/modules/permissions/permission_utils.h
@@ -7,11 +7,15 @@
 
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
 namespace blink {
 
 class ExecutionContext;
+class ExceptionState;
+class ScriptState;
+class ScriptValue;
 
 void ConnectToPermissionService(
     ExecutionContext*,
@@ -33,6 +37,18 @@
 mojom::blink::PermissionDescriptorPtr CreateWakeLockPermissionDescriptor(
     mojom::blink::WakeLockType type);
 
+// Parses the raw permission dictionary and returns the Mojo
+// PermissionDescriptor if parsing was successful. If an exception occurs, it
+// will be stored in |exceptionState| and nullptr will be returned.
+//
+// Websites will be able to run code when `name()` is called, changing the
+// current context. The caller should make sure that no assumption is made
+// after this has been called.
+MODULES_EXPORT mojom::blink::PermissionDescriptorPtr ParsePermissionDescriptor(
+    ScriptState*,
+    const ScriptValue& raw_permission,
+    ExceptionState&);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_PERMISSION_UTILS_H_
diff --git a/third_party/blink/renderer/modules/permissions/permissions.cc b/third_party/blink/renderer/modules/permissions/permissions.cc
index f00bb757..511fb0a 100644
--- a/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -11,11 +11,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_clipboard_permission_descriptor.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_midi_permission_descriptor.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_permission_descriptor.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_push_permission_descriptor.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_permission_descriptor.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -36,153 +31,11 @@
 using mojom::blink::PermissionName;
 using mojom::blink::PermissionService;
 
-namespace {
-
-// Parses the raw permission dictionary and returns the Mojo
-// PermissionDescriptor if parsing was successful. If an exception occurs, it
-// will be stored in |exceptionState| and null will be returned. Therefore, the
-// |exceptionState| should be checked before attempting to use the returned
-// permission as the non-null assert will be fired otherwise.
-//
-// Websites will be able to run code when `name()` is called, changing the
-// current context. The caller should make sure that no assumption is made
-// after this has been called.
-PermissionDescriptorPtr ParsePermission(ScriptState* script_state,
-                                        const ScriptValue raw_permission,
-                                        ExceptionState& exception_state) {
-  PermissionDescriptor* permission =
-      NativeValueTraits<PermissionDescriptor>::NativeValue(
-          script_state->GetIsolate(), raw_permission.V8Value(),
-          exception_state);
-
-  if (exception_state.HadException()) {
-    exception_state.ThrowTypeError(exception_state.Message());
-    return nullptr;
-  }
-
-  const String& name = permission->name();
-  if (name == "geolocation")
-    return CreatePermissionDescriptor(PermissionName::GEOLOCATION);
-  if (name == "camera")
-    return CreatePermissionDescriptor(PermissionName::VIDEO_CAPTURE);
-  if (name == "microphone")
-    return CreatePermissionDescriptor(PermissionName::AUDIO_CAPTURE);
-  if (name == "notifications")
-    return CreatePermissionDescriptor(PermissionName::NOTIFICATIONS);
-  if (name == "persistent-storage")
-    return CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE);
-  if (name == "push") {
-    PushPermissionDescriptor* push_permission =
-        NativeValueTraits<PushPermissionDescriptor>::NativeValue(
-            script_state->GetIsolate(), raw_permission.V8Value(),
-            exception_state);
-    if (exception_state.HadException()) {
-      exception_state.ThrowTypeError(exception_state.Message());
-      return nullptr;
-    }
-
-    // Only "userVisibleOnly" push is supported for now.
-    if (!push_permission->userVisibleOnly()) {
-      exception_state.ThrowDOMException(
-          DOMExceptionCode::kNotSupportedError,
-          "Push Permission without userVisibleOnly:true isn't supported yet.");
-      return nullptr;
-    }
-
-    return CreatePermissionDescriptor(PermissionName::NOTIFICATIONS);
-  }
-  if (name == "midi") {
-    MidiPermissionDescriptor* midi_permission =
-        NativeValueTraits<MidiPermissionDescriptor>::NativeValue(
-            script_state->GetIsolate(), raw_permission.V8Value(),
-            exception_state);
-    return CreateMidiPermissionDescriptor(midi_permission->sysex());
-  }
-  if (name == "background-sync")
-    return CreatePermissionDescriptor(PermissionName::BACKGROUND_SYNC);
-  if (name == "ambient-light-sensor" || name == "accelerometer" ||
-      name == "gyroscope" || name == "magnetometer") {
-    // ALS requires an extra flag.
-    if (name == "ambient-light-sensor") {
-      if (!RuntimeEnabledFeatures::SensorExtraClassesEnabled()) {
-        exception_state.ThrowTypeError(
-            "GenericSensorExtraClasses flag is not enabled.");
-        return nullptr;
-      }
-    }
-
-    return CreatePermissionDescriptor(PermissionName::SENSORS);
-  }
-  if (name == "accessibility-events") {
-    if (!RuntimeEnabledFeatures::AccessibilityObjectModelEnabled()) {
-      exception_state.ThrowTypeError(
-          "Accessibility Object Model is not enabled.");
-      return nullptr;
-    }
-    return CreatePermissionDescriptor(PermissionName::ACCESSIBILITY_EVENTS);
-  }
-  if (name == "clipboard-read" || name == "clipboard-write") {
-    PermissionName permission_name = PermissionName::CLIPBOARD_READ;
-    if (name == "clipboard-write")
-      permission_name = PermissionName::CLIPBOARD_WRITE;
-
-    ClipboardPermissionDescriptor* clipboard_permission =
-        NativeValueTraits<ClipboardPermissionDescriptor>::NativeValue(
-            script_state->GetIsolate(), raw_permission.V8Value(),
-            exception_state);
-    return CreateClipboardPermissionDescriptor(
-        permission_name, clipboard_permission->allowWithoutGesture(),
-        clipboard_permission->allowWithoutSanitization());
-  }
-  if (name == "payment-handler")
-    return CreatePermissionDescriptor(PermissionName::PAYMENT_HANDLER);
-  if (name == "background-fetch")
-    return CreatePermissionDescriptor(PermissionName::BACKGROUND_FETCH);
-  if (name == "idle-detection")
-    return CreatePermissionDescriptor(PermissionName::IDLE_DETECTION);
-  if (name == "periodic-background-sync")
-    return CreatePermissionDescriptor(PermissionName::PERIODIC_BACKGROUND_SYNC);
-  if (name == "wake-lock") {
-    if (!RuntimeEnabledFeatures::WakeLockEnabled(
-            ExecutionContext::From(script_state))) {
-      exception_state.ThrowTypeError("Wake Lock is not enabled.");
-      return nullptr;
-    }
-    WakeLockPermissionDescriptor* wake_lock_permission =
-        NativeValueTraits<WakeLockPermissionDescriptor>::NativeValue(
-            script_state->GetIsolate(), raw_permission.V8Value(),
-            exception_state);
-    if (exception_state.HadException())
-      return nullptr;
-    const String& type = wake_lock_permission->type();
-    if (type == "screen") {
-      return CreateWakeLockPermissionDescriptor(
-          mojom::blink::WakeLockType::kScreen);
-    } else if (type == "system") {
-      return CreateWakeLockPermissionDescriptor(
-          mojom::blink::WakeLockType::kSystem);
-    } else {
-      NOTREACHED();
-    }
-  }
-  if (name == "nfc") {
-    if (!RuntimeEnabledFeatures::WebNFCEnabled(
-            ExecutionContext::From(script_state))) {
-      exception_state.ThrowTypeError("Web NFC is not enabled.");
-      return nullptr;
-    }
-    return CreatePermissionDescriptor(PermissionName::NFC);
-  }
-  return nullptr;
-}
-
-}  // anonymous namespace
-
 ScriptPromise Permissions::query(ScriptState* script_state,
                                  const ScriptValue& raw_permission,
                                  ExceptionState& exception_state) {
   PermissionDescriptorPtr descriptor =
-      ParsePermission(script_state, raw_permission, exception_state);
+      ParsePermissionDescriptor(script_state, raw_permission, exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
 
@@ -206,7 +59,7 @@
                                    const ScriptValue& raw_permission,
                                    ExceptionState& exception_state) {
   PermissionDescriptorPtr descriptor =
-      ParsePermission(script_state, raw_permission, exception_state);
+      ParsePermissionDescriptor(script_state, raw_permission, exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
 
@@ -231,7 +84,7 @@
                                   const ScriptValue& raw_permission,
                                   ExceptionState& exception_state) {
   PermissionDescriptorPtr descriptor =
-      ParsePermission(script_state, raw_permission, exception_state);
+      ParsePermissionDescriptor(script_state, raw_permission, exception_state);
   if (exception_state.HadException())
     return ScriptPromise();
 
@@ -261,8 +114,8 @@
   for (wtf_size_t i = 0; i < raw_permissions.size(); ++i) {
     const ScriptValue& raw_permission = raw_permissions[i];
 
-    auto descriptor =
-        ParsePermission(script_state, raw_permission, exception_state);
+    auto descriptor = ParsePermissionDescriptor(script_state, raw_permission,
+                                                exception_state);
     if (exception_state.HadException())
       return ScriptPromise();
 
diff --git a/third_party/blink/renderer/modules/permissions/testing/internals_permission.cc b/third_party/blink/renderer/modules/permissions/testing/internals_permission.cc
new file mode 100644
index 0000000..3e467cb
--- /dev/null
+++ b/third_party/blink/renderer/modules/permissions/testing/internals_permission.cc
@@ -0,0 +1,87 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/permissions/testing/internals_permission.h"
+
+#include <utility>
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions/permission_automation.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/testing/internals.h"
+#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// static
+ScriptPromise InternalsPermission::setPermission(
+    ScriptState* script_state,
+    Internals&,
+    const ScriptValue& raw_descriptor,
+    const String& state,
+    const String& origin,
+    const String& embedding_origin,
+    ExceptionState& exception_state) {
+  mojom::blink::PermissionDescriptorPtr descriptor =
+      ParsePermissionDescriptor(script_state, raw_descriptor, exception_state);
+  if (exception_state.HadException())
+    return ScriptPromise();
+
+  KURL url = url_test_helpers::ToKURL(origin.Utf8());
+  if (!url.IsValid()) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+                                      "'" + origin + "' is not a valid URL.");
+    return ScriptPromise();
+  }
+
+  KURL embedding_url = url_test_helpers::ToKURL(embedding_origin.Utf8());
+  if (!embedding_url.IsValid()) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kSyntaxError,
+        "'" + embedding_origin + "' is not a valid URL.");
+    return ScriptPromise();
+  }
+
+  mojo::Remote<test::mojom::blink::PermissionAutomation> permission_automation;
+  Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
+      permission_automation.BindNewPipeAndPassReceiver());
+  DCHECK(permission_automation.is_bound());
+
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
+  auto* raw_permission_automation = permission_automation.get();
+  raw_permission_automation->SetPermission(
+      std::move(descriptor), ToPermissionStatus(state.Utf8()), url,
+      embedding_url,
+      WTF::Bind(
+          // While we only really need |resolver|, we also take the
+          // mojo::Remote<> so that it remains alive after this function exits.
+          [](ScriptPromiseResolver* resolver,
+             mojo::Remote<test::mojom::blink::PermissionAutomation>,
+             bool success) {
+            if (success)
+              resolver->Resolve();
+            else
+              resolver->Reject();
+          },
+          WrapPersistent(resolver), std::move(permission_automation)));
+
+  return promise;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/testing/internals_permission.h b/third_party/blink/renderer/modules/permissions/testing/internals_permission.h
new file mode 100644
index 0000000..59fd0f0
--- /dev/null
+++ b/third_party/blink/renderer/modules/permissions/testing/internals_permission.h
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_TESTING_INTERNALS_PERMISSION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_TESTING_INTERNALS_PERMISSION_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class ExceptionState;
+class Internals;
+class ScriptPromise;
+class ScriptState;
+class ScriptValue;
+
+class InternalsPermission {
+  STATIC_ONLY(InternalsPermission);
+
+ public:
+  static ScriptPromise setPermission(ScriptState*,
+                                     Internals&,
+                                     const ScriptValue&,
+                                     const String& state,
+                                     const String& origin,
+                                     const String& embedding_origin,
+                                     ExceptionState&);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_TESTING_INTERNALS_PERMISSION_H_
diff --git a/third_party/blink/renderer/modules/permissions/testing/internals_permission.idl b/third_party/blink/renderer/modules/permissions/testing/internals_permission.idl
new file mode 100644
index 0000000..5fe940b
--- /dev/null
+++ b/third_party/blink/renderer/modules/permissions/testing/internals_permission.idl
@@ -0,0 +1,9 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+    ImplementedAs=InternalsPermission
+] partial interface Internals {
+    [CallWith=ScriptState, RaisesException] Promise<void> setPermission(object descriptor, PermissionState state, USVString url, USVString embedding_url);
+};
diff --git a/third_party/blink/renderer/modules/xr/BUILD.gn b/third_party/blink/renderer/modules/xr/BUILD.gn
index 25597618..0da6263 100644
--- a/third_party/blink/renderer/modules/xr/BUILD.gn
+++ b/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -20,6 +20,8 @@
     "xr_bounded_reference_space.h",
     "xr_canvas_input_provider.cc",
     "xr_canvas_input_provider.h",
+    "xr_dom_overlay_state.cc",
+    "xr_dom_overlay_state.h",
     "xr_frame.cc",
     "xr_frame.h",
     "xr_frame_provider.cc",
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc
index 7f84b3f..ddc0079 100644
--- a/third_party/blink/renderer/modules/xr/xr.cc
+++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
+#include "third_party/blink/renderer/core/fullscreen/fullscreen_options.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -126,7 +127,10 @@
 }
 
 bool IsFeatureValidForMode(device::mojom::XRSessionFeature feature,
-                           device::mojom::blink::XRSessionMode mode) {
+                           device::mojom::blink::XRSessionMode mode,
+                           XRSessionInit* session_init,
+                           ExecutionContext* execution_context,
+                           mojom::ConsoleMessageLevel error_level) {
   switch (feature) {
     case device::mojom::XRSessionFeature::REF_SPACE_VIEWER:
     case device::mojom::XRSessionFeature::REF_SPACE_LOCAL:
@@ -137,7 +141,15 @@
       return mode == device::mojom::blink::XRSessionMode::kImmersiveVr ||
              mode == device::mojom::blink::XRSessionMode::kImmersiveAr;
     case device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR:
-      return mode == device::mojom::blink::XRSessionMode::kImmersiveAr;
+      if (mode != device::mojom::blink::XRSessionMode::kImmersiveAr)
+        return false;
+      if (!session_init->hasDomOverlay()) {
+        execution_context->AddConsoleMessage(ConsoleMessage::Create(
+            mojom::ConsoleMessageSource::kJavaScript, error_level,
+            "Must specify a valid domOverlay.root element in XRSessionInit"));
+        return false;
+      }
+      return true;
   }
 }
 
@@ -483,6 +495,90 @@
 
 void XR::PendingRequestSessionQuery::Trace(blink::Visitor* visitor) {
   visitor->Trace(resolver_);
+  visitor->Trace(dom_overlay_element_);
+}
+
+XR::OverlayFullscreenEventManager::OverlayFullscreenEventManager(
+    XR* xr,
+    XR::PendingRequestSessionQuery* query,
+    device::mojom::blink::RequestSessionResultPtr result)
+    : xr_(xr), query_(query), result_(std::move(result)) {
+  DVLOG(2) << __func__;
+}
+
+XR::OverlayFullscreenEventManager::~OverlayFullscreenEventManager() = default;
+
+void XR::OverlayFullscreenEventManager::Invoke(
+    ExecutionContext* execution_context,
+    Event* event) {
+  DVLOG(2) << __func__ << ": event type=" << event->type();
+
+  // This handler should only be called once, it's unregistered after use.
+  DCHECK(query_);
+  DCHECK(result_);
+
+  Element* element = query_->DOMOverlayElement();
+  element->GetDocument().removeEventListener(
+      event_type_names::kFullscreenchange, this, true);
+  element->GetDocument().removeEventListener(event_type_names::kFullscreenerror,
+                                             this, true);
+
+  if (event->type() == event_type_names::kFullscreenchange) {
+    // Succeeded, proceed with session creation.
+    xr_->OnRequestSessionReturned(query_, std::move(result_));
+  }
+
+  if (event->type() == event_type_names::kFullscreenerror) {
+    // Failed, reject the session
+    element->GetDocument().SetIsImmersiveArOverlay(false);
+    xr_->OnRequestSessionReturned(
+        query_, device::mojom::blink::RequestSessionResult::NewFailureReason(
+                    device::mojom::RequestSessionError::INVALID_CLIENT));
+  }
+}
+
+void XR::OverlayFullscreenEventManager::RequestFullscreen() {
+  Element* element = query_->DOMOverlayElement();
+  DCHECK(element);
+
+  // Set the "is immersive AR overlay" property now since that allows fullscreen
+  // element changes without user activation. Requesting the immersive session
+  // had required a user activation state, but that may have expired by now due
+  // to the user taking time to respond to the consent prompt. This is cleared
+  // in the error handler if activating fullscreen mode fails.
+  element->GetDocument().SetIsImmersiveArOverlay(true);
+
+  if (element == Fullscreen::FullscreenElementFrom(element->GetDocument())) {
+    // It's possible that the requested element is already fullscreen, in which
+    // case we must not wait for a fullscreenchange event since it won't arrive.
+    // Detect that and proceed directly with session creation in this case. This
+    // can happen if the site used Fullscreen API to place the element into
+    // fullscreen mode before requesting the session, and if the session can
+    // proceed without needing a consent prompt. (Showing a dialog exits
+    // fullscreen mode.)
+    DVLOG(2) << __func__ << ": requested element already fullscreen";
+    xr_->OnRequestSessionReturned(query_, std::move(result_));
+    return;
+  }
+
+  // Set up event listeners for success and failure.
+  element->GetDocument().addEventListener(event_type_names::kFullscreenchange,
+                                          this, true);
+  element->GetDocument().addEventListener(event_type_names::kFullscreenerror,
+                                          this, true);
+
+  // Use the event-generating unprefixed version of RequestFullscreen to ensure
+  // that the fullscreen event listener is informed once this completes.
+  FullscreenOptions* options = FullscreenOptions::Create();
+  options->setNavigationUI("hide");
+  Fullscreen::RequestFullscreen(*element, options,
+                                Fullscreen::RequestType::kUnprefixed);
+}
+
+void XR::OverlayFullscreenEventManager::Trace(blink::Visitor* visitor) {
+  visitor->Trace(xr_);
+  visitor->Trace(query_);
+  EventListener::Trace(visitor);
 }
 
 device::mojom::blink::XRSessionOptionsPtr XR::XRSessionOptionsFromQuery(
@@ -740,10 +836,18 @@
   // Submit the request to VrServiceImpl in the Browser process
   outstanding_request_queries_.insert(query);
   auto session_options = XRSessionOptionsFromQuery(*query);
-  service_->RequestSession(
-      std::move(session_options),
-      WTF::Bind(&XR::OnRequestSessionReturned, WrapWeakPersistent(this),
-                WrapPersistent(query)));
+
+  // In DOM overlay mode, there's an additional step before an immersive-ar
+  // session can start, we need to enter fullscreen mode by setting the
+  // appropriate element as fullscreen from the Renderer, then waiting for the
+  // browser side to send an event indicating success or failure.
+  auto callback =
+      query->DOMOverlayElement()
+          ? WTF::Bind(&XR::OnRequestSessionSetupForDomOverlay,
+                      WrapWeakPersistent(this), WrapPersistent(query))
+          : WTF::Bind(&XR::OnRequestSessionReturned, WrapWeakPersistent(this),
+                      WrapPersistent(query));
+  service_->RequestSession(std::move(session_options), std::move(callback));
 }
 
 void XR::RequestInlineSession(LocalFrame* frame,
@@ -798,6 +902,7 @@
     Document* doc,
     const HeapVector<ScriptValue>& features,
     const device::mojom::blink::XRSessionMode& session_mode,
+    XRSessionInit* session_init,
     mojom::ConsoleMessageLevel error_level) {
   RequestedXRSessionFeatureSet result;
 
@@ -813,7 +918,9 @@
             mojom::ConsoleMessageSource::kJavaScript, error_level,
             "Unrecognized feature requested: " + feature_string));
         result.invalid_features = true;
-      } else if (!IsFeatureValidForMode(feature_enum.value(), session_mode)) {
+      } else if (!IsFeatureValidForMode(feature_enum.value(), session_mode,
+                                        session_init, GetExecutionContext(),
+                                        error_level)) {
         GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
             mojom::ConsoleMessageSource::kJavaScript, error_level,
             "Feature '" + feature_string + "' is not supported for mode: " +
@@ -880,7 +987,7 @@
   RequestedXRSessionFeatureSet required_features;
   if (session_init && session_init->hasRequiredFeatures()) {
     required_features = ParseRequestedFeatures(
-        doc, session_init->requiredFeatures(), session_mode,
+        doc, session_init->requiredFeatures(), session_mode, session_init,
         mojom::ConsoleMessageLevel::kError);
   }
 
@@ -888,7 +995,7 @@
   RequestedXRSessionFeatureSet optional_features;
   if (session_init && session_init->hasOptionalFeatures()) {
     optional_features = ParseRequestedFeatures(
-        doc, session_init->optionalFeatures(), session_mode,
+        doc, session_init->optionalFeatures(), session_mode, session_init,
         mojom::ConsoleMessageLevel::kWarning);
   }
 
@@ -923,6 +1030,11 @@
           GetSourceId(), resolver, session_mode, std::move(required_features),
           std::move(optional_features));
 
+  if (session_init && session_init->hasDomOverlay()) {
+    DCHECK(session_init->domOverlay()->hasRoot()) << "required in IDL";
+    query->SetDOMOverlayElement(session_init->domOverlay()->root());
+  }
+
   switch (session_mode) {
     case device::mojom::blink::XRSessionMode::kImmersiveVr:
     case device::mojom::blink::XRSessionMode::kImmersiveAr:
@@ -956,6 +1068,23 @@
   query->Resolve(supports_session);
 }
 
+void XR::OnRequestSessionSetupForDomOverlay(
+    PendingRequestSessionQuery* query,
+    device::mojom::blink::RequestSessionResultPtr result) {
+  DCHECK(query->DOMOverlayElement());
+  if (result->is_success()) {
+    // Success. Now request fullscreen mode and continue with
+    // OnRequestSessionReturned once that completes.
+    fullscreen_event_manager_ =
+        MakeGarbageCollected<OverlayFullscreenEventManager>(this, query,
+                                                            std::move(result));
+    fullscreen_event_manager_->RequestFullscreen();
+  } else {
+    // Session request failed, continue processing that normally.
+    OnRequestSessionReturned(query, std::move(result));
+  }
+}
+
 void XR::OnRequestSessionReturned(
     PendingRequestSessionQuery* query,
     device::mojom::blink::RequestSessionResultPtr result) {
@@ -968,6 +1097,10 @@
     DCHECK(has_outstanding_immersive_request_);
     has_outstanding_immersive_request_ = false;
   }
+  // Clean up the fullscreen event manager which may have been added for
+  // DOM overlay setup. We're done with it, and it contains a reference
+  // to the query and the DOM overlay element.
+  fullscreen_event_manager_ = nullptr;
 
   // TODO(https://crbug.com/872316) Improve the error messaging to indicate why
   // a request failed.
@@ -1036,12 +1169,13 @@
       LocalFrame* frame = GetFrame();
       DCHECK(frame);
 
-      if (enabled_features.Contains(
-              device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR)) {
-        // The session is using DOM overlay mode.
+      if (query->DOMOverlayElement()) {
+        // The session is using DOM overlay mode. At this point the overlay
+        // element is already in fullscreen mode, and the session can
+        // proceed.
         Document* doc = frame->GetDocument();
         DCHECK(doc);
-        doc->SetIsImmersiveArOverlay(true);
+        session->SetDOMOverlayElement(query->DOMOverlayElement());
 
         // Save the current base background color (restored in ExitPresent),
         // and set a transparent background for the FrameView.
@@ -1052,25 +1186,6 @@
         frame_view->UpdateLifecycleToCompositingInputsClean();
         original_base_background_color_ = frame_view->BaseBackgroundColor();
         frame_view->SetBaseBackgroundColor(Color::kTransparent);
-
-        // In DOM overlay mode, entering fullscreen mode needs to be triggered
-        // from the Renderer by actually fullscreening an element. If there
-        // is no current fullscreen element, fullscreen the <body> element
-        // for now. The JS application can use enterFullscreen to change this.
-        //
-        // A TabObserver on the browser side exits the session if there's
-        // no longer a fullscreen element, for example if the JS app manually
-        // unfullscreens the "body" element. That ensures we don't end up in a
-        // hybrid non-fullscreen AR state.
-        Element* fullscreen_element = Fullscreen::FullscreenElementFrom(*doc);
-        if (!fullscreen_element) {
-          Element* body = doc->body();
-          DCHECK(body);
-          // FIXME: this is the "prefixed" version that doesn't generate a
-          // fullscreenchange event and auto-hides navigation bars. Should the
-          // event be generated?
-          Fullscreen::RequestFullscreen(*body);
-        }
       }
     }
 
@@ -1202,6 +1317,7 @@
   visitor->Trace(sessions_);
   visitor->Trace(outstanding_support_queries_);
   visitor->Trace(outstanding_request_queries_);
+  visitor->Trace(fullscreen_event_manager_);
   ContextLifecycleObserver::Trace(visitor);
   EventTargetWithInlineData::Trace(visitor);
 }
diff --git a/third_party/blink/renderer/modules/xr/xr.h b/third_party/blink/renderer/modules/xr/xr.h
index 9680fd53..27b1cc1 100644
--- a/third_party/blink/renderer/modules/xr/xr.h
+++ b/third_party/blink/renderer/modules/xr/xr.h
@@ -13,8 +13,10 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/page/focus_changed_observer.h"
+#include "third_party/blink/renderer/modules/xr/xr_dom_overlay_init.h"
 #include "third_party/blink/renderer/modules/xr/xr_session.h"
 #include "third_party/blink/renderer/modules/xr/xr_session_init.h"
 #include "third_party/blink/renderer/platform/graphics/color.h"
@@ -198,6 +200,11 @@
     // Returns underlying resolver's script state.
     ScriptState* GetScriptState() const;
 
+    void SetDOMOverlayElement(Element* element) {
+      dom_overlay_element_ = element;
+    }
+    Element* DOMOverlayElement() { return dom_overlay_element_; }
+
     virtual void Trace(blink::Visitor*);
 
    private:
@@ -219,6 +226,7 @@
 
     const int64_t ukm_source_id_;
 
+    Member<Element> dom_overlay_element_;
     DISALLOW_COPY_AND_ASSIGN(PendingRequestSessionQuery);
   };
 
@@ -277,6 +285,31 @@
     DISALLOW_COPY_AND_ASSIGN(PendingSupportsSessionQuery);
   };
 
+  // Native event listener for fullscreen change / error events when starting an
+  // immersive-ar session that uses DOM Overlay mode. See
+  // OnRequestSessionReturned().
+  class OverlayFullscreenEventManager : public NativeEventListener {
+   public:
+    OverlayFullscreenEventManager(
+        XR* xr,
+        XR::PendingRequestSessionQuery*,
+        device::mojom::blink::RequestSessionResultPtr);
+    ~OverlayFullscreenEventManager() override;
+
+    // NativeEventListener
+    void Invoke(ExecutionContext*, Event*) override;
+
+    void RequestFullscreen();
+
+    void Trace(blink::Visitor*) override;
+
+   private:
+    Member<XR> xr_;
+    Member<PendingRequestSessionQuery> query_;
+    device::mojom::blink::RequestSessionResultPtr result_;
+    DISALLOW_COPY_AND_ASSIGN(OverlayFullscreenEventManager);
+  };
+
   ScriptPromise InternalIsSessionSupported(ScriptState*,
                                            const String&,
                                            ExceptionState& exception_state,
@@ -290,6 +323,7 @@
       Document* doc,
       const HeapVector<ScriptValue>& features,
       const device::mojom::blink::XRSessionMode& session_mode,
+      XRSessionInit* session_init,
       mojom::ConsoleMessageLevel error_level);
 
   void RequestImmersiveSession(LocalFrame* frame,
@@ -301,11 +335,18 @@
                             PendingRequestSessionQuery* query,
                             ExceptionState* exception_state);
 
+  void OnRequestSessionSetupForDomOverlay(
+      PendingRequestSessionQuery*,
+      device::mojom::blink::RequestSessionResultPtr result);
   void OnRequestSessionReturned(
       PendingRequestSessionQuery*,
       device::mojom::blink::RequestSessionResultPtr result);
   void OnSupportsSessionReturned(PendingSupportsSessionQuery*,
                                  bool supports_session);
+  void ResolveSessionRequest(
+      PendingRequestSessionQuery*,
+      device::mojom::blink::RequestSessionResultPtr result);
+  void RejectSessionRequest(PendingRequestSessionQuery*);
 
   void EnsureDevice();
   void ReportImmersiveSupported(bool supported);
@@ -364,6 +405,11 @@
   FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle
       feature_handle_for_scheduler_;
 
+  // In DOM overlay mode, use a fullscreen event listener to detect when
+  // transition to fullscreen mode completes or fails, and reject/resolve
+  // the pending request session promise accordingly.
+  Member<OverlayFullscreenEventManager> fullscreen_event_manager_;
+
   // In DOM overlay mode, save and restore the FrameView background color.
   Color original_base_background_color_;
 
diff --git a/third_party/blink/renderer/modules/xr/xr_dom_overlay_init.idl b/third_party/blink/renderer/modules/xr/xr_dom_overlay_init.idl
new file mode 100644
index 0000000..7a7d279
--- /dev/null
+++ b/third_party/blink/renderer/modules/xr/xr_dom_overlay_init.idl
@@ -0,0 +1,8 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://immersive-web.github.io/dom-overlays/#dictdef-xrdomoverlayinit
+dictionary XRDOMOverlayInit {
+  required Element root;
+};
diff --git a/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.cc b/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.cc
new file mode 100644
index 0000000..84290fd
--- /dev/null
+++ b/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/xr/xr_dom_overlay_state.h"
+
+#include "third_party/blink/renderer/core/dom/element.h"
+
+namespace blink {
+
+namespace {
+
+const String MapOverlayType(XRDOMOverlayState::DOMOverlayType type) {
+  switch (type) {
+    case XRDOMOverlayState::DOMOverlayType::kScreen:
+      return "screen";
+    case XRDOMOverlayState::DOMOverlayType::kFloating:
+      return "floating";
+  }
+}
+
+}  // namespace
+
+XRDOMOverlayState::XRDOMOverlayState(DOMOverlayType type)
+    : type_string_(MapOverlayType(type)) {}
+
+void XRDOMOverlayState::Trace(blink::Visitor* visitor) {
+  ScriptWrappable::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.h b/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.h
new file mode 100644
index 0000000..bd590c04
--- /dev/null
+++ b/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.h
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DOM_OVERLAY_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DOM_OVERLAY_STATE_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// Implementation of
+// https://immersive-web.github.io/dom-overlays/#dictdef-xrdomoverlaystate, used
+// as SameObject instances owned by |XRSession|.
+class XRDOMOverlayState : public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  enum class DOMOverlayType {
+    kScreen = 0,
+    kFloating,
+  };
+
+  explicit XRDOMOverlayState(DOMOverlayType type);
+  ~XRDOMOverlayState() override = default;
+
+  const String& type() const { return type_string_; }
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  const String type_string_;
+  // Currently, instances of this class are created at session start, on the
+  // assumption that the objects are very small. If this becomes more complex in
+  // the future, i.e. when adding additional members, consider switching to lazy
+  // instantiation.
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DOM_OVERLAY_STATE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.idl b/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.idl
new file mode 100644
index 0000000..dfd0f9a
--- /dev/null
+++ b/third_party/blink/renderer/modules/xr/xr_dom_overlay_state.idl
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://immersive-web.github.io/dom-overlays/#enumdef-xrdomoverlaytype
+enum XRDOMOverlayType {
+  "screen",
+  "floating",
+};
+
+// https://immersive-web.github.io/dom-overlays/#dictdef-xrdomoverlaystate
+[
+    SecureContext,
+    Exposed=Window,
+    RuntimeEnabled=WebXRIncubations
+] interface XRDOMOverlayState {
+  readonly attribute XRDOMOverlayType type;
+};
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc
index 37f6cba6..b4c6acd6 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/renderer/modules/xr/xr_anchor_set.h"
 #include "third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h"
 #include "third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h"
+#include "third_party/blink/renderer/modules/xr/xr_dom_overlay_state.h"
 #include "third_party/blink/renderer/modules/xr/xr_frame.h"
 #include "third_party/blink/renderer/modules/xr/xr_frame_provider.h"
 #include "third_party/blink/renderer/modules/xr/xr_hit_result.h"
@@ -345,6 +346,24 @@
   }
 }
 
+void XRSession::SetDOMOverlayElement(Element* element) {
+  DVLOG(2) << __func__ << ": element=" << element;
+  DCHECK(enabled_features_.Contains(
+      device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR));
+  DCHECK(element);
+
+  overlay_element_ = element;
+
+  // Set up the domOverlayState attribute. This could be done lazily on first
+  // access, but it's a tiny object and it's unclear if the memory that might
+  // save during XR sessions is worth the code size increase to do so. This
+  // should be revisited if the state gets more complex in the future.
+  //
+  // At this time, "screen" is the only supported DOM Overlay type.
+  dom_overlay_state_ = MakeGarbageCollected<XRDOMOverlayState>(
+      XRDOMOverlayState::DOMOverlayType::kScreen);
+}
+
 const String XRSession::visibilityState() const {
   switch (visibility_state_) {
     case XRVisibilityState::VISIBLE:
@@ -1854,6 +1873,8 @@
   visitor->Trace(input_sources_);
   visitor->Trace(resize_observer_);
   visitor->Trace(canvas_input_provider_);
+  visitor->Trace(overlay_element_);
+  visitor->Trace(dom_overlay_state_);
   visitor->Trace(callback_collection_);
   visitor->Trace(hit_test_promises_);
   visitor->Trace(create_anchor_promises_);
diff --git a/third_party/blink/renderer/modules/xr/xr_session.h b/third_party/blink/renderer/modules/xr/xr_session.h
index cb6d471..1f530e1 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.h
+++ b/third_party/blink/renderer/modules/xr/xr_session.h
@@ -39,6 +39,7 @@
 class XRAnchor;
 class XRAnchorSet;
 class XRCanvasInputProvider;
+class XRDOMOverlayState;
 class XRHitTestOptionsInit;
 class XRHitTestSource;
 class XRPlane;
@@ -101,6 +102,7 @@
 
   XR* xr() const { return xr_; }
   const String& environmentBlendMode() const { return blend_mode_string_; }
+  XRDOMOverlayState* domOverlayState() const { return dom_overlay_state_; }
   const String visibilityState() const;
   XRRenderState* renderState() const { return render_state_; }
   XRWorldTrackingState* worldTrackingState() { return world_tracking_state_; }
@@ -182,6 +184,8 @@
   DoubleSize OutputCanvasSize() const;
   void DetachOutputCanvas(HTMLCanvasElement* output_canvas);
 
+  void SetDOMOverlayElement(Element* element);
+
   void LogGetPose() const;
 
   // EventTarget overrides.
@@ -406,6 +410,8 @@
   Member<XRWebGLLayer> prev_base_layer_;
   Member<ResizeObserver> resize_observer_;
   Member<XRCanvasInputProvider> canvas_input_provider_;
+  Member<Element> overlay_element_;
+  Member<XRDOMOverlayState> dom_overlay_state_;
   bool environment_error_handler_subscribed_ = false;
   HeapHashSet<Member<ScriptPromiseResolver>> hit_test_promises_;
   // Set of promises returned from CreateAnchor that are still in-flight.
diff --git a/third_party/blink/renderer/modules/xr/xr_session.idl b/third_party/blink/renderer/modules/xr/xr_session.idl
index 4638ba0..f71e1a4 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.idl
+++ b/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -32,6 +32,7 @@
   readonly attribute XRVisibilityState visibilityState;
   [SameObject] readonly attribute XRRenderState renderState;
   [MeasureAs=XRSessionGetInputSources, SameObject] readonly attribute XRInputSourceArray inputSources;
+  [RuntimeEnabled=WebXRIncubations, SameObject] readonly attribute XRDOMOverlayState domOverlayState;
 
   attribute EventHandler onend;
   attribute EventHandler onselect;
diff --git a/third_party/blink/renderer/modules/xr/xr_session_init.idl b/third_party/blink/renderer/modules/xr/xr_session_init.idl
index 5de94651..705227f 100644
--- a/third_party/blink/renderer/modules/xr/xr_session_init.idl
+++ b/third_party/blink/renderer/modules/xr/xr_session_init.idl
@@ -6,4 +6,5 @@
 dictionary XRSessionInit {
   sequence<any> requiredFeatures;
   sequence<any> optionalFeatures;
+  [RuntimeEnabled=WebXRIncubations] XRDOMOverlayInit domOverlay;
 };
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
index da31a21d..264b8d0 100644
--- a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
+++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
@@ -199,8 +199,8 @@
 
 base::TimeDelta ThreadHeapStatsCollector::Event::background_marking_time()
     const {
-  return base::TimeDelta::FromMicroseconds(
-      base::subtle::NoBarrier_Load(&concurrent_scope_data[kConcurrentMark]));
+  return base::TimeDelta::FromMicroseconds(base::subtle::NoBarrier_Load(
+      &concurrent_scope_data[kConcurrentMarkingStep]));
 }
 
 base::TimeDelta ThreadHeapStatsCollector::Event::marking_time() const {
@@ -233,7 +233,7 @@
 base::TimeDelta ThreadHeapStatsCollector::Event::background_sweeping_time()
     const {
   return base::TimeDelta::FromMicroseconds(
-      concurrent_scope_data[kConcurrentSweep]);
+      concurrent_scope_data[kConcurrentSweepingStep]);
 }
 
 base::TimeDelta ThreadHeapStatsCollector::Event::sweeping_time() const {
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
index 4e8a2bd..9589294 100644
--- a/third_party/blink/renderer/platform/heap/heap_stats_collector.h
+++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -67,8 +67,8 @@
   V(VisitStackRoots)
 
 #define FOR_ALL_CONCURRENT_SCOPES(V) \
-  V(ConcurrentMark)                  \
-  V(ConcurrentSweep)
+  V(ConcurrentMarkingStep)           \
+  V(ConcurrentSweepingStep)
 
 // Manages counters and statistics across garbage collection cycles.
 //
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc
index 08d102eb..b196480 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -529,7 +529,8 @@
   // Concurrent sweeper doesn't call finalizers - this guarantees that sweeping
   // is not called recursively.
   ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope(
-      Heap().stats_collector(), ThreadHeapStatsCollector::kConcurrentSweep);
+      Heap().stats_collector(),
+      ThreadHeapStatsCollector::kConcurrentSweepingStep);
   const bool finished = Heap().AdvanceSweep(
       ThreadHeap::SweepingType::kConcurrent,
       base::TimeTicks::Now() + kConcurrentSweepStepDuration);
@@ -1743,7 +1744,8 @@
   VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] "
           << "ConcurrentMark";
   ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope(
-      Heap().stats_collector(), ThreadHeapStatsCollector::kConcurrentMark);
+      Heap().stats_collector(),
+      ThreadHeapStatsCollector::kConcurrentMarkingStep);
 
   uint8_t task_id;
   {
diff --git a/third_party/blink/renderer/platform/mojo/geometry.typemap b/third_party/blink/renderer/platform/mojo/geometry.typemap
index 20ae890..636bfca 100644
--- a/third_party/blink/renderer/platform/mojo/geometry.typemap
+++ b/third_party/blink/renderer/platform/mojo/geometry.typemap
@@ -32,7 +32,7 @@
 # TODO(zqzhang): ideally, gfx.mojom.Size should be mapped into ::blink::IntSize.
 # However that introduces an link issue on Windows. See https://crbug.com/653323
 type_mappings = [
-  "gfx.mojom.Point=::blink::WebPoint",
+  "gfx.mojom.Point=::gfx::Point",
   "gfx.mojom.PointF=::gfx::PointF",
   "gfx.mojom.Point3F=::blink::FloatPoint3D",
   "gfx.mojom.Quaternion=::gfx::Quaternion",
diff --git a/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc b/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
index 8e279d0..eaf58d28 100644
--- a/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
+++ b/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
@@ -32,7 +32,7 @@
 
  private:
   // GeometryTraitsTestService:
-  void EchoPoint(const WebPoint& p, EchoPointCallback callback) override {
+  void EchoPoint(const gfx::Point& p, EchoPointCallback callback) override {
     std::move(callback).Run(p);
   }
 
@@ -116,17 +116,6 @@
   EXPECT_EQ(input, output);
 }
 
-TEST_F(GeometryStructTraitsTest, Point) {
-  const float kX = 1234;
-  const float kY = 5678;
-  WebPoint input(kX, kY);
-  mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
-      GetTraitsTestProxy();
-  WebPoint output;
-  proxy->EchoPoint(input, &output);
-  EXPECT_EQ(input, output);
-}
-
 TEST_F(GeometryStructTraitsTest, Point3D) {
   const float kX = 1.234;
   const float kY = 5.678;
diff --git a/third_party/blink/web_tests/PRESUBMIT.py b/third_party/blink/web_tests/PRESUBMIT.py
index 39cb587..ce4e052 100644
--- a/third_party/blink/web_tests/PRESUBMIT.py
+++ b/third_party/blink/web_tests/PRESUBMIT.py
@@ -50,6 +50,9 @@
             input_api.os_path.join(this_dir, 'virtual') in path or
             input_api.os_path.join(this_dir, 'flag-specific') in path):
             continue
+        # Temporary workaround for crbug.com/1041588
+        if path.endswith('http/tests/security/sandbox-iframe-allows-modals-expected.txt'):
+            continue
         baseline_files.append(path)
     return baseline_files
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index ff95fa8..8a0420c 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6380,7 +6380,8 @@
 # Sheriff 2019-12-23
 crbug.com/1036626 http/tests/devtools/tracing/tracing-record-input-events.js [ Pass Failure ]
 crbug.com/1036626 virtual/threaded/http/tests/devtools/tracing/tracing-record-input-events.js [ Pass Failure ]
-crbug.com/1036054 [ Retina ] virtual/threaded/fast/scroll-snap/snap-to-area-with-fractional-offset.html [ Pass Timeout ]
+crbug.com/1034789 [ Mac10.13 ] virtual/threaded/fast/scroll-snap/snap-to-area-with-fractional-offset.html [ Pass Timeout ]
+crbug.com/1034789 [ Retina ] virtual/threaded/fast/scroll-snap/snap-to-area-with-fractional-offset.html [ Pass Timeout ]
 crbug.com/1033381 synthetic_gestures/smooth-scroll-tiny-delta.html [ Pass Crash ]
 
 # Sheriff 2019-12-27
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
index 8ddb6cf..c97bcba 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -37,6 +37,18 @@
      {}
     ]
    ],
+   "css/css-grid/subgrid/contain-strict-nested-subgrid-crash.html": [
+    [
+     "css/css-grid/subgrid/contain-strict-nested-subgrid-crash.html",
+     {}
+    ]
+   ],
+   "css/css-grid/subgrid/contain-strict-subgrid-crash.html": [
+    [
+     "css/css-grid/subgrid/contain-strict-subgrid-crash.html",
+     {}
+    ]
+   ],
    "css/css-multicol/abspos-in-multicol-with-spanner-crash.html": [
     [
      "css/css-multicol/abspos-in-multicol-with-spanner-crash.html",
@@ -79327,6 +79339,30 @@
      {}
     ]
    ],
+   "css/css-text/white-space/white-space-zero-fontsize-001.html": [
+    [
+     "css/css-text/white-space/white-space-zero-fontsize-001.html",
+     [
+      [
+       "/css/css-text/white-space/reference/white-space-zero-fontsize-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/white-space-zero-fontsize-002.html": [
+    [
+     "css/css-text/white-space/white-space-zero-fontsize-002.html",
+     [
+      [
+       "/css/css-text/white-space/reference/white-space-zero-fontsize-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-text/word-boundary/word-boundary-001.html": [
     [
      "css/css-text/word-boundary/word-boundary-001.html",
@@ -148566,6 +148602,12 @@
    "css/css-text/white-space/reference/white-space-wrap-after-nowrap-001-ref.html": [
     []
    ],
+   "css/css-text/white-space/reference/white-space-zero-fontsize-001-ref.html": [
+    []
+   ],
+   "css/css-text/white-space/reference/white-space-zero-fontsize-002-ref.html": [
+    []
+   ],
    "css/css-text/white-space/seg-break-transformation-001-expected.txt": [
     []
    ],
@@ -393393,7 +393435,7 @@
    "reftest"
   ],
   "css/css-grid/grid-layout-properties.html": [
-   "0debe91f9246f67753cdb89c62ef818cbba73063",
+   "7cdda674b4759ef50766416fb5399033a0f09f06",
    "testharness"
   ],
   "css/css-grid/grid-model/display-grid.html": [
@@ -394032,6 +394074,14 @@
    "995b1a8d2ae1aaa7c0230379e5b799b12ac9e93c",
    "reftest"
   ],
+  "css/css-grid/subgrid/contain-strict-nested-subgrid-crash.html": [
+   "a98e43777eee9347ba1d69a4b133140cea0577fc",
+   "crashtest"
+  ],
+  "css/css-grid/subgrid/contain-strict-subgrid-crash.html": [
+   "0d377175b7b6aa6b8fd5ba0dc3e3f3ed20f8aad2",
+   "crashtest"
+  ],
   "css/css-grid/subgrid/grid-gap-001-ref.html": [
    "e7909fc2064e4d3498ab90da179cf4ad0d0e9c79",
    "support"
@@ -414088,6 +414138,14 @@
    "80b2260cbbe6122e90c297ab1f2cd83917712030",
    "support"
   ],
+  "css/css-text/white-space/reference/white-space-zero-fontsize-001-ref.html": [
+   "3c27ed25beed79a983f221c203f9aa72abe2beca",
+   "support"
+  ],
+  "css/css-text/white-space/reference/white-space-zero-fontsize-002-ref.html": [
+   "6d2134ac4da3fc7bc3ce78fea834f2037e47cf6c",
+   "support"
+  ],
   "css/css-text/white-space/seg-break-transformation-000.html": [
    "cb7b0f30b566320c1022f61fde44bc09695badb1",
    "testharness"
@@ -414432,6 +414490,14 @@
    "a484f1cf9167e468063cf2205493b8e71a254470",
    "reftest"
   ],
+  "css/css-text/white-space/white-space-zero-fontsize-001.html": [
+   "900e1143f2fd84ed68892be4622f93e678250ab9",
+   "reftest"
+  ],
+  "css/css-text/white-space/white-space-zero-fontsize-002.html": [
+   "1b8d3b7eb60f07d12ea87d3464c228269262ec7d",
+   "reftest"
+  ],
   "css/css-text/word-boundary/reference/word-boundary-001-ref.html": [
    "620079f6ad48bba3d65a9bcd92edfd717228b973",
    "support"
@@ -449873,11 +449939,11 @@
    "support"
   ],
   "eventsource/resources/cors-cookie.py": [
-   "7deaff498d7c0c077f6417cd725725ca55039b96",
+   "c35824ff437feed72364181b57d7732c170722ab",
    "support"
   ],
   "eventsource/resources/cors.py": [
-   "d01596c8366367b87e4fcfd971208c3e44604f31",
+   "42a0a0bb5843389674453fc56d8a87c67cd48dcd",
    "support"
   ],
   "eventsource/resources/eventsource-onmessage-realm.htm": [
@@ -449889,7 +449955,7 @@
    "support"
   ],
   "eventsource/resources/last-event-id.py": [
-   "09e4f29731a1d597172b64311c6400a189a4dd20",
+   "2b74bf66a286ff65b386662412018002c762dee2",
    "support"
   ],
   "eventsource/resources/message.py": [
@@ -516657,7 +516723,7 @@
    "support"
   ],
   "tools/serve/serve.py": [
-   "1868b1a36e51c187491d73aa2708484da882042f",
+   "f33846bc24c042729857113f8e8be9387b9a8e56",
    "support"
   ],
   "tools/serve/test_functional.py": [
@@ -520709,7 +520775,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/environment.py": [
-   "7dcea4aeafabb9c481dccdc1aaf9bd153572bb7d",
+   "608b24dfd3ad878a95d27b030e17890d27eb9a0a",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/__init__.py": [
@@ -520753,7 +520819,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executorservo.py": [
-   "2b8e865fa9bd1f0f62a1b9cbd6f79ffd0bcb8d46",
+   "8f8e120e66da6403f256f99f279f1f5dc8008272",
    "support"
   ],
   "tools/wptrunner/wptrunner/executors/executorservodriver.py": [
@@ -538057,7 +538123,7 @@
    "support"
   ],
   "wpt.py": [
-   "c65e1ed2c6cde4d3abd9e9a771f02542398fec49",
+   "affba7343eadfd1b6144febf6c0083ddd970db71",
    "support"
   ],
   "x-frame-options/META.yml": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties.html b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties.html
index 0debe91f..7cdda674 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/grid-layout-properties.html
@@ -79,8 +79,8 @@
 
     }({
       'grid-template-columns': { // named 'grid-definition-columns' in last draft
-        initial: '150px',
-        'none': ['none', '150px'],
+        initial: 'none',
+        'none': ['none', 'none'],
         '<line-names>': ['[a] auto [b] auto [c]', '[a] 150px [b] 100px [c]'],
         '<track-size>.auto': ['auto', '150px'],
         '<track-size>.<track-breadth>.<length>': ['100px', '100px'],
@@ -89,20 +89,20 @@
         '<track-size>.<track-breadth>.min-content': ['min-content', '100px'],
         '<track-size>.<track-breadth>.max-content': ['max-content', '150px'],
         '<track-size>.<track-breadth>.minmax()': ['minmax(100px, 200px)', '200px'],
-        'reset': ['none', '150px'],
+        'reset': ['none', 'none'],
       },
       'grid-template-rows': { // named 'grid-definition-rows' in last draft
-        initial: '50px 50px 50px',
-        'none': ['none', '50px 50px 50px'],
-        '<line-names>': ['[a] auto [b] auto [c]', '[a] 50px [b] 50px [c] 50px'],
-        '<track-size>.auto': ['auto', '50px 50px 50px'],
-        '<track-size>.<track-breadth>.<length>': ['100px', '100px 50px 50px'],
-        '<track-size>.<track-breadth>.<percentage>': ['100%', '150px 50px 50px'],
-        '<track-size>.<track-breadth>.<flex>': ['1fr', '50px 50px 50px'],
-        '<track-size>.<track-breadth>.min-content': ['min-content', '50px 50px 50px'],
-        '<track-size>.<track-breadth>.max-content': ['max-content', '50px 50px 50px'],
-        '<track-size>.<track-breadth>.minmax()': ['minmax(100px, 200px)', '200px 50px 50px'],
-        'reset': ['none', '50px 50px 50px'],
+        initial: 'none',
+        'none': ['none', 'none'],
+        '<line-names>': ['[a] auto [b] auto [c]', '[a] 50px [b] 50px [c]'],
+        '<track-size>.auto': ['auto', '50px'],
+        '<track-size>.<track-breadth>.<length>': ['100px', '100px'],
+        '<track-size>.<track-breadth>.<percentage>': ['100%', '50px'],
+        '<track-size>.<track-breadth>.<flex>': ['1fr', '50px'],
+        '<track-size>.<track-breadth>.min-content': ['min-content', '50px'],
+        '<track-size>.<track-breadth>.max-content': ['max-content', '50px'],
+        '<track-size>.<track-breadth>.minmax()': ['minmax(100px, 200px)', '200px'],
+        'reset': ['none', 'none'],
       },
       'grid-template-areas': {
         initial: 'none',
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contain-strict-nested-subgrid-crash.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contain-strict-nested-subgrid-crash.html
new file mode 100644
index 0000000..a98e437
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contain-strict-nested-subgrid-crash.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1606485">
+<style>
+* {
+  grid-template-rows: subgrid;
+  display: grid;
+  overflow: scroll;
+  contain: strict;
+}
+</style>
+<script>
+document.addEventListener('DOMContentLoaded', function() {
+  let e = document.createElement('s');
+  document.documentElement.appendChild(e);
+  document.documentElement.getBoundingClientRect() // Update layout
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contain-strict-subgrid-crash.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contain-strict-subgrid-crash.html
new file mode 100644
index 0000000..0d37717
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contain-strict-subgrid-crash.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<head>
+<title>contain: strict element with subgrid properties</title>
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1606485">
+</head>
+<style>
+
+#gridcontainer {
+  display: grid;
+  contain: strict;
+}
+
+.item {
+  display: grid;
+  grid: subgrid [x] / subgrid [x];
+}
+</style>
+<div id="gridcontainer">
+<div class="item">Text1</div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/white-space-zero-fontsize-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/white-space-zero-fontsize-001-ref.html
new file mode 100644
index 0000000..3c27ed25
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/white-space-zero-fontsize-001-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Text test reference</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<style>
+pre {
+  font-size: 12px;
+  float: left;
+  border: 1px solid black;
+  margin: 12px;
+}
+</style>
+<pre>
+foo
+bar
+</pre>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/white-space-zero-fontsize-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/white-space-zero-fontsize-002-ref.html
new file mode 100644
index 0000000..6d2134a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/white-space-zero-fontsize-002-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Text test reference</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<style>
+pre {
+  font-size: 12px;
+  float: left;
+  border: 1px solid black;
+  margin: 12px;
+  -moz-tab-size: 100px;
+  tab-size: 100px;
+}
+</style>
+<pre>
+<span>foo</span>&#x9;<span>bar</span>
+</pre>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/white-space-zero-fontsize-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/white-space-zero-fontsize-001.html
new file mode 100644
index 0000000..900e1143
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/white-space-zero-fontsize-001.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Text Test: preserved white space with zero font-size</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-property">
+<link rel="match" href="reference/white-space-zero-fontsize-001-ref.html">
+<meta name="assert" content="Forced line break in preserved white space is respected even when font-size is zero">
+<style>
+pre {
+  font-size: 0;
+  float: left;
+  border: 1px solid black;
+  margin: 12px;
+}
+span { font-size: 12px; }
+</style>
+<pre>
+<span>foo</span>
+<span>bar</span>
+</pre>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/white-space-zero-fontsize-002.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/white-space-zero-fontsize-002.html
new file mode 100644
index 0000000..1b8d3b7e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/white-space-zero-fontsize-002.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CSS Text Test: preserved white space with zero font-size</title>
+<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-property">
+<link rel="match" href="reference/white-space-zero-fontsize-002-ref.html">
+<meta name="assert" content="Tab in preserved white space is respected even when font-size is zero">
+<style>
+pre {
+  font-size: 0;
+  float: left;
+  border: 1px solid black;
+  margin: 12px;
+  -moz-tab-size: 100px;
+  tab-size: 100px;
+}
+span { font-size: 12px; }
+</style>
+<pre>
+<span>foo</span>&#x9;<span>bar</span>
+</pre>
diff --git a/third_party/blink/web_tests/external/wpt/eventsource/resources/cors-cookie.py b/third_party/blink/web_tests/external/wpt/eventsource/resources/cors-cookie.py
index 7deaff49..c35824f 100644
--- a/third_party/blink/web_tests/external/wpt/eventsource/resources/cors-cookie.py
+++ b/third_party/blink/web_tests/external/wpt/eventsource/resources/cors-cookie.py
@@ -1,7 +1,8 @@
 from datetime import datetime
+from six import ensure_str
 
 def main(request, response):
-    last_event_id = request.headers.get("Last-Event-Id", "")
+    last_event_id = ensure_str(request.headers.get("Last-Event-Id", ""))
     ident = request.GET.first('ident', "test")
     cookie = "COOKIE" if ident in request.cookies else "NO_COOKIE"
     origin = request.GET.first('origin', request.headers["origin"])
diff --git a/third_party/blink/web_tests/external/wpt/eventsource/resources/cors.py b/third_party/blink/web_tests/external/wpt/eventsource/resources/cors.py
index d01596c..42a0a0b 100644
--- a/third_party/blink/web_tests/external/wpt/eventsource/resources/cors.py
+++ b/third_party/blink/web_tests/external/wpt/eventsource/resources/cors.py
@@ -4,7 +4,7 @@
 def run_other(request, response, path):
     #This is a terrible hack
     environ = {"__file__": path}
-    execfile(path, environ, environ)
+    exec(compile(open(path, "r").read(), path, 'exec'), environ, environ)
     rv = environ["main"](request, response)
     return rv
 
diff --git a/third_party/blink/web_tests/external/wpt/eventsource/resources/last-event-id.py b/third_party/blink/web_tests/external/wpt/eventsource/resources/last-event-id.py
index 09e4f29..2b74bf6 100644
--- a/third_party/blink/web_tests/external/wpt/eventsource/resources/last-event-id.py
+++ b/third_party/blink/web_tests/external/wpt/eventsource/resources/last-event-id.py
@@ -1,7 +1,9 @@
+from six import ensure_str
+
 def main(request, response):
   response.headers.set("Content-Type", "text/event-stream")
 
-  last_event_id = request.headers.get("Last-Event-ID", None)
+  last_event_id = ensure_str(request.headers.get("Last-Event-ID", ""))
   if last_event_id:
     return "data: " + last_event_id + "\n\n"
   else:
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt
deleted file mode 100644
index 38cabd5..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Sandboxed Cross-Origin-Opener-Policy popup should result in a network error assert_unreached: A COOP popup was created from a sandboxed frame Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js b/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
index b45ff20..54788b4 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
@@ -891,6 +891,11 @@
         case 'tracked-pointer':
           input_desc.targetRayMode = device.mojom.XRTargetRayMode.POINTING;
           break;
+        case 'screen':
+          input_desc.targetRayMode = device.mojom.XRTargetRayMode.TAPPING;
+          break;
+        default:
+          throw new Error('Unhandled target ray mode ' + this.target_ray_mode_);
       }
 
       switch (this.handedness_) {
diff --git a/third_party/blink/web_tests/external/wpt/tools/serve/serve.py b/third_party/blink/web_tests/external/wpt/tools/serve/serve.py
index 1868b1a..f33846b 100644
--- a/third_party/blink/web_tests/external/wpt/tools/serve/serve.py
+++ b/third_party/blink/web_tests/external/wpt/tools/serve/serve.py
@@ -351,7 +351,7 @@
         if headers is None:
             headers = {}
         handler = handlers.StaticHandler(path, format_args, content_type, **headers)
-        self.add_handler(b"GET", str(route), handler)
+        self.add_handler("GET", str(route), handler)
 
     def add_mount_point(self, url_base, path):
         url_base = "/%s/" % url_base.strip("/") if url_base != "/" else "/"
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py
index 7dcea4a..608b24df 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/environment.py
@@ -192,7 +192,7 @@
             data += fp.read()
         with open(os.path.join(here, "testdriver-extra.js"), "rb") as fp:
             data += fp.read()
-        route_builder.add_handler(b"GET", b"/resources/testdriver.js",
+        route_builder.add_handler("GET", "/resources/testdriver.js",
                                   StringHandler(data, "text/javascript"))
 
         for url_base, paths in iteritems(self.test_paths):
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorservo.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
index 2b8e865..8f8e120e 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
@@ -7,7 +7,7 @@
 import threading
 import traceback
 import uuid
-from six import iteritems
+from six import ensure_str, iteritems
 
 from mozprocess import ProcessHandler
 
@@ -260,10 +260,10 @@
             if rv != 0 or not os.path.exists(output_path):
                 return False, ("CRASH", None)
 
-            with open(output_path) as f:
+            with open(output_path, "rb") as f:
                 # Might need to strip variable headers or something here
                 data = f.read()
-                return True, base64.b64encode(data)
+                return True, ensure_str(base64.b64encode(data))
 
     def do_test(self, test):
         result = self.implementation.run_test(test)
diff --git a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js
index 3d9bfa2..d56a4925f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js
+++ b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_constants.js
@@ -157,3 +157,10 @@
     pointerOrigin: VALID_POINTER_TRANSFORM,
     profiles: []
 };
+
+const SCREEN_CONTROLLER = {
+    handedness: "none",
+    targetRayMode: "screen",
+    pointerOrigin: VALID_POINTER_TRANSFORM,
+    profiles: []
+};
diff --git a/third_party/blink/web_tests/external/wpt/wpt.py b/third_party/blink/web_tests/external/wpt/wpt.py
index c65e1ed2c..affba73 100644
--- a/third_party/blink/web_tests/external/wpt/wpt.py
+++ b/third_party/blink/web_tests/external/wpt/wpt.py
@@ -1,3 +1,3 @@
 # This file exists to allow `python wpt <command>` to work on Windows:
 # https://github.com/web-platform-tests/wpt/pull/6907
-execfile("wpt")
+exec(compile(open("wpt", "r").read(), "wpt", 'exec'))
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-expected.txt
deleted file mode 100644
index fd5b1a5d..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-expected.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-This test checks that the align-content property is applied correctly when using content-distribution values.
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-lr-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-lr-expected.txt
deleted file mode 100644
index fd5b1a5d..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-lr-expected.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-This test checks that the align-content property is applied correctly when using content-distribution values.
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-lr.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-lr.html
deleted file mode 100644
index 9a01571..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-lr.html
+++ /dev/null
@@ -1,342 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0px;
-}
-
-.grid {
-    grid-auto-columns: 20px;
-    grid-auto-rows: 40px;
-    position: relative;
-    width: 400px;
-    height: 300px;
-}
-
-.stretchedGrid {
-    grid-auto-rows: auto;
-}
-
-.thirdRowFirstColumn {
-    background-color: magenta;
-    grid-column: 1;
-    grid-row: 3;
-}
-
-.thirdRowSecondColumn {
-    background-color: navy;
-    grid-column: 2;
-    grid-row: 3;
-}
-
-.fourthRowFirstColumn {
-    background-color: green;
-    grid-column: 1;
-    grid-row: 4;
-}
-
-.fourthRowSecondColumn {
-    background-color: pink;
-    grid-column: 2;
-    grid-row: 4;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the align-content property is applied correctly when using content-distribution values.</p>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="360" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="360" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="80" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="80" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="280" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="280" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="107" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="107" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="253" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="253" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="200" data-offset-y="20" data-expected-width="200" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="360" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="360" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="47" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="47" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="313" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="313" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="70" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="70" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="290" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="290" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="133" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="133" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="133" data-offset-y="0" data-expected-width="134" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="133" data-offset-y="20" data-expected-width="134" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="267" data-offset-y="0" data-expected-width="133" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="267" data-offset-y="20" data-expected-width="133" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="120" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="240" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="240" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="360" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="360" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="30" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="30" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="130" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="130" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="230" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="230" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="330" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="330" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="48" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="48" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="136" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="136" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="224" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="224" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="312" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="312" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalLR" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="200" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="300" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-    </div>
-</div>
-
-<!-- RTL direction. -->
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="360" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="360" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="80" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="80" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="280" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="280" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="107" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="107" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="253" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="253" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="200" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="200" data-offset-y="280" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="200" data-offset-y="260" data-expected-width="200" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="360" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="360" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="47" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="47" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="313" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="313" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="70" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="70" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="290" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="290" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="133" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="133" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="133" data-offset-y="280" data-expected-width="134" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="133" data-offset-y="260" data-expected-width="134" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="267" data-offset-y="280" data-expected-width="133" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="267" data-offset-y="260" data-expected-width="133" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="120" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="240" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="240" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="360" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="360" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="30" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="30" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="130" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="130" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="230" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="230" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="330" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="330" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="48" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="48" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="136" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="136" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="224" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="224" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="312" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="312" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalLR directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="100" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="200" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="200" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="300" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="300" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-rl-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-rl-expected.txt
deleted file mode 100644
index fd5b1a5d..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-rl-expected.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-This test checks that the align-content property is applied correctly when using content-distribution values.
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: LTR | align-content: 'space-between'
-
-PASS
-
-direction: LTR | align-content: 'space-around'
-
-PASS
-
-direction: LTR | align-content: 'space-evenly'
-
-PASS
-
-direction: LTR | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
-
-direction: RTL | align-content: 'space-between'
-
-PASS
-
-direction: RTL | align-content: 'space-around'
-
-PASS
-
-direction: RTL | align-content: 'space-evenly'
-
-PASS
-
-direction: RTL | align-content: 'stretch'
-
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-rl.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-rl.html
deleted file mode 100644
index 7effcf8..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution-vertical-rl.html
+++ /dev/null
@@ -1,342 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0px;
-}
-
-.grid {
-    grid-auto-columns: 20px;
-    grid-auto-rows: 40px;
-    position: relative;
-    width: 400px;
-    height: 300px;
-}
-
-.stretchedGrid {
-    grid-auto-rows: auto;
-}
-
-.thirdRowFirstColumn {
-    background-color: magenta;
-    grid-column: 1;
-    grid-row: 3;
-}
-
-.thirdRowSecondColumn {
-    background-color: navy;
-    grid-column: 2;
-    grid-row: 3;
-}
-
-.fourthRowFirstColumn {
-    background-color: green;
-    grid-column: 1;
-    grid-row: 4;
-}
-
-.fourthRowSecondColumn {
-    background-color: pink;
-    grid-column: 2;
-    grid-row: 4;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the align-content property is applied correctly when using content-distribution values.</p>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="360" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="360" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="280" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="280" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="80" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="80" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="253" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="253" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="107" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="107" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="200" data-offset-y="20" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="200" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="360" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="360" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="313" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="313" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="47" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="47" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="290" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="290" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="70" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="70" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="267" data-offset-y="0" data-expected-width="133" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="267" data-offset-y="20" data-expected-width="133" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="133" data-offset-y="0" data-expected-width="134" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="133" data-offset-y="20" data-expected-width="134" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="133" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="133" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="360" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="360" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="240" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="240" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="120" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="120" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="330" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="330" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="230" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="230" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="130" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="130" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="30" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="30" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="312" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="312" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="224" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="224" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="136" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="136" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="48" data-offset-y="0" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="48" data-offset-y="20" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalRL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="300" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="200" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="100" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="0" data-offset-y="20" data-expected-width="100" data-expected-height="20"></div>
-    </div>
-</div>
-
-<!-- RTL direction. -->
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="360" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="360" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="280" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="280" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="80" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="80" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="253" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="253" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="107" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="107" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="200" data-offset-y="280" data-expected-width="200" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="200" data-offset-y="260" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="200" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="200" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="360" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="360" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="313" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="313" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="47" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="47" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="290" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="290" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="180" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="70" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="70" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="267" data-offset-y="280" data-expected-width="133" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="267" data-offset-y="260" data-expected-width="133" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="133" data-offset-y="280" data-expected-width="134" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="133" data-offset-y="260" data-expected-width="134" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="133" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="133" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="360" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="360" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="240" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="240" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="120" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="120" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="330" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="330" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="230" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="230" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="130" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="130" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="30" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="30" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="312" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="312" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="224" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="224" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="136" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="136" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="48" data-offset-y="280" data-expected-width="40" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="48" data-offset-y="260" data-expected-width="40" data-expected-height="20"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch verticalRL directionRTL" data-expected-width="400" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="300" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="firstRowSecondColumn" data-offset-x="300" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowFirstColumn" data-offset-x="200" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="secondRowSecondColumn" data-offset-x="200" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="100" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="100" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="100" data-expected-height="20"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="0" data-offset-y="260" data-expected-width="100" data-expected-height="20"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution.html
deleted file mode 100644
index 438d4a5..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-distribution.html
+++ /dev/null
@@ -1,342 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0px;
-}
-
-.grid {
-    grid-auto-columns: 20px;
-    grid-auto-rows: 40px;
-    position: relative;
-    width: 200px;
-    height: 300px;
-}
-
-.stretchedGrid {
-    grid-auto-rows: auto;
-}
-
-.thirdRowFirstColumn {
-    background-color: magenta;
-    grid-column: 1;
-    grid-row: 3;
-}
-
-.thirdRowSecondColumn {
-    background-color: navy;
-    grid-column: 2;
-    grid-row: 3;
-}
-
-.fourthRowFirstColumn {
-    background-color: green;
-    grid-column: 1;
-    grid-row: 4;
-}
-
-.fourthRowSecondColumn {
-    background-color: pink;
-    grid-column: 2;
-    grid-row: 4;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the align-content property is applied correctly when using content-distribution values.</p>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="55" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="55" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="205" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="205" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="73" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="73" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="187" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="187" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="150"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="0" data-expected-width="20" data-expected-height="150"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="150" data-expected-width="20" data-expected-height="150"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="150" data-expected-width="20" data-expected-height="150"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="230" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="230" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="45" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="45" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="215" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="215" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="100"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="0" data-expected-width="20" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="100"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="100" data-expected-width="20" data-expected-height="100"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="100"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="200" data-expected-width="20" data-expected-height="100"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="87" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="87" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="173" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="173" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="20" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="18" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="18" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="93" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="93" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="168" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="168" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="243" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="20" data-offset-y="243" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="28" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="28" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="96" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="96" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="164" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="164" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="232" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="20" data-offset-y="232" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="75"></div>
-        <div class="firstRowSecondColumn" data-offset-x="20" data-offset-y="0" data-expected-width="20" data-expected-height="75"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="75" data-expected-width="20" data-expected-height="75"></div>
-        <div class="secondRowSecondColumn" data-offset-x="20" data-offset-y="75" data-expected-width="20" data-expected-height="75"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="0" data-offset-y="150" data-expected-width="20" data-expected-height="75"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="20" data-offset-y="150" data-expected-width="20" data-expected-height="75"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="0" data-offset-y="225" data-expected-width="20" data-expected-height="75"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="20" data-offset-y="225" data-expected-width="20" data-expected-height="75"></div>
-    </div>
-</div>
-
-<!-- RTL direction. -->
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="55" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="55" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="205" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="205" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="73" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="73" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="187" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="187" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="150"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="0" data-expected-width="20" data-expected-height="150"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="150" data-expected-width="20" data-expected-height="150"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="150" data-expected-width="20" data-expected-height="150"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="230" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="230" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="45" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="45" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="215" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="215" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="100"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="0" data-expected-width="20" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="100"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="100" data-expected-width="20" data-expected-height="100"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="200" data-expected-width="20" data-expected-height="100"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="200" data-expected-width="20" data-expected-height="100"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-between'</p>
-    <div class="grid alignContentSpaceBetween directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="87" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="87" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="173" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="173" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="180" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="160" data-offset-y="260" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-around'</p>
-    <div class="grid alignContentSpaceAround directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="18" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="18" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="93" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="93" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="168" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="168" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="180" data-offset-y="243" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="160" data-offset-y="243" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'space-evenly'</p>
-    <div class="grid alignContentSpaceEvenly directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="28" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="28" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="96" data-expected-width="20" data-expected-height="40"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="96" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="164" data-expected-width="20" data-expected-height="40"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="164" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="180" data-offset-y="232" data-expected-width="20" data-expected-height="40"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="160" data-offset-y="232" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'stretch'</p>
-    <div class="grid stretchedGrid alignContentStretch directionRTL" data-expected-width="200" data-expected-height="300">
-        <div class="firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="75"></div>
-        <div class="firstRowSecondColumn" data-offset-x="160" data-offset-y="0" data-expected-width="20" data-expected-height="75"></div>
-        <div class="secondRowFirstColumn" data-offset-x="180" data-offset-y="75" data-expected-width="20" data-expected-height="75"></div>
-        <div class="secondRowSecondColumn" data-offset-x="160" data-offset-y="75" data-expected-width="20" data-expected-height="75"></div>
-        <div class="thirdRowFirstColumn" data-offset-x="180" data-offset-y="150" data-expected-width="20" data-expected-height="75"></div>
-        <div class="thirdRowSecondColumn" data-offset-x="160" data-offset-y="150" data-expected-width="20" data-expected-height="75"></div>
-        <div class="fourthRowFirstColumn" data-offset-x="180" data-offset-y="225" data-expected-width="20" data-expected-height="75"></div>
-        <div class="fourthRowSecondColumn" data-offset-x="160" data-offset-y="225" data-expected-width="20" data-expected-height="75"></div>
-    </div>
-</div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-expected.txt
deleted file mode 100644
index 69de21eb..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content-expected.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-This test checks that the align-content property is applied correctly.
-
-direction: LTR | align-content: 'center'
-
-PASS
-
-direction: LTR | align-content: 'left'
-
-PASS
-
-direction: LTR | align-content: 'right'
-
-PASS
-
-direction: LTR | align-content: 'start'
-
-PASS
-
-direction: LTR | align-content: 'end'
-
-PASS
-
-direction: LTR | align-content: 'flex-start'
-
-PASS
-
-direction: LTR | align-content: 'flex-end
-
-PASS
-
-direction: LTR | align-content: 'auto' (resolved to 'start')
-
-PASS
-
-direction: RTL | align-content: 'center'
-
-PASS
-
-direction: RTL | align-content: 'left'
-
-PASS
-
-direction: RTL | align-content: 'right'
-
-PASS
-
-direction: RTL | align-content: 'start'
-
-PASS
-
-direction: RTL | align-content: 'end'
-
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content.html
deleted file mode 100644
index f697eae9..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-content.html
+++ /dev/null
@@ -1,167 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid: 100px 100px / 50px 50px;
-    position: relative;
-    width: 200px;
-    height: 300px;
-}
-
-.verticalGrid {
-    width: 300px;
-    height: 200px;
-}
-
-.cell {
-    width: 20px;
-    height: 40px;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the align-content property is applied correctly.</p>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'center'</p>
-    <div class="grid alignContentCenter" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="50" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="150" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'left'</p>
-    <div class="grid alignContentLeft" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'right'</p>
-    <div class="grid alignContentRight" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'start'</p>
-    <div class="grid alignContentStart" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'end'</p>
-    <div class="grid alignContentEnd" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'flex-start'</p>
-    <div class="grid alignContentFlexStart" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'flex-end</p>
-    <div class="grid alignContentFlexEnd" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- Default alignment and initial values. -->
-<div style="position: relative">
-    <p>direction: LTR | align-content: 'auto' (resolved to 'start')</p>
-    <div class="grid" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="50" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- RTL direction. -->
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'center'</p>
-    <div class="grid directionRTL alignContentCenter" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="50" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="150" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'left'</p>
-    <div class="grid directionRTL alignContentLeft" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'right'</p>
-    <div class="grid directionRTL alignContentRight" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'start'</p>
-    <div class="grid directionRTL alignContentStart" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <p>direction: RTL | align-content: 'end'</p>
-    <div class="grid directionRTL alignContentEnd" data-expected-width="200" data-expected-height="300">
-        <div class="cell firstRowFirstColumn" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="100" data-expected-width="50" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="150" data-offset-y="200" data-expected-width="50" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="130" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-expected.txt
deleted file mode 100644
index 5ec7e800..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-This test checks that the align-self property is applied correctly.
-
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding-vertical-lr.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding-vertical-lr.html
deleted file mode 100644
index 4b81040c22..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding-vertical-lr.html
+++ /dev/null
@@ -1,236 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid-template-columns: 100px 200px;
-    grid-template-rows: 200px 200px;
-    padding: 10px 15px 20px 30px;
-    border-width: 5px 10px 15px 20px;
-    border-style: dotted;
-    border-color: blue;
-    position: relative;
-}
-
-.cell {
-    width: 20px;
-    height: 40px;
-    margin: 4px 8px 12px 16px;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the 'margin', 'border' and 'padding' properties are applied together correctly for 'align' and 'justify' properties on vertical-LR grids.</p>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'auto' | justify-items: 'auto'</p>
-    <div class="grid fit-content verticalLR" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"   data-offset-x="46"  data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn"  data-offset-x="46"  data-offset-y="114" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowFirstColumn"  data-offset-x="246" data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="246" data-offset-y="114" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'center' | justify-items: 'center'</p>
-    <div class="grid fit-content verticalLR itemsCenter" data-expected-width="475" data-expected-height="350">
-        <div class="firstRowFirstColumn cell"     data-offset-x="124"  data-offset-y="36"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"   data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="324"  data-offset-y="186" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'end' | justify-items: 'end'</p>
-    <div class="grid fit-content verticalLR itemsEnd" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="202" data-offset-y="58" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="402" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'left' | justify-items: 'left'</p>
-    <div class="grid fit-content verticalLR itemsLeft" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="114" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'start' | justify-items: 'right'</p>
-    <div class="grid fit-content verticalLR alignItemsStart justifyItemsRight" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="58" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (ortho) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionLTR verticalLR itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="58" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (ortho) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionLTR verticalLR itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="202" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="402" data-offset-y="114" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (parall) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionLTR verticalLR itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="14" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="114" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (parall) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionLTR verticalLR itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="202" data-offset-y="58"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="402" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- RTL direction. -->
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'auto' | justify-items: 'auto'</p>
-    <div class="grid fit-content verticalLR directionRTL" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"   data-offset-x="46"  data-offset-y="258" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn"  data-offset-x="46"  data-offset-y="158" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowFirstColumn"  data-offset-x="246" data-offset-y="258" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="246" data-offset-y="158" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'center' | justify-items: 'center'</p>
-    <div class="grid fit-content verticalLR directionRTL itemsCenter" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="124" data-offset-y="236" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="324" data-offset-y="86" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'end' | justify-items: 'end'</p>
-    <div class="grid fit-content verticalLR directionRTL itemsEnd"       data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="202" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="402" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'start' | justify-items: 'left'</p>
-    <div class="grid fit-content verticalLR directionRTL alignItemsStart justifyItemsLeft"      data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'start' | justify-items: 'right'</p>
-    <div class="grid fit-content verticalLR directionRTL alignItemsStart justifyItemsRight"     data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (ortho) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content verticalLR directionRTL itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (ortho) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content verticalLR directionRTL itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="202" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="402" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (parall) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content verticalLR directionRTL itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="246" data-offset-y="158"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (parall) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content verticalLR directionRTL itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="202" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="402" data-offset-y="14" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding-vertical-rl.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding-vertical-rl.html
deleted file mode 100644
index d41754fd..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding-vertical-rl.html
+++ /dev/null
@@ -1,237 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid-template-columns: 100px 200px;
-    grid-template-rows: 200px 200px;
-    padding: 10px 15px 20px 30px;
-    border-width: 5px 10px 15px 20px;
-    border-style: dotted;
-    border-color: blue;
-    position: relative;
-}
-
-.cell {
-    width: 20px;
-    height: 40px;
-    margin: 4px 8px 12px 16px;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the 'margin', 'border' and 'padding' properties are applied together correctly for 'align' and 'justify' properties on vertical-RL grids.</p>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'auto' | justify-items: 'auto'</p>
-    <div class="grid fit-content verticalRL" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"   data-offset-x="402" data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn"  data-offset-x="402" data-offset-y="114" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowFirstColumn"  data-offset-x="202" data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="202" data-offset-y="114" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'center' | justify-items: 'center'</p>
-    <div class="grid fit-content verticalRL itemsCenter" data-expected-width="475" data-expected-height="350">
-        <div class="firstRowFirstColumn cell"     data-offset-x="324" data-offset-y="36"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="124" data-offset-y="186" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'end' | justify-items: 'end'</p>
-    <div class="grid fit-content verticalRL itemsEnd" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="58" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'left' | justify-items: 'left'</p>
-    <div class="grid fit-content verticalRL itemsLeft" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="114" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'start' | justify-items: 'right'</p>
-    <div class="grid fit-content verticalRL alignItemsStart justifyItemsRight" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="58" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (ortho) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionLTR verticalRL itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="58" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (ortho) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionLTR verticalRL itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="114" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (parall) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionLTR verticalRL itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="14" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="114" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (parall) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionLTR verticalRL itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="58"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="110" data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-
-<!-- RTL direction. -->
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'auto' | justify-items: 'auto'</p>
-    <div class="grid fit-content verticalRL directionRTL" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"   data-offset-x="402" data-offset-y="258" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn"  data-offset-x="402" data-offset-y="158" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowFirstColumn"  data-offset-x="202" data-offset-y="258" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="202" data-offset-y="158" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'center' | justify-items: 'center'</p>
-    <div class="grid fit-content verticalRL directionRTL itemsCenter" data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="324" data-offset-y="236" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="124" data-offset-y="86" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'end' | justify-items: 'end'</p>
-    <div class="grid fit-content verticalRL directionRTL itemsEnd"       data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'start' | justify-items: 'left'</p>
-    <div class="grid fit-content verticalRL directionRTL alignItemsStart justifyItemsLeft"      data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'start' | justify-items: 'right'</p>
-    <div class="grid fit-content verticalRL directionRTL alignItemsStart justifyItemsRight"     data-expected-width="475" data-expected-height="350">
-        <div class="cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (ortho) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content verticalRL directionRTL itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (ortho) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content verticalRL directionRTL itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (parall) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content verticalRL directionRTL itemsSelfStart" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="402" data-offset-y="258" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="158"  data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (parall) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content verticalRL directionRTL itemsSelfEnd" data-expected-width="475" data-expected-height="350">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="230" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="200" data-expected-height="100"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="14" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding.html
deleted file mode 100644
index f43f0e80..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-margin-border-padding.html
+++ /dev/null
@@ -1,236 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid-template-columns: 100px 200px;
-    grid-template-rows: 200px 200px;
-    padding: 10px 15px 20px 30px;
-    border-width: 5px 10px 15px 20px;
-    border-style: dotted;
-    border-color: blue;
-    position: relative;
-}
-
-.cell {
-    width: 20px;
-    height: 40px;
-    margin: 4px 8px 12px 16px;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the 'margin', 'border' and 'padding' properties are applied together correctly for 'align' and 'justify' properties.</p>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'auto' | justify-items: 'auto'</p>
-    <div class="grid fit-content" data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"   data-offset-x="46"  data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn"  data-offset-x="146" data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowFirstColumn"  data-offset-x="46"  data-offset-y="214" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="146" data-offset-y="214" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'center' | justify-items: 'center'</p>
-    <div class="grid fit-content itemsCenter" data-expected-width="375" data-expected-height="450">
-        <div class="firstRowFirstColumn cell"     data-offset-x="74"  data-offset-y="86" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="224" data-offset-y="286" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'end' | justify-items: 'end'</p>
-    <div class="grid fit-content itemsEnd" data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="102" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="302" data-offset-y="358" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'start' | justify-items: 'left'</p>
-    <div class="grid fit-content alignItemsStart justifyItemsLeft" data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="146" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR | align-items: 'start' | justify-items: 'right'</p>
-    <div class="grid fit-content alignItemsStart justifyItemsRight" data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="102" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="302" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (ortho) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionLTR itemsSelfStart" data-expected-width="375" data-expected-height="450">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="102" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="302" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (ortho) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionLTR itemsSelfEnd" data-expected-width="375" data-expected-height="450">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="46"  data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="146" data-offset-y="358" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR (parall) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionLTR itemsSelfStart" data-expected-width="375" data-expected-height="450">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="46" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="146" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: LTR - (parall) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionLTR itemsSelfEnd" data-expected-width="375" data-expected-height="450">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="102"  data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="130" data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="30"  data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="302" data-offset-y="358" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- RTL direction. -->
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'auto' | justify-items: 'auto'</p>
-    <div class="grid fit-content directionRTL" data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"   data-offset-x="302" data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn"  data-offset-x="202" data-offset-y="14"  data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowFirstColumn"  data-offset-x="302" data-offset-y="214" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell secondRowSecondColumn" data-offset-x="202" data-offset-y="214" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'center' | justify-items: 'center'</p>
-    <div class="grid fit-content directionRTL itemsCenter" data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="274" data-offset-y="86" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="124" data-offset-y="286" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'end' | justify-items: 'end'</p>
-    <div class="grid fit-content directionRTL itemsEnd"       data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="358" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'start' | justify-items: 'left'</p>
-    <div class="grid fit-content directionRTL alignItemsStart justifyItemsLeft"      data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL | align-items: 'start' | justify-items: 'right'</p>
-    <div class="grid fit-content directionRTL alignItemsStart justifytemsRight"     data-expected-width="375" data-expected-height="450">
-        <div class="cell firstRowFirstColumn"     data-offset-x="302" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (ortho) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionRTL itemsSelfStart" data-expected-width="375" data-expected-height="450">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="46"  data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (ortho) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionRTL itemsSelfEnd" data-expected-width="375" data-expected-height="450">
-        <div class="directionLTR cell firstRowFirstColumn"     data-offset-x="302" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionLTR selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionLTR selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionLTR cell secondRowSecondColumn"   data-offset-x="202" data-offset-y="358" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (parall) | align-items: 'self-start' | justify-items: 'self-start'</p>
-    <div class="grid fit-content directionRTL itemsSelfStart" data-expected-width="375" data-expected-height="450">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="302" data-offset-y="14"  data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="202"  data-offset-y="214" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-<div>
-    <p>border: 5px 10px 15px 20px | padding: 10px 15px 20px 30px | margin: 4px 8px 12px 16px<br>
-        direction: RTL (parall) | align-items: 'self-end' | justify-items: 'self-end'</p>
-    <div class="grid fit-content directionRTL itemsSelfEnd" data-expected-width="375" data-expected-height="450">
-        <div class="directionRTL cell firstRowFirstColumn"     data-offset-x="246" data-offset-y="158" data-expected-width="20"  data-expected-height="40"></div>
-        <div class="directionRTL selfStretch firstRowSecondColumn" data-offset-x="30"  data-offset-y="10"  data-expected-width="200" data-expected-height="200"></div>
-        <div class="directionRTL selfStretch secondRowFirstColumn" data-offset-x="230" data-offset-y="210" data-expected-width="100" data-expected-height="200"></div>
-        <div class="directionRTL cell secondRowSecondColumn"   data-offset-x="46" data-offset-y="358" data-expected-width="20"  data-expected-height="40"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-overflow-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-overflow-expected.txt
deleted file mode 100644
index ee761ee..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-overflow-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This test checks that the 'overflow' keyword is applied correctly for 'align' and 'justify' properties.
-
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-overflow.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-overflow.html
deleted file mode 100644
index 53a4c9f2..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-overflow.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid-template-columns: 150px 150px;
-    grid-template-rows: 120px 120px 120px;
-    margin-bottom: 20px;
-}
-
-.cellOverflowWidth {
-    width: 180px;
-    height: 40px;
-}
-
-.cellOverflowHeight {
-    width: 50px;
-    height: 150px;
-}
-
-.cellWithNoOverflow {
-    width: 50px;
-    height: 40px;
-}
-
-.thirdRowFirstColumn {
-    background-color: green;
-    grid-column: 1;
-    grid-row: 3;
-}
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the 'overflow' keyword is applied correctly for 'align' and 'justify' properties.</p>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsCenter justifyItemsCenter" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowWidth  firstRowFirstColumn" data-offset-x="-15" data-offset-y="40" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn" data-offset-x="50" data-offset-y="160" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="50" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn" data-offset-x="200" data-offset-y="40" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowWidth  secondRowSecondColumn" data-offset-x="135" data-offset-y="160" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="200" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsCenterUnsafe justifyItemsCenterUnsafe" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowHeight firstRowFirstColumn" data-offset-x="50" data-offset-y="-15" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn" data-offset-x="50" data-offset-y="160" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="50" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn" data-offset-x="200" data-offset-y="40" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowHeight secondRowSecondColumn" data-offset-x="200" data-offset-y="105" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="200" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsCenterSafe justifyItemsCenterSafe" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowWidth  firstRowFirstColumn" data-offset-x="0" data-offset-y="40" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn" data-offset-x="50" data-offset-y="160" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="50" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn" data-offset-x="200" data-offset-y="40" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowWidth  secondRowSecondColumn" data-offset-x="150" data-offset-y="160" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="200" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsCenterSafe justifyItemsCenterSafe" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowHeight firstRowFirstColumn" data-offset-x="50" data-offset-y="0" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn" data-offset-x="50" data-offset-y="160" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="50" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn" data-offset-x="200" data-offset-y="40" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowHeight secondRowSecondColumn alignSelfCenterSafe justifySelfCenterSafe" data-offset-x="200" data-offset-y="120" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="200" data-offset-y="280" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsEnd justifyItemsEnd" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowWidth  firstRowFirstColumn" data-offset-x="-30" data-offset-y="80" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn justifySelfCenter" data-offset-x="50" data-offset-y="200" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="100" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn" data-offset-x="250" data-offset-y="80" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowWidth  secondRowSecondColumn" data-offset-x="120" data-offset-y="200" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="250" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsEndUnsafe justifyItemsEndUnsafe" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowHeight firstRowFirstColumn" data-offset-x="100" data-offset-y="-30" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn" data-offset-x="100" data-offset-y="200" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="100" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn alignSelfCenter" data-offset-x="250" data-offset-y="40" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowHeight secondRowSecondColumn" data-offset-x="250" data-offset-y="90" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="250" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsEndSafe justifyItemsEndSafe" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowWidth  firstRowFirstColumn" data-offset-x="0" data-offset-y="80" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn justifySelfCenterUnsafe" data-offset-x="50" data-offset-y="200" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="100" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn" data-offset-x="250" data-offset-y="80" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowWidth  secondRowSecondColumn" data-offset-x="150" data-offset-y="200" data-expected-width="180" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="250" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsEndSafe justifyItemsEndSafe" data-expected-width="300" data-expected-height="360">
-        <div class="cellOverflowHeight firstRowFirstColumn" data-offset-x="100" data-offset-y="0" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow secondRowFirstColumn" data-offset-x="100" data-offset-y="200" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow thirdRowFirstColumn" data-offset-x="100" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellWithNoOverflow firstRowSecondColumn alignSelfCenterUnsafe" data-offset-x="250" data-offset-y="40" data-expected-width="50" data-expected-height="40"></div>
-        <div class="cellOverflowHeight secondRowSecondColumn" data-offset-x="250" data-offset-y="120" data-expected-width="50" data-expected-height="150"></div>
-        <div class="cellWithNoOverflow thirdRowSecondColumn" data-offset-x="250" data-offset-y="320" data-expected-width="50" data-expected-height="40"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch-expected.txt
deleted file mode 100644
index 9911dff2..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-This test checks that the 'stretch' value is applied correctly for 'align' and 'justify' properties.
-
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
-PASS
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch-with-orthogonal-flows.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch-with-orthogonal-flows.html
deleted file mode 100644
index 75d58ea..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch-with-orthogonal-flows.html
+++ /dev/null
@@ -1,119 +0,0 @@
-<!DOCTYPE html>
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
-<style>
-body {
-    margin: 0;
-}
-.container {
-    position: relative;
-}
-.grid {
-    grid-template-columns: 100px 100px;
-    grid-template-rows: 150px 150px;
-    font: 10px/1 Ahem;
-}
-.widthAndHeightSet {
-    width: 20px;
-    height: 40px;
-}
-.onlyWidthSet { width: 20px; }
-.onlyHeightSet { height: 40px; }
-.maxHeight { max-height: 160px; }
-.maxWidth { max-width: 90px; }
-.minWidth { min-width: 120px; }
-.minHeight { min-height: 220px; }
-.topAutoMargin { margin-top: auto; }
-.bottomAutoMargin { margin-bottom: auto; }
-.leftAutoMargin { margin-left: auto; }
-.rightAutoMargin { margin-right: auto; }
-</style>
-<body onload="checkLayout('.grid')">
-<div id="log"></div>
-<p>This test checks that stretching alignment works as expected with orthogonal flows.</p>
-
-<p>HORIZONTAL vs VERTICAL-RL</p>
-<p><b>row1/col1:</b> fixed width and height - <b>row1/col2:</b> fixed width and auto height - <b>row2/col1:</b> auto width and fixed height - <b>row2/col2:</b> auto width and height, but start.</p>
-<div class="container">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="300">
-        <div class="verticalRL firstRowFirstColumn   selfStretch   widthAndHeightSet " data-expected-width="20"  data-expected-height="40">XXX</div>
-        <div class="verticalRL firstRowSecondColumn  sefStretch    onlyWidthSet      " data-expected-width="20"  data-expected-height="150">XXX</div>
-        <div class="verticalRL secondRowFirstColumn  selfStretch    onlyHeightSet     " data-expected-width="100" data-expected-height="40">XXX</div>
-        <div class="verticalRL secondRowSecondColumn selfSelfStart                   " data-expected-width="10"  data-expected-height="30">XXX</div>
-    </div>
-</div>
-<p><b>row1/co1l:</b> bottom auto margin - <b>row1/col2:</b> left auto margin - <b>row2/col1:</b> top auto margin - <b>row2/col2:</b> right auto margin.</p>
-<div class="container">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="300">
-        <div class="verticalRL firstRowFirstColumn   selfStretch bottomAutoMargin " data-expected-width="100" data-expected-height="30">XXX</div>
-        <div class="verticalRL firstRowSecondColumn  seffStretch leftAutoMargin   " data-expected-width="10"  data-expected-height="150">XXX</div>
-        <div class="verticalRL secondRowFirstColumn  selffStretch topAutoMargin    " data-expected-width="100" data-expected-height="30">XXX</div>
-        <div class="verticalRL secondRowSecondColumn selffStretch rightAutoMargin  " data-expected-width="10"  data-expected-height="150">XXX</div>
-    </div>
-</div>
-
-<p>HORIZONTAL vs VERTICAL-LR</p>
-<p><b>row1/col1:</b> fixed width and height - <b>row1/col2:</b> fixed width and auto height - <b>row2/col1:</b> auto width and fixed height - <b>row2/col2:</b> auto width and height, but start.</p>
-<div class="container">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="300">
-        <div class="verticalLR firstRowFirstColumn   selfStretch   widthAndHeightSet " data-expected-width="20"  data-expected-height="40">XXX</div>
-        <div class="verticalLR firstRowSecondColumn  sefStretch    onlyWidthSet      " data-expected-width="20"  data-expected-height="150">XXX</div>
-        <div class="verticalLR secondRowFirstColumn  selfStretch    onlyHeightSet     " data-expected-width="100" data-expected-height="40">XXX</div>
-        <div class="verticalLR secondRowSecondColumn selfSelfStart                   " data-expected-width="10"  data-expected-height="30">XXX</div>
-    </div>
-</div>
-<p><b>row1/co1l:</b> bottom auto margin - <b>row1/col2:</b> left auto margin - <b>row2/col1:</b> top auto margin - <b>row2/col2:</b> right auto margin.</p>
-<div class="container">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="300">
-        <div class="verticalLR firstRowFirstColumn   selfStretch bottomAutoMargin " data-expected-width="100" data-expected-height="30">XXX</div>
-        <div class="verticalLR firstRowSecondColumn  seffStretch leftAutoMargin   " data-expected-width="10"  data-expected-height="150">XXX</div>
-        <div class="verticalLR secondRowFirstColumn  selffStretch topAutoMargin    " data-expected-width="100" data-expected-height="30">XXX</div>
-        <div class="verticalLR secondRowSecondColumn selffStretch rightAutoMargin  " data-expected-width="10"  data-expected-height="150">XXX</div>
-    </div>
-</div>
-
-<p>VERTICAL-RL vs HORIZONTAL</p>
-<p><b>row1/col1:</b> fixed width and height - <b>row1/col2:</b> fixed width and auto height - <b>row2/col1:</b> auto width and fixed height - <b>row2/col2:</b> auto width and height, but start.</p>
-<div class="container">
-    <div class="grid fit-content verticalRL" data-expected-width="300" data-expected-height="200">
-        <div class="horizonalTB firstRowFirstColumn   selfStretch   widthAndHeightSet " data-expected-width="20"  data-expected-height="40">XXX</div>
-        <div class="horizonalTB firstRowSecondColumn  sefStretch    onlyWidthSet      " data-expected-width="20"  data-expected-height="100">XXX</div>
-        <div class="horizonalTB secondRowFirstColumn  selfStretch    onlyHeightSet     " data-expected-width="150" data-expected-height="40">XXX</div>
-        <div class="horizonalTB secondRowSecondColumn selfSelfStart                   " data-expected-width="10"  data-expected-height="30">XXX</div>
-    </div>
-</div>
-<p><b>row1/co1l:</b> bottom auto margin - <b>row1/col2:</b> left auto margin - <b>row2/col1:</b> top auto margin - <b>row2/col2:</b> right auto margin.</p>
-<div class="container">
-    <div class="grid fit-content verticalRL" data-expected-width="300" data-expected-height="200">
-        <div class="horizonalTB firstRowFirstColumn   selfStretch bottomAutoMargin " data-expected-width="150" data-expected-height="30">XXX</div>
-        <div class="horizonalTB firstRowSecondColumn  seffStretch leftAutoMargin   " data-expected-width="10"  data-expected-height="100">XXX</div>
-        <div class="horizonalTB secondRowFirstColumn  selffStretch topAutoMargin    " data-expected-width="150" data-expected-height="30">XXX</div>
-        <div class="horizonalTB secondRowSecondColumn selffStretch rightAutoMargin  " data-expected-width="10"  data-expected-height="100">XXX</div>
-    </div>
-</div>
-
-<p>VERTICAL-LR vs HORIZONTAL</p>
-<p><b>row1/col1:</b> fixed width and height - <b>row1/col2:</b> fixed width and auto height - <b>row2/col1:</b> auto width and fixed height - <b>row2/col2:</b> auto width and height, but start.</p>
-<div class="container">
-    <div class="grid fit-content verticalLR" data-expected-width="300" data-expected-height="200">
-        <div class="horizonalTB firstRowFirstColumn   selfStretch   widthAndHeightSet " data-expected-width="20"  data-expected-height="40">XXX</div>
-        <div class="horizonalTB firstRowSecondColumn  sefStretch    onlyWidthSet      " data-expected-width="20"  data-expected-height="100">XXX</div>
-        <div class="horizonalTB secondRowFirstColumn  selfStretch    onlyHeightSet     " data-expected-width="150" data-expected-height="40">XXX</div>
-        <div class="horizonalTB secondRowSecondColumn selfSelfStart                   " data-expected-width="10"  data-expected-height="30">XXX</div>
-    </div>
-</div>
-<p><b>row1/co1l:</b> bottom auto margin - <b>row1/col2:</b> left auto margin - <b>row2/col1:</b> top auto margin - <b>row2/col2:</b> right auto margin.</p>
-<div class="container">
-    <div class="grid fit-content verticalLR" data-expected-width="300" data-expected-height="200">
-        <div class="horizonalTB firstRowFirstColumn   selfStretch bottomAutoMargin " data-expected-width="150" data-expected-height="30">XXX</div>
-        <div class="horizonalTB firstRowSecondColumn  seffStretch leftAutoMargin   " data-expected-width="10"  data-expected-height="100">XXX</div>
-        <div class="horizonalTB secondRowFirstColumn  selffStretch topAutoMargin    " data-expected-width="150" data-expected-height="30">XXX</div>
-        <div class="horizonalTB secondRowSecondColumn selffStretch rightAutoMargin  " data-expected-width="10"  data-expected-height="100">XXX</div>
-    </div>
-</div>
-
-</body>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch.html
deleted file mode 100644
index 3a1d6613..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align-justify-stretch.html
+++ /dev/null
@@ -1,184 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid-template-columns: 100px 100px;
-    grid-template-rows: 200px 200px;
-    margin-bottom: 20px;
-}
-
-.widthAndHeightSet {
-    width: 20px;
-    height: 40px;
-}
-.onlyWidthSet { width: 20px; }
-.onlyHeightSet { height: 40px; }
-.maxHeight { max-height: 160px; }
-.maxWidth { max-width: 90px; }
-.minWidth { min-width: 120px; }
-.minHeight { min-height: 220px; }
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the 'stretch' value is applied correctly for 'align' and 'justify' properties.</p>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="alignSelfStretch justifySelfStart firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="0" data-expected-height="200"></div>
-        <div class="widthAndHeightSet alignSelfStretch justifySelfStart firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet alignSelfStretch justifySelfStart secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet alignSelfStretch justifySelfStart secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="0" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="alignSelfStart justifySelfStretch firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="0"></div>
-        <div class="widthAndHeightSet alignSelfStart justifySelfStretch firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet alignSelfStart justifySelfStretch secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="0"></div>
-        <div class="onlyHeightSet alignSelfStart justifySelfStretch secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="maxHeight alignSelfStretch justifySelfStart firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="0" data-expected-height="160"></div>
-        <div class="minWidth widthAndHeightSet alignSelfStretch justifySelfStart firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="120" data-expected-height="40"></div>
-        <div class="minHeight onlyWidthSet alignSelfStretch justifySelfStart secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="220"></div>
-        <div class="maxWidth onlyHeightSet alignSelfStretch justifySelfStretch secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="90" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="alignSelfStretch justifySelfStretch firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="widthAndHeightSet alignSelfStretch justifySelfStretch firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet alignSelfStretch justifySelfStretch secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet alignSelfStretch justifySelfStretch secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsStretch justifyItemsStart" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="0" data-expected-height="200"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="0" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsStart justifyItemsStretch" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="0"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="0"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsStretch justifyItemsStretch" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content alignItemsAuto justifyItemsAuto" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="100" data-expected-height="200"></div>
-        <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="200"></div>
-    </div>
-</div>
-
-<!-- RTL direction (it should not affect the block-flow direction). -->
-<div style="position: relative">
-    <div class="grid fit-content directionRTL alignItemsStretch justifyItemsStretch" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="80" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="180" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="0" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- RTL direction (it should not affect the block-flow) with opposite directions grid container vs grid item. -->
-<div style="position: relative">
-    <div class="grid fit-content alignItemsStretch justifyItemsStretch" data-expected-width="200" data-expected-height="400">
-        <div class="firstRowFirstColumn  directionRTL" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn  directionRTL" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn  directionRTL" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="200"></div>
-        <div class="onlyHeightSet secondRowSecondColumn  directionRTL" data-offset-x="100" data-offset-y="200" data-expected-width="100" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- Vertical RL writing mode. -->
-<div style="position: relative">
-    <div class="grid fit-content verticalRL alignItemsStretch justifyItemsStretch" data-expected-width="400" data-expected-height="200">
-        <div class="firstRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="380" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="100"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="200" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content verticalRL" data-expected-width="400" data-expected-height="200">
-        <div class="firstRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="firstRowSecondColumn" data-offset-x="200" data-offset-y="100" data-expected-width="200" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="secondRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="200" data-expected-height="100"></div>
-    </div>
-</div>
-
-<!-- Vertical LR writing mode. -->
-<div style="position: relative">
-    <div class="grid fit-content verticalLR alignItemsStretch justifyItemsStretch" data-expected-width="400" data-expected-height="200">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="widthAndHeightSet firstRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="onlyWidthSet secondRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="20" data-expected-height="100"></div>
-        <div class="onlyHeightSet secondRowSecondColumn" data-offset-x="200" data-offset-y="100" data-expected-width="200" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content verticalLR" data-expected-width="400" data-expected-height="200">
-        <div class="firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="firstRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="200" data-expected-height="100"></div>
-        <div class="secondRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="secondRowSecondColumn" data-offset-x="200" data-offset-y="100" data-expected-width="200" data-expected-height="100"></div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-align.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-align.html
deleted file mode 100644
index b628063..0000000
--- a/third_party/blink/web_tests/fast/css-grid-layout/grid-align.html
+++ /dev/null
@@ -1,240 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet">
-<link href="resources/grid.css" rel="stylesheet">
-<link href="resources/grid-alignment.css" rel="stylesheet">
-<script src="../../resources/check-layout.js"></script>
-<style>
-body {
-    margin: 0;
-}
-
-.grid {
-    grid-template-columns: 100px 100px;
-    grid-template-rows: 200px 200px;
-    margin-bottom: 20px;
-}
-
-.cell {
-    width: 20px;
-    height: 40px;
-}
-
-.item {
-    width: 8px;
-    height: 16px;
-    background: black;
-}
-
-</style>
-</head>
-<body onload="checkLayout('.grid')">
-
-<p>This test checks that the align-self property is applied correctly.</p>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="alignSelfStretch firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell alignSelfStart firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfEnd firstRowSecondColumn" data-offset-x="100" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfCenter secondRowFirstColumn" data-offset-x="0" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfRight secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfLeft secondRowSecondColumn" data-offset-x="100" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="cell alignSelfFlexEnd firstRowFirstColumn" data-offset-x="0" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfFlexStart firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfStart secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfEnd secondRowSecondColumn" data-offset-x="100" data-offset-y="360" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- Default alignment and initial values. -->
-<div style="position: relative">
-    <div class="grid fit-content alignItemsCenter" data-expected-width="200" data-expected-height="400">
-        <div class="cell alignSelfAuto firstRowFirstColumn" data-offset-x="0" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell firstRowSecondColumn" data-offset-x="100" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfStart secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfEnd secondRowSecondColumn" data-offset-x="100" data-offset-y="360" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-        <div class="alignSelfAuto firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-        <div class="cell firstRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfStart secondRowFirstColumn" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfEnd secondRowSecondColumn" data-offset-x="100" data-offset-y="360" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- RTL direction (it should not affect the block-flow direction). -->
-<div style="position: relative">
-     <div class="grid fit-content directionRTL" data-expected-width="200" data-expected-height="400">
-         <div class="alignSelfStretch firstRowFirstColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-         <div class="cell alignSelfStart firstRowSecondColumn" data-offset-x="80" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfEnd firstRowSecondColumn" data-offset-x="80" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfCenter secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfRight secondRowSecondColumn" data-offset-x="80" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfLeft secondRowSecondColumn" data-offset-x="80" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-     </div>
-</div>
-
-<div style="position: relative">
-     <div class="grid fit-content directionRTL" data-expected-width="200" data-expected-height="400">
-         <div class="cell alignSelfFlexEnd firstRowFirstColumn" data-offset-x="180" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfFlexStart firstRowSecondColumn" data-offset-x="80" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfSelfStart secondRowFirstColumn" data-offset-x="180" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfSelfEnd secondRowSecondColumn" data-offset-x="80" data-offset-y="360" data-expected-width="20" data-expected-height="40"></div>
-     </div>
-</div>
-
-<!-- RTL direction (it should not affect the block-flow) with opposite directions grid container vs grid item. -->
-<div style="position: relative">
-     <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-         <div class="alignSelfStretch firstRowFirstColumn directionRTL" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="200"></div>
-         <div class="cell alignSelfStart firstRowSecondColumn directionRTL" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfEnd firstRowSecondColumn directionRTL" data-offset-x="100" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfCenter secondRowFirstColumn directionRTL" data-offset-x="0" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfRight secondRowSecondColumn directionRTL" data-offset-x="100" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfLeft secondRowSecondColumn directionRTL" data-offset-x="100" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-     </div>
-</div>
-
-<div style="position: relative">
-     <div class="grid fit-content" data-expected-width="200" data-expected-height="400">
-         <div class="cell alignSelfFlexEnd firstRowFirstColumn directionRTL" data-offset-x="0" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfFlexStart firstRowSecondColumn directionRTL" data-offset-x="100" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfSelfStart secondRowFirstColumn directionRTL" data-offset-x="0" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
-         <div class="cell alignSelfSelfEnd secondRowSecondColumn directionRTL" data-offset-x="100" data-offset-y="360" data-expected-width="20" data-expected-height="40"></div>
-     </div>
-</div>
-
-<!-- Vertical RL writing mode. -->
-<div style="position: relative">
-    <div class="grid fit-content verticalRL" data-expected-width="400" data-expected-height="200">
-        <div class="alignSelfStretch firstRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell alignSelfStart firstRowSecondColumn" data-offset-x="380" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfEnd firstRowSecondColumn" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfCenter secondRowFirstColumn" data-offset-x="90" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfRight secondRowSecondColumn" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfLeft secondRowSecondColumn" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content verticalRL" data-expected-width="400" data-expected-height="200">
-        <div class="cell alignSelfFlexEnd firstRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfFlexStart firstRowSecondColumn" data-offset-x="380" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfStart secondRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfEnd secondRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- Vertical LR writing mode. -->
-<div style="position: relative">
-    <div class="grid fit-content verticalLR" data-expected-width="400" data-expected-height="200">
-        <div class="alignSelfStretch firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
-        <div class="cell alignSelfStart firstRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfEnd firstRowSecondColumn" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfCenter secondRowFirstColumn" data-offset-x="290" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfRight secondRowSecondColumn" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfLeft secondRowSecondColumn" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content verticalLR" data-expected-width="400" data-expected-height="200">
-        <div class="cell alignSelfFlexEnd firstRowFirstColumn" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfFlexStart firstRowSecondColumn" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfStart secondRowFirstColumn" data-offset-x="200" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
-        <div class="cell alignSelfSelfEnd secondRowSecondColumn" data-offset-x="380" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
-    </div>
-</div>
-
-<!-- Vertical RL writing mode with opposite block-flow directions grid container vs grid item. -->
-<div style="position: relative">
-    <div class="grid fit-content verticalRL" data-expected-width="400" data-expected-height="200">
-        <div class="alignSelfStretch firstRowFirstColumn verticalLR" data-offset-x="200" data-offset-y="0" data-expected-width="200" data-expected-height="100">
-        </div>
-        <div class="cell alignSelfStart firstRowSecondColumn verticalLR" data-offset-x="380" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfEnd firstRowSecondColumn verticalLR" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfCenter secondRowFirstColumn verticalLR" data-offset-x="90" data-offset-y="0" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfRight secondRowSecondColumn verticalLR" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfLeft secondRowSecondColumn verticalLR" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content verticalRL" data-expected-width="400" data-expected-height="200">
-        <div class="cell alignSelfFlexEnd firstRowFirstColumn verticalLR" data-offset-x="200" data-offset-y="0" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfFlexStart firstRowSecondColumn verticalLR" data-offset-x="380" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfSelfStart secondRowFirstColumn verticalLR" data-offset-x="0" data-offset-y="0" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfSelfEnd secondRowSecondColumn verticalLR" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-    </div>
-</div>
-
-<!-- Vertical LR writing mode with opposite block-flow directions grid container vs grid item. -->
-<div style="position: relative">
-    <div class="grid fit-content verticalLR" data-expected-width="400" data-expected-height="200">
-        <div class="alignSelfStretch firstRowFirstColumn verticalRL" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="100">
-        </div>
-        <div class="cell alignSelfStart firstRowSecondColumn verticalRL" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfEnd firstRowSecondColumn verticalRL" data-offset-x="180" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfCenter secondRowFirstColumn verticalRL" data-offset-x="290" data-offset-y="0" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfRight secondRowSecondColumn verticalRL" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfLeft secondRowSecondColumn verticalRL" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-    </div>
-</div>
-
-<div style="position: relative">
-    <div class="grid fit-content verticalLR" data-expected-width="400" data-expected-height="200">
-        <div class="cell alignSelfFlexEnd firstRowFirstColumn verticalRL" data-offset-x="180" data-offset-y="0" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfFlexStart firstRowSecondColumn verticalRL" data-offset-x="0" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfSelfStart secondRowFirstColumn verticalRL" data-offset-x="380" data-offset-y="0" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-        <div class="cell alignSelfSelfEnd secondRowSecondColumn verticalRL" data-offset-x="200" data-offset-y="100" data-expected-width="20" data-expected-height="40">
-            <div class="item"></div>
-        </div>
-    </div>
-</div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/unit/parse-filter-query-expected.txt b/third_party/blink/web_tests/http/tests/devtools/unit/parse-filter-query-expected.txt
deleted file mode 100644
index 38d79a5..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/unit/parse-filter-query-expected.txt
+++ /dev/null
@@ -1,115 +0,0 @@
-This tests a utility's ability to parse filter queries.
-
-Query: text
-{"text":"text","negative":false}
-
-Query: text with spaces
-{"text":"text","negative":false}
-{"text":"with","negative":false}
-{"text":"spaces","negative":false}
-
-Query: -
-{"text":"-","negative":false}
-
-Query: -text
-{"text":"text","negative":true}
-
-Query: //
-{"text":"//","negative":false}
-
-Query: /regex/
-{"regex":"regex","negative":false}
-
-Query: /regex/ /another/
-{"regex":"regex","negative":false}
-{"regex":"another","negative":false}
-
-Query: /complex/regex/
-{"regex":"complex\\/regex","negative":false}
-
-Query: /regex/ text
-{"regex":"regex","negative":false}
-{"text":"text","negative":false}
-
-Query: key1:foo
-{"key":"key1","text":"foo","negative":false}
-
-Query: -key1:foo
-{"key":"key1","text":"foo","negative":true}
-
-Query: key1:foo key2:bar
-{"key":"key1","text":"foo","negative":false}
-{"key":"key2","text":"bar","negative":false}
-
-Query: -key1:foo key2:bar
-{"key":"key1","text":"foo","negative":true}
-{"key":"key2","text":"bar","negative":false}
-
-Query: key1:foo -key2:bar
-{"key":"key1","text":"foo","negative":false}
-{"key":"key2","text":"bar","negative":true}
-
-Query: -key1:foo -key2:bar
-{"key":"key1","text":"foo","negative":true}
-{"key":"key2","text":"bar","negative":true}
-
-Query: key1:/regex/
-{"key":"key1","text":"/regex/","negative":false}
-
-Query: key1:foo innerText key2:bar
-{"key":"key1","text":"foo","negative":false}
-{"text":"innerText","negative":false}
-{"key":"key2","text":"bar","negative":false}
-
-Query: bar key1 foo
-{"text":"bar","negative":false}
-{"text":"key1","negative":false}
-{"text":"foo","negative":false}
-
-Query: bar key1:foo
-{"text":"bar","negative":false}
-{"key":"key1","text":"foo","negative":false}
-
-Query: bar key1:foo baz
-{"text":"bar","negative":false}
-{"key":"key1","text":"foo","negative":false}
-{"text":"baz","negative":false}
-
-Query: bar key1:foo yek:roo baz
-{"text":"bar","negative":false}
-{"key":"key1","text":"foo","negative":false}
-{"text":"yek:roo","negative":false}
-{"text":"baz","negative":false}
-
-Query: bar key1:foo -yek:roo baz
-{"text":"bar","negative":false}
-{"key":"key1","text":"foo","negative":false}
-{"text":"yek:roo","negative":true}
-{"text":"baz","negative":false}
-
-Query: bar baz key1:foo goo zoo
-{"text":"bar","negative":false}
-{"text":"baz","negative":false}
-{"key":"key1","text":"foo","negative":false}
-{"text":"goo","negative":false}
-{"text":"zoo","negative":false}
-
-Query: bar key1:key1:foo
-{"text":"bar","negative":false}
-{"key":"key1","text":"key1:foo","negative":false}
-
-Query: bar :key1:foo baz
-{"text":"bar","negative":false}
-{"text":":key1:foo","negative":false}
-{"text":"baz","negative":false}
-
-Query: bar -:key1:foo baz
-{"text":"bar","negative":false}
-{"text":"-:key1:foo","negative":false}
-{"text":"baz","negative":false}
-
-Query: bar key1:-foo baz
-{"text":"bar","negative":false}
-{"key":"key1","text":"-foo","negative":false}
-{"text":"baz","negative":false}
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/unit/parse-filter-query.js b/third_party/blink/web_tests/http/tests/devtools/unit/parse-filter-query.js
deleted file mode 100644
index 9497050..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/unit/parse-filter-query.js
+++ /dev/null
@@ -1,46 +0,0 @@
-(async function () {
-    TestRunner.addResult("This tests a utility's ability to parse filter queries.");
-
-    var keys = ["key1", "key2"];
-    var queries = [
-        "text",
-        "text with spaces",
-        "-",
-        "-text",
-        "//",
-        "/regex/",
-        "/regex/ /another/",
-        "/complex\/regex/",
-        "/regex/ text",
-        "key1:foo",
-        "-key1:foo",
-        "key1:foo key2:bar",
-        "-key1:foo key2:bar",
-        "key1:foo -key2:bar",
-        "-key1:foo -key2:bar",
-        "key1:/regex/",
-        "key1:foo innerText key2:bar",
-        "bar key1 foo",
-        "bar key1:foo",
-        "bar key1:foo baz",
-        "bar key1:foo yek:roo baz",
-        "bar key1:foo -yek:roo baz",
-        "bar baz key1:foo goo zoo",
-        "bar key1:key1:foo",
-        "bar :key1:foo baz",
-        "bar -:key1:foo baz",
-        "bar key1:-foo baz",
-    ];
-
-    var parser = new TextUtils.FilterParser(keys);
-    for (var query of queries) {
-        var result = parser.parse(query);
-        TestRunner.addResult("\nQuery: " + query);
-        for (var descriptor of result) {
-            if (descriptor.regex)
-                descriptor.regex = descriptor.regex.source;
-            TestRunner.addResult(JSON.stringify(descriptor));
-        }
-    }
-    TestRunner.completeTest();
-})();
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html b/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html
index 9c64e1f..ee744e8 100644
--- a/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html
+++ b/third_party/blink/web_tests/http/tests/push_messaging/subscribe-success-in-document.html
@@ -18,10 +18,13 @@
             swRegistration = serviceWorkerRegistration;
             return wait_for_state(test, swRegistration.installing, 'activated');
         })
-        .then(function() {
+        .then(async function() {
             // If running manually, grant permission when prompted.
-            if (window.testRunner)
-                testRunner.setPermission('push-messaging', 'granted', location.origin, location.origin);
+            if (window.internals) {
+                await window.internals.setPermission(
+                    {name: 'push', userVisibleOnly: true}, 'granted',
+                    location.origin, location.origin);
+            }
             return swRegistration.pushManager.subscribe({ userVisibleOnly: true });
         })
         .then(function(pushSubscription) {
diff --git a/third_party/blink/web_tests/http/tests/resources/permissions-helper.js b/third_party/blink/web_tests/http/tests/resources/permissions-helper.js
index 7e513aa..5ffc949 100644
--- a/third_party/blink/web_tests/http/tests/resources/permissions-helper.js
+++ b/third_party/blink/web_tests/http/tests/resources/permissions-helper.js
@@ -1,5 +1,5 @@
 // This file provides a PermissionsHelper object which can be used by
-// LayoutTests using testRunner to handle permissions. The methods in the object
+// LayoutTests to handle permissions. The methods in the object
 // return promises so can be used to write idiomatic, race-free code.
 //
 // The current available methods are:
@@ -46,21 +46,7 @@
 
   return {
     setPermission: function(name, state) {
-      return new Promise(function(resolver, reject) {
-        navigator.permissions.query(nameToObject(name)).then(function(result) {
-            if (result.state == state) {
-                resolver()
-                return;
-            }
-
-            result.onchange = function() {
-                result.onchange = null;
-                resolver();
-            };
-
-            testRunner.setPermission(name, state, location.origin, location.origin);
-        });
-      });
+      return internals.setPermission(nameToObject(name), state, location.origin, location.origin);
     }
   }
 })();
diff --git a/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals-expected.txt b/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals-expected.txt
new file mode 100644
index 0000000..b0532440
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals-expected.txt
@@ -0,0 +1,10 @@
+ALERT: Yay!
+CONFIRM: Question?
+PROMPT: Question?, default text: 
+This is a testharness.js-based test.
+PASS alert() is shown.
+PASS print() does get called.
+PASS confirm() returns 'true' (in our test environment).
+PASS prompt() returns a result.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals.php b/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals.php
index 292e1579..a456191 100644
--- a/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals.php
+++ b/third_party/blink/web_tests/http/tests/security/sandbox-iframe-allows-modals.php
@@ -6,28 +6,34 @@
 <head>
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
+    <script>
+      // testharnessreport.js disables reporting js dialogs so turn it back on so that we can
+      // detect they were shown via the -expected.txt output.
+      if (testRunner)
+        testRunner.setDumpJavaScriptDialogs(true);
+    </script>
 </head>
 <body>
     <script>
         test(function () {
             var result = alert("Yay!");
             assert_equals(result, undefined);
-        }, "alert() returns synchronously in a sandboxed page without blocking on user input.");
+        }, "alert() is shown.");
 
         test(function () {
             var result = print();
             assert_equals(result, undefined);
-        }, "print() returns synchronously in a sandboxed page without blocking on user input.");
+        }, "print() does get called.");
 
         test(function () {
             var result = confirm("Question?");
             assert_equals(result, true);
-        }, "confirm() returns 'true' in a sandboxed page (in our test environment).");
+        }, "confirm() returns 'true' (in our test environment).");
 
         test(function () {
             var result = prompt("Question?");
             assert_equals(result, null);
-        }, "prompt() returns 'null' synchronously in a sandboxed page without blocking on user input.");
+        }, "prompt() returns a result.");
     </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html b/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html
index 73986d7..6b47191 100644
--- a/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html
+++ b/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html
@@ -6,9 +6,10 @@
 <script>
 'use strict';
 
-self.testRunner.setPermission('wake-lock-screen', 'granted', location.origin, location.origin);
+promise_test(async t => {
+  await internals.setPermission({name: 'wake-lock', type: 'screen'}, 'granted',
+                                location.origin, location.origin);
 
-promise_test(t => {
   window.testRunner.setPageVisibility('hidden');
   assert_true(document.hidden);
   return promise_rejects(t, "NotAllowedError", navigator.wakeLock.request('screen'));
@@ -21,7 +22,10 @@
 // A more interoperable test would allow both |screenLock| to reject with
 // NotAllowedError as well as it resolving to a WakeLockSentinel that would fire
 // a "release" event upon page vsibility change.
-promise_test(t => {
+promise_test(async t => {
+  await internals.setPermission({name: 'wake-lock', type: 'screen'}, 'granted',
+                                location.origin, location.origin);
+
   window.testRunner.setPageVisibility('visible');
 
   const screenLock = navigator.wakeLock.request('screen');
@@ -31,6 +35,9 @@
 }, "navigator.wakeLock.request('screen') aborts when the page is hidden");
 
 promise_test(async t => {
+  await internals.setPermission({name: 'wake-lock', type: 'screen'}, 'granted',
+                                location.origin, location.origin);
+
   window.testRunner.setPageVisibility('visible');
 
   const screenLock1 = await navigator.wakeLock.request('screen');
diff --git a/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html b/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html
index 2819e5ca..ff22918 100644
--- a/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html
+++ b/third_party/blink/web_tests/wake-lock/wakelock-request-denied.html
@@ -6,8 +6,9 @@
 <script>
 'use strict';
 
-promise_test(t => {
-  self.testRunner.setPermission('wake-lock-screen', 'denied', location.origin, location.origin);
+promise_test(async t => {
+  await internals.setPermission({name: 'wake-lock', type: 'screen'}, 'denied',
+                                location.origin, location.origin);
   return promise_rejects(t, "NotAllowedError", navigator.wakeLock.request('screen'));
 }, 'Denied requests should abort with NotAllowedError');
 </script>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index a488a22..4f47883 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -11112,6 +11112,10 @@
     attribute @@toStringTag
     getter boundsGeometry
     method constructor
+interface XRDOMOverlayState
+    attribute @@toStringTag
+    getter type
+    method constructor
 interface XRFrame
     attribute @@toStringTag
     getter session
@@ -11223,6 +11227,7 @@
     method constructor
 interface XRSession : EventTarget
     attribute @@toStringTag
+    getter domOverlayState
     getter environmentBlendMode
     getter inputSources
     getter onend
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar_dom_overlay.https.html b/third_party/blink/web_tests/wpt_internal/webxr/ar_dom_overlay.https.html
index 05f7e651..b4bced7 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/ar_dom_overlay.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar_dom_overlay.https.html
@@ -5,34 +5,103 @@
 <script src="/webxr/resources/webxr_util.js"></script>
 <script src="/webxr/resources/webxr_test_constants.js"></script>
 <script src="/webxr/resources/webxr_test_asserts.js"></script>
-<canvas />
+
+<style type="text/css">
+  div {
+      padding: 10px;
+      min-width: 10px;
+      min-height: 10px;
+  }
+</style>
+<div id="div_overlay">
+  <canvas />
+</div>
+<div id="div_other">
+  <p>test text</p>
+</div>
 
 <script>
 // Because AR is not yet in the core webxr spec, this is an internal-chrome only test.
-let testName = "Ensures DOM Overlay feature works for immersive-ar";
 
 let fakeDeviceInitParams = { supportedModes: ["immersive-ar"],
                              views: VALID_VIEWS,
+                             viewerOrigin: IDENTITY_TRANSFORM,
                              supportedFeatures: ALL_FEATURES.concat([
                                  'dom-overlay-for-handheld-ar'])};
 
-let testFunction = function(session, fakeDeviceController, t) {
+let watcherDone = new Event("watcherdone");
+
+let testFunction = function(overlayElement, session, fakeDeviceController, t) {
+  console.log('session start');
   assert_equals(session.mode, 'immersive-ar');
   assert_not_equals(session.environmentBlendMode, 'opaque');
 
-  // The <body> element should have a transparent background.
-  assert_equals(window.getComputedStyle(document.body).backgroundColor,
+  assert_true(overlayElement != null);
+  assert_true(overlayElement instanceof Element);
+
+  assert_equals(session.domOverlayState.type, "screen");
+
+  // Verify SameObject property for domOverlayState
+  assert_true(session.domOverlayState === session.domOverlayState);
+
+  // add: "select", "no_event",
+  let eventWatcher = new EventWatcher(
+    t, session, ["select", "watcherdone"]);
+  let eventPromise = eventWatcher.wait_for(
+    ["select", "watcherdone"]);
+
+  session.addEventListener('select', (ev) => {
+    console.log(ev.type, ev);
+  });
+
+  // The overlay element should have a transparent background.
+  assert_equals(window.getComputedStyle(overlayElement).backgroundColor,
                 'rgba(0, 0, 0, 0)');
 
-  // Try fullscreening an element.
-  let elem = document.querySelector('canvas');
-  return elem.requestFullscreen().then(() => {
-      assert_equals(document.fullscreenElement, elem);
+  // Try fullscreening a different element, this should fail.
+  let elem = document.getElementById('div_other');
+  assert_true(elem != null);
+  assert_not_equals(elem, overlayElement);
+
+  let input_source =
+      fakeDeviceController.simulateInputSourceConnection(SCREEN_CONTROLLER);
+  session.requestReferenceSpace('viewer').then(function(viewerSpace) {
+    // Press the primary input button and then release it a short time later.
+    session.requestAnimationFrame((time, xrFrame) => {
+      console.log('frame 1 time=' + time);
+      input_source.startSelection();
+
+      session.requestAnimationFrame((time, xrFrame) => {
+        console.log('frame 2 time=' + time);
+        input_source.endSelection();
+
+        session.requestAnimationFrame((time, xrFrame) => {
+          console.log('frame 3 time=' + time);
+          // Need to process one more frame to allow select to propagate.
+          session.requestAnimationFrame((time, xrFrame) => {
+            console.log('frame 4 time=' + time);
+            session.dispatchEvent(watcherDone);
+          });
+        });
+      });
+    });
   });
+  return eventPromise;
 };
 
 xr_session_promise_test(
-  testName, testFunction, fakeDeviceInitParams, 'immersive-ar',
-    {requiredFeatures: ['dom-overlay-for-handheld-ar']});
+  "Ensures DOM Overlay feature works for immersive-ar",
+  testFunction.bind(this, document.body),
+  fakeDeviceInitParams, 'immersive-ar',
+    {requiredFeatures: ['dom-overlay-for-handheld-ar'],
+     domOverlay: { root: document.body } });
+
+xr_session_promise_test(
+  "Ensures DOM Overlay element selection works",
+  testFunction.bind(this, document.getElementById('div_overlay')),
+  fakeDeviceInitParams, 'immersive-ar', {
+    requiredFeatures: ['dom-overlay-for-handheld-ar'],
+    domOverlay: { root: document.getElementById('div_overlay') }
+  });
 
 </script>
diff --git a/third_party/ced/BUILD.gn b/third_party/ced/BUILD.gn
index cab0f309..cd0c02a8 100644
--- a/third_party/ced/BUILD.gn
+++ b/third_party/ced/BUILD.gn
@@ -43,9 +43,7 @@
     "src/util/string_util.h",
     "src/util/varsetter.h",
   ]
-  public = [
-    "src/compact_enc_det/compact_enc_det.h",
-  ]
+  public = [ "src/compact_enc_det/compact_enc_det.h" ]
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     "//build/config/compiler:no_chromium_code",
@@ -99,9 +97,7 @@
 }
 
 fuzzer_test("compact_enc_det_fuzzer") {
-  sources = [
-    "compact_enc_det_fuzzer.cc",
-  ]
+  sources = [ "compact_enc_det_fuzzer.cc" ]
   deps = [
     ":ced",
     "//base/test:test_support",
diff --git a/third_party/closure_compiler/compile_js.gni b/third_party/closure_compiler/compile_js.gni
index 8c10a56..9782717 100644
--- a/third_party/closure_compiler/compile_js.gni
+++ b/third_party/closure_compiler/compile_js.gni
@@ -60,19 +60,13 @@
                              "testonly",
                              "visibility",
                            ])
-    inputs = [
-      "$script_path/compiler.py",
-    ]
+    inputs = [ "$script_path/compiler.py" ]
     output_file = "$target_gen_dir/$target_name.js_library"
-    outputs = [
-      output_file,
-    ]
+    outputs = [ output_file ]
     args = [ "--output" ] + [ rebase_path(output_file, root_build_dir) ]
 
     if (!defined(sources)) {
-      sources = [
-        target_name + ".js",
-      ]
+      sources = [ target_name + ".js" ]
     }
 
     args += [ "--sources" ] + rebase_path(sources, root_build_dir)
@@ -176,16 +170,12 @@
     ]
 
     if (!defined(outputs)) {
-      outputs = [
-        "$target_gen_dir/$target_name.js",
-      ]
+      outputs = [ "$target_gen_dir/$target_name.js" ]
     }
     args += [ "--output" ] + rebase_path(outputs, root_build_dir)
 
     if (!defined(sources)) {
-      sources = [
-        "$target_name.js",
-      ]
+      sources = [ "$target_name.js" ]
     }
 
     if (defined(deps)) {
diff --git a/third_party/freetype/BUILD.gn b/third_party/freetype/BUILD.gn
index 9d0aafca..0dcf7742 100644
--- a/third_party/freetype/BUILD.gn
+++ b/third_party/freetype/BUILD.gn
@@ -63,9 +63,7 @@
 
   # FreeType only exposes ft2build.h, all other FreeType headers are accessed by macro names.
   # gn check does not expand macros, so list only this header.
-  public = [
-    "src/include/ft2build.h",
-  ]
+  public = [ "src/include/ft2build.h" ]
 
   sources = [
     "include/freetype-custom-config/ftconfig.h",
diff --git a/third_party/s2cellid/BUILD.gn b/third_party/s2cellid/BUILD.gn
index db13b4c..4bf071b 100644
--- a/third_party/s2cellid/BUILD.gn
+++ b/third_party/s2cellid/BUILD.gn
@@ -37,7 +37,5 @@
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
   public_configs = [ ":s2_config" ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/third_party/tcmalloc/BUILD.gn b/third_party/tcmalloc/BUILD.gn
index ea10b28..970b7a0 100644
--- a/third_party/tcmalloc/BUILD.gn
+++ b/third_party/tcmalloc/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/compiler/compiler.gni")
 
 executable("addr2line-pdb") {
-  sources = [
-    "chromium/src/windows/addr2line-pdb.c",
-  ]
+  sources = [ "chromium/src/windows/addr2line-pdb.c" ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
diff --git a/third_party/wayland/BUILD.gn b/third_party/wayland/BUILD.gn
index 7dfa302..68e2951 100644
--- a/third_party/wayland/BUILD.gn
+++ b/third_party/wayland/BUILD.gn
@@ -46,13 +46,9 @@
   }
 
   static_library("wayland_protocol") {
-    sources = [
-      "protocol/wayland-protocol.c",
-    ]
+    sources = [ "protocol/wayland-protocol.c" ]
 
-    deps = [
-      ":wayland_util",
-    ]
+    deps = [ ":wayland_util" ]
 
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
@@ -114,9 +110,7 @@
   }
 
   executable("wayland_scanner") {
-    sources = [
-      "src/src/scanner.c",
-    ]
+    sources = [ "src/src/scanner.c" ]
 
     deps = [
       ":wayland_util",
diff --git a/third_party/wayland/wayland_protocol.gni b/third_party/wayland/wayland_protocol.gni
index fc97aee..2639a7e 100644
--- a/third_party/wayland/wayland_protocol.gni
+++ b/third_party/wayland/wayland_protocol.gni
@@ -60,9 +60,7 @@
     } else {
       wayland_scanner_label =
           "//third_party/wayland:wayland_scanner($host_toolchain)"
-      deps = [
-        wayland_scanner_label,
-      ]
+      deps = [ wayland_scanner_label ]
       wayland_scanner_path = get_label_info(wayland_scanner_label,
                                             "root_out_dir") + "/wayland_scanner"
       cmd = "./" + rebase_path(wayland_scanner_path, root_build_dir)
diff --git a/third_party/zlib/google/BUILD.gn b/third_party/zlib/google/BUILD.gn
index 4024836..a628d2f 100644
--- a/third_party/zlib/google/BUILD.gn
+++ b/third_party/zlib/google/BUILD.gn
@@ -42,7 +42,5 @@
     "compression_utils_portable.cc",
     "compression_utils_portable.h",
   ]
-  deps = [
-    "//third_party/zlib",
-  ]
+  deps = [ "//third_party/zlib" ]
 }
diff --git a/tools/generate_stubs/rules.gni b/tools/generate_stubs/rules.gni
index aa69a7a..a69f8e5 100644
--- a/tools/generate_stubs/rules.gni
+++ b/tools/generate_stubs/rules.gni
@@ -32,9 +32,7 @@
   action("${target_name}__stubs_gen") {
     script = "//tools/generate_stubs/generate_stubs.py"
     sources = invoker.sigs
-    inputs = [
-      invoker.extra_header,
-    ]
+    inputs = [ invoker.extra_header ]
     outputs = [
       "${target_gen_dir}/${invoker.output_name}.cc",
       "${target_gen_dir}/${invoker.output_name}.h",
diff --git a/tools/json_to_struct/json_to_struct.gni b/tools/json_to_struct/json_to_struct.gni
index d923439..29afcb2 100644
--- a/tools/json_to_struct/json_to_struct.gni
+++ b/tools/json_to_struct/json_to_struct.gni
@@ -58,9 +58,7 @@
 
     sources = get_target_outputs(":$action_name")
 
-    deps = [
-      ":$action_name",
-    ]
+    deps = [ ":$action_name" ]
 
     if (defined(invoker.deps)) {
       deps += invoker.deps
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 9818660..00bfa2c 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -162,6 +162,10 @@
       'Dawn Win10 x64 DEPS Builder': 'dawn_tests_release_trybot',
     },
 
+    'chromium.devtools-frontend': {
+      'DevTools Linux (chromium)': 'release_trybot',
+    },
+
     'chromium.fuzz': {
       'ASAN Debug': 'asan_lsan_debug_bot',
       'ASAN Release Media': 'asan_lsan_fuzzer_v8_heap_chromeos_codecs_release_bot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 4028b292..46d346f0 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -6247,6 +6247,11 @@
   <int value="1" label="Cloned"/>
 </enum>
 
+<enum name="BooleanCloseJustCurrentTab">
+  <int value="0" label="Different behavior"/>
+  <int value="1" label="Closed just current tab"/>
+</enum>
+
 <enum name="BooleanCloseTimeout">
   <int value="0" label="Closed normally"/>
   <int value="1" label="Timed out"/>
@@ -6705,6 +6710,11 @@
   <int value="1" label="Foreground"/>
 </enum>
 
+<enum name="BooleanInScope">
+  <int value="0" label="Not in scope"/>
+  <int value="1" label="In scope"/>
+</enum>
+
 <enum name="BooleanInstalled">
   <int value="0" label="Not installed"/>
   <int value="1" label="Installed"/>
@@ -19114,6 +19124,7 @@
   <int value="656" label="ReportDeviceCpuInfo"/>
   <int value="657" label="DeviceLoginScreenPrimaryMouseButtonSwitch"/>
   <int value="658" label="PerAppTimeLimitsWhitelist"/>
+  <int value="659" label="AccessibilityShortcutsEnabled"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9d44acb..a504b6d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -29928,6 +29928,20 @@
   </summary>
 </histogram>
 
+<histogram name="CustomTabs.CloseButton.ChildTab.ScopeAlgorithm.ClosesOneTab"
+    enum="BooleanCloseJustCurrentTab" expires_after="2020-08-01">
+  <owner>hartmanng@chromium.org</owner>
+  <owner>peconn@chromium.org</owner>
+  <owner>pkotwicz@chromium.org</owner>
+  <summary>
+    Records whether the CustomTab/TrustedWebActivity &quot;navigate to landing
+    page&quot; algorithm for child tabs - e.g. tabs opened via window.open() -
+    produces the same behaviour (closes the current tab) as the webapp
+    &quot;close current tab&quot; algorithm. Recorded when the user clicks the
+    CustomTab/TrustedWebActivity close button on a child tab.
+  </summary>
+</histogram>
+
 <histogram name="CustomTabs.ConnectionStatusOnReturn.GSA"
     enum="CustomTabsConnection" expires_after="M83">
   <owner>nyquist@chromium.org</owner>
@@ -30285,8 +30299,8 @@
 </histogram>
 
 <histogram name="CustomTabs.SpeculationStatusOnStart"
-    enum="CustomTabsSpeculationStatusOnStart" expires_after="2020-01-26">
-  <owner>mattcary@chromium.org</owner>
+    enum="CustomTabsSpeculationStatusOnStart" expires_after="2020-07-26">
+  <owner>lizeb@chromium.org</owner>
   <summary>
     Recorded only for Android. How a speculation was started or why it was
     disallowed. This is recorded when a speculation of any kind is requested,
@@ -30300,8 +30314,8 @@
 </histogram>
 
 <histogram name="CustomTabs.SpeculationStatusOnSwap"
-    enum="CustomTabsSpeculationStatusOnSwap" expires_after="2020-01-26">
-  <owner>mattcary@chromium.org</owner>
+    enum="CustomTabsSpeculationStatusOnSwap" expires_after="2020-07-26">
+  <owner>lizeb@chromium.org</owner>
   <summary>
     Recorded only for Android. Recorded when a speculation is requesting to swap
     into a visible tab.
@@ -165562,6 +165576,18 @@
   </summary>
 </histogram>
 
+<histogram name="WebApk.Navigation.ChildTab.InScope" enum="BooleanInScope"
+    expires_after="2020-08-01">
+  <owner>hartmanng@chromium.org</owner>
+  <owner>peconn@chromium.org</owner>
+  <owner>pkotwicz@chromium.org</owner>
+  <summary>
+    Recorded each time that a child tab - e.g. a tab opened via window.open() -
+    is navigated. Records whether the navigation is within the scope of the
+    WebAPK's Web Manifest.
+  </summary>
+</histogram>
+
 <histogram name="WebApk.Navigation.InScope" enum="Boolean"
     expires_after="2020-04-01">
   <owner>hartmanng@chromium.org</owner>
@@ -165569,7 +165595,8 @@
   <owner>yfriedman@chromium.org</owner>
   <summary>
     Recorded each time that a WebAPK is navigated. Records whether the
-    navigation is within the scope of the WebAPK's Web Manifest.
+    navigation is within the scope of the WebAPK's Web Manifest. Not recorded
+    for child tabs - e.g. tabs opened via window.open()
   </summary>
 </histogram>
 
diff --git a/tools/traffic_annotation/summary/BUILD.gn b/tools/traffic_annotation/summary/BUILD.gn
index fb2029f..3d8f4e1 100644
--- a/tools/traffic_annotation/summary/BUILD.gn
+++ b/tools/traffic_annotation/summary/BUILD.gn
@@ -3,10 +3,6 @@
 # found in the LICENSE file.
 
 copy("annotations_xml") {
-  sources = [
-    "annotations.xml",
-  ]
-  outputs = [
-    "$target_out_dir/annotations.xml",
-  ]
+  sources = [ "annotations.xml" ]
+  outputs = [ "$target_out_dir/annotations.xml" ]
 }
diff --git a/tools/xdisplaycheck/BUILD.gn b/tools/xdisplaycheck/BUILD.gn
index 717c31a..1dc067c 100644
--- a/tools/xdisplaycheck/BUILD.gn
+++ b/tools/xdisplaycheck/BUILD.gn
@@ -3,9 +3,7 @@
 # found in the LICENSE file.
 
 executable("xdisplaycheck") {
-  sources = [
-    "xdisplaycheck.cc",
-  ]
+  sources = [ "xdisplaycheck.cc" ]
 
   configs += [ "//build/config/linux:x11" ]
 }
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 61cb4cb..be9ddc1 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -265,9 +265,7 @@
 executable("aura_demo") {
   testonly = true
 
-  sources = [
-    "demo/demo_main.cc",
-  ]
+  sources = [ "demo/demo_main.cc" ]
 
   deps = [
     ":aura",
@@ -342,9 +340,7 @@
     "//ui/wm",
   ]
 
-  data_deps = [
-    "//third_party/mesa_headers",
-  ]
+  data_deps = [ "//third_party/mesa_headers" ]
 }
 
 # This target is added as a dependency of browser interactive_ui_tests. It must
@@ -352,9 +348,7 @@
 source_set("aura_interactive_ui_tests") {
   testonly = true
   if (is_win) {
-    sources = [
-      "native_window_occlusion_tracker_win_interactive_test.cc",
-    ]
+    sources = [ "native_window_occlusion_tracker_win_interactive_test.cc" ]
 
     deps = [
       ":aura",
diff --git a/ui/base/clipboard/BUILD.gn b/ui/base/clipboard/BUILD.gn
index 0ef99650..8f70881 100644
--- a/ui/base/clipboard/BUILD.gn
+++ b/ui/base/clipboard/BUILD.gn
@@ -47,9 +47,7 @@
 
   defines = [ "IS_UI_BASE_CLIPBOARD_TYPES_IMPL" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   libs = []
   if (is_mac) {
@@ -111,9 +109,7 @@
     "//ui/gfx/geometry",
   ]
 
-  public_deps = [
-    ":clipboard_types",
-  ]
+  public_deps = [ ":clipboard_types" ]
 
   if (use_aura) {
     # Aura clipboard.
diff --git a/ui/base/resource/resource_bundle_ios.mm b/ui/base/resource/resource_bundle_ios.mm
index 5b1546f..1117868 100644
--- a/ui/base/resource/resource_bundle_ios.mm
+++ b/ui/base/resource/resource_bundle_ios.mm
@@ -165,8 +165,6 @@
     image = gfx::Image(ui_image);
   }
 
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
   auto inserted = images_.emplace(resource_id, image);
   DCHECK(inserted.second);
   return inserted.first->second;
diff --git a/ui/base/resource/resource_bundle_mac.mm b/ui/base/resource/resource_bundle_mac.mm
index cc95b28..6bd9d7a 100644
--- a/ui/base/resource/resource_bundle_mac.mm
+++ b/ui/base/resource/resource_bundle_mac.mm
@@ -137,8 +137,6 @@
     image = gfx::Image(ns_image);
   }
 
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
   auto inserted = images_.emplace(resource_id, image);
   DCHECK(inserted.second);
   return inserted.first->second;
diff --git a/ui/chromeos/BUILD.gn b/ui/chromeos/BUILD.gn
index 15899fa..8a5c1a3 100644
--- a/ui/chromeos/BUILD.gn
+++ b/ui/chromeos/BUILD.gn
@@ -79,10 +79,6 @@
     "//ui/views",
     "//ui/views:test_support",
   ]
-  data = [
-    "$root_out_dir/locales/en-US.pak",
-  ]
-  data_deps = [
-    "//ui/resources:ui_test_pak_data",
-  ]
+  data = [ "$root_out_dir/locales/en-US.pak" ]
+  data_deps = [ "//ui/resources:ui_test_pak_data" ]
 }
diff --git a/ui/events/devices/BUILD.gn b/ui/events/devices/BUILD.gn
index 1c76106..3eae4ed 100644
--- a/ui/events/devices/BUILD.gn
+++ b/ui/events/devices/BUILD.gn
@@ -77,9 +77,7 @@
 
 if (is_android) {
   generate_jni("ui_events_devices_jni_headers") {
-    sources = [
-      "../../android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java",
-    ]
+    sources = [ "../../android/java/src/org/chromium/ui/events/devices/InputDeviceObserver.java" ]
   }
 }
 
@@ -89,11 +87,7 @@
     "device_data_manager_test_api.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
-  public_deps = [
-    ":devices",
-  ]
+  public_deps = [ ":devices" ]
 }
diff --git a/ui/events/platform/x11/BUILD.gn b/ui/events/platform/x11/BUILD.gn
index 3fd7f2aa..2fa71d2f 100644
--- a/ui/events/platform/x11/BUILD.gn
+++ b/ui/events/platform/x11/BUILD.gn
@@ -33,9 +33,7 @@
     "//ui/gfx/x",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   if (is_chromeos) {
     deps += [ "//ui/events/ozone" ]
diff --git a/ui/events/types/BUILD.gn b/ui/events/types/BUILD.gn
index 015c681..ee32d7a 100644
--- a/ui/events/types/BUILD.gn
+++ b/ui/events/types/BUILD.gn
@@ -3,7 +3,5 @@
 # found in the LICENSE file.
 
 source_set("headers") {
-  sources = [
-    "scroll_types.h",
-  ]
+  sources = [ "scroll_types.h" ]
 }
diff --git a/ui/file_manager/base/gn/js_test_gen_html.gni b/ui/file_manager/base/gn/js_test_gen_html.gni
index 2131b27..cfc27c04 100644
--- a/ui/file_manager/base/gn/js_test_gen_html.gni
+++ b/ui/file_manager/base/gn/js_test_gen_html.gni
@@ -77,9 +77,7 @@
       sources += get_target_outputs(dep)
     }
 
-    outputs = [
-      "$target_gen_dir/{{source_name_part}}_gen.html",
-    ]
+    outputs = [ "$target_gen_dir/{{source_name_part}}_gen.html" ]
     args = [ "--output" ] + rebase_path(outputs, root_build_dir)
     args += [
       "--src_path",
@@ -108,9 +106,7 @@
     js_type_check(type_check_target_name) {
       testonly = true
       forward_variables_from(invoker, [ "closure_flags" ])
-      deps = [
-        dep,
-      ]
+      deps = [ dep ]
     }
   }
   type_check_group_name = target_name + "_type_check_auto"
@@ -121,8 +117,6 @@
   group(target_name) {
     data = get_target_outputs(":$html_gen_target_name")
     testonly = true
-    deps = [
-      ":$html_gen_target_name",
-    ]
+    deps = [ ":$html_gen_target_name" ]
   }
 }
diff --git a/ui/file_manager/base/js/BUILD.gn b/ui/file_manager/base/js/BUILD.gn
index c86b84b..07c4ba12 100644
--- a/ui/file_manager/base/js/BUILD.gn
+++ b/ui/file_manager/base/js/BUILD.gn
@@ -82,9 +82,7 @@
 }
 
 js_test_gen_html("js_test_gen_html") {
-  deps = [
-    ":volume_manager_types_unittest",
-  ]
+  deps = [ ":volume_manager_types_unittest" ]
 }
 
 js_library("mediasession_types") {
diff --git a/ui/file_manager/gallery/js/BUILD.gn b/ui/file_manager/gallery/js/BUILD.gn
index 471e4906..e854367e 100644
--- a/ui/file_manager/gallery/js/BUILD.gn
+++ b/ui/file_manager/gallery/js/BUILD.gn
@@ -68,9 +68,7 @@
 }
 
 js_library("error_banner") {
-  deps = [
-    "//ui/file_manager/file_manager/common/js:util",
-  ]
+  deps = [ "//ui/file_manager/file_manager/common/js:util" ]
 }
 
 js_library("gallery") {
@@ -130,9 +128,7 @@
 }
 
 js_library("gallery_metrics") {
-  deps = [
-    "//ui/file_manager/file_manager/common/js:metrics_base",
-  ]
+  deps = [ "//ui/file_manager/file_manager/common/js:metrics_base" ]
 }
 
 js_library("gallery_util") {
@@ -179,9 +175,7 @@
 }
 
 js_unittest("ribbon_unittest") {
-  deps = [
-    ":ribbon",
-  ]
+  deps = [ ":ribbon" ]
 }
 
 js_library("slide_mode") {
diff --git a/ui/file_manager/gallery/js/image_editor/BUILD.gn b/ui/file_manager/gallery/js/image_editor/BUILD.gn
index c426567..0467e35 100644
--- a/ui/file_manager/gallery/js/image_editor/BUILD.gn
+++ b/ui/file_manager/gallery/js/image_editor/BUILD.gn
@@ -58,9 +58,7 @@
 }
 
 js_library("filter") {
-  deps = [
-    ":image_util",
-  ]
+  deps = [ ":image_util" ]
 }
 
 js_library("image_adjust") {
@@ -98,9 +96,7 @@
 }
 
 js_library("image_editor_prompt") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
 }
 
 js_library("image_editor_toolbar") {
@@ -162,9 +158,7 @@
 }
 
 js_library("image_util") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
 }
 
 js_library("image_view") {
diff --git a/ui/gfx/mojom/BUILD.gn b/ui/gfx/mojom/BUILD.gn
index 0a8a74c..47dc1bc 100644
--- a/ui/gfx/mojom/BUILD.gn
+++ b/ui/gfx/mojom/BUILD.gn
@@ -33,11 +33,7 @@
 }
 
 mojom("test_interfaces") {
-  sources = [
-    "traits_test_service.mojom",
-  ]
+  sources = [ "traits_test_service.mojom" ]
 
-  public_deps = [
-    ":mojom",
-  ]
+  public_deps = [ ":mojom" ]
 }
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn
index 5e7f7b64..42bcefc 100644
--- a/ui/webui/resources/js/BUILD.gn
+++ b/ui/webui/resources/js/BUILD.gn
@@ -72,21 +72,15 @@
 }
 
 js_library("i18n_template_no_process") {
-  deps = [
-    ":load_time_data",
-  ]
+  deps = [ ":load_time_data" ]
 }
 
 js_library("i18n_template") {
-  deps = [
-    ":i18n_template_no_process",
-  ]
+  deps = [ ":i18n_template_no_process" ]
 }
 
 js_library("i18n_behavior") {
-  deps = [
-    ":load_time_data",
-  ]
+  deps = [ ":load_time_data" ]
 }
 
 js_library("list_property_update_behavior") {
@@ -104,22 +98,16 @@
 }
 
 js_library("promise_resolver") {
-  deps = [
-    ":assert",
-  ]
+  deps = [ ":assert" ]
 }
 
 js_library("util") {
-  deps = [
-    ":cr",
-  ]
+  deps = [ ":cr" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
 js_library("web_ui_listener_behavior") {
-  deps = [
-    ":cr",
-  ]
+  deps = [ ":cr" ]
 }
 
 js_library("webui_resource_test") {
@@ -157,9 +145,7 @@
     "cr.ui.KeyboardShortcutList|KeyboardShortcutList",
     "Polymer.ArraySplice.calculateSplices|calculateSplices",
   ]
-  deps = [
-    "cr:modulize",
-  ]
+  deps = [ "cr:modulize" ]
 }
 
 group("closure_compile_modules") {
@@ -189,9 +175,7 @@
 }
 
 js_library("assert.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/assert.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/assert.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
@@ -204,16 +188,13 @@
 }
 
 js_library("event_tracker.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/event_tracker.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/event_tracker.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("find_shortcut_behavior.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/find_shortcut_behavior.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/js/find_shortcut_behavior.m.js" ]
   deps = [
     ":assert.m",
     ":cr.m",
@@ -224,19 +205,13 @@
 }
 
 js_library("icon.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/icon.m.js",
-  ]
-  deps = [
-    ":cr.m",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/icon.m.js" ]
+  deps = [ ":cr.m" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("i18n_behavior.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/i18n_behavior.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/i18n_behavior.m.js" ]
   deps = [
     ":load_time_data.m",
     ":parse_html_subset.m",
@@ -255,9 +230,7 @@
 }
 
 js_library("load_time_data.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/load_time_data.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/load_time_data.m.js" ]
   deps = [
     ":assert.m",
     ":parse_html_subset.m",
@@ -267,36 +240,25 @@
 }
 
 js_library("parse_html_subset.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/parse_html_subset.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/parse_html_subset.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("promise_resolver.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/promise_resolver.m.js",
-  ]
-  deps = [
-    ":assert.m",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/promise_resolver.m.js" ]
+  deps = [ ":assert.m" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("search_highlight_utils.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/search_highlight_utils.m.js",
-  ]
-  deps = [
-    ":assert.m",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/js/search_highlight_utils.m.js" ]
+  deps = [ ":assert.m" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("util.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/util.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/util.m.js" ]
   deps = [
     ":assert.m",
     ":cr.m",
@@ -306,11 +268,8 @@
 }
 
 js_library("web_ui_listener_behavior.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/web_ui_listener_behavior.m.js",
-  ]
-  deps = [
-    ":cr.m",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/js/web_ui_listener_behavior.m.js" ]
+  deps = [ ":cr.m" ]
   extra_deps = [ ":modulize" ]
 }
diff --git a/ui/webui/resources/js/cr/BUILD.gn b/ui/webui/resources/js/cr/BUILD.gn
index 7805bd1..d68bb45 100644
--- a/ui/webui/resources/js/cr/BUILD.gn
+++ b/ui/webui/resources/js/cr/BUILD.gn
@@ -14,33 +14,23 @@
 
 js_type_check("closure_compile_modules") {
   uses_js_modules = true
-  deps = [
-    ":event_target.m",
-  ]
+  deps = [ ":event_target.m" ]
 }
 
 js_library("event_target") {
-  deps = [
-    "..:cr",
-  ]
+  deps = [ "..:cr" ]
 }
 
 js_library("ui") {
-  deps = [
-    "..:cr",
-  ]
+  deps = [ "..:cr" ]
 }
 
 js_library("event_target.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/event_target.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/cr/event_target.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_modulizer("modulize") {
   input_files = [ "event_target.js" ]
-  deps = [
-    "ui:modulize",
-  ]
+  deps = [ "ui:modulize" ]
 }
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn
index 560fd9db..5db8d24 100644
--- a/ui/webui/resources/js/cr/ui/BUILD.gn
+++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -83,15 +83,11 @@
 }
 
 js_library("dialogs") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("drag_wrapper") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("focus_grid") {
@@ -103,15 +99,11 @@
 }
 
 js_library("focus_manager") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("focus_outline_manager") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("focus_row_behavior") {
@@ -138,15 +130,11 @@
 }
 
 js_library("grid") {
-  deps = [
-    ":list",
-  ]
+  deps = [ ":list" ]
 }
 
 js_library("keyboard_shortcut_list") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("list") {
@@ -159,9 +147,7 @@
 }
 
 js_library("list_item") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("list_selection_controller") {
@@ -223,9 +209,7 @@
 }
 
 js_library("position_util") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("splitter") {
@@ -236,9 +220,7 @@
 }
 
 js_library("store") {
-  deps = [
-    "../..:cr",
-  ]
+  deps = [ "../..:cr" ]
 }
 
 js_library("store_client") {
@@ -304,16 +286,12 @@
 }
 
 js_library("drag_wrapper.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/drag_wrapper.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/cr/ui/drag_wrapper.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("focus_grid.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_grid.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_grid.m.js" ]
   deps = [
     ":focus_row.m",
     "../..:assert.m",
@@ -322,9 +300,8 @@
 }
 
 js_library("focus_outline_manager.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_outline_manager.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_outline_manager.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
@@ -334,9 +311,7 @@
     "../..:event_tracker.m",
     "../..:util.m",
   ]
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_row.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_row.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
@@ -347,9 +322,8 @@
     "../..:assert.m",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_row_behavior.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_row_behavior.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
@@ -358,9 +332,8 @@
     "../..:assert.m",
     "../..:cr.m",
   ]
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_without_ink.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/js/cr/ui/focus_without_ink.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
@@ -372,9 +345,7 @@
 }
 
 js_library("store.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/store.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/cr/ui/store.m.js" ]
   extra_deps = [ ":modulize" ]
 }
 
@@ -383,8 +354,6 @@
     ":store.m",
     "../..:assert.m",
   ]
-  sources = [
-    "$root_gen_dir/ui/webui/resources/js/cr/ui/store_client.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/js/cr/ui/store_client.m.js" ]
   extra_deps = [ ":modulize" ]
 }
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index e38b8b9..aa90280 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -195,14 +195,12 @@
     "//components/embedder_support:switches",
     "//components/network_time",
     "//components/prefs",
-    "//components/resources",
     "//components/security_interstitials/content:security_interstitial_page",
     "//components/security_interstitials/content/renderer:security_interstitial_page_controller",
     "//components/security_interstitials/core",
     "//components/spellcheck:buildflags",
     "//components/ssl_errors",
     "//components/startup_metric_utils/browser",
-    "//components/strings",
     "//components/user_prefs",
     "//components/version_info",
     "//components/web_cache/browser",
@@ -261,6 +259,8 @@
     deps += [
       "//android_webview:generate_aw_resources",
       "//android_webview:generate_aw_strings",
+      "//components/android_system_error_page",
+      "//components/autofill/android:provider",
       "//components/crash/android:crashpad_main",
       "//components/metrics",
       "//components/minidump_uploader",
diff --git a/weblayer/browser/DEPS b/weblayer/browser/DEPS
index 09f1972..d327d60 100644
--- a/weblayer/browser/DEPS
+++ b/weblayer/browser/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+cc",
+  "+components/autofill/android",
   "+components/autofill/content/browser",
   "+components/autofill/core/browser",
   "+components/autofill/core/common",
diff --git a/weblayer/browser/OWNERS b/weblayer/browser/OWNERS
index c814729..3608fa4 100644
--- a/weblayer/browser/OWNERS
+++ b/weblayer/browser/OWNERS
@@ -1,6 +1,4 @@
-per-file weblayer_content_browser_overlay_manifest.cc=set noparent
-per-file weblayer_content_browser_overlay_manifest.cc=file://ipc/SECURITY_OWNERS
-per-file weblayer_content_browser_overlay_manifest.h=set noparent
-per-file weblayer_content_browser_overlay_manifest.h=file://ipc/SECURITY_OWNERS
-per-file weblayer_browser_interface_binders.cc=set noparent
-per-file weblayer_browser_interface_binders.cc=file://ipc/SECURITY_OWNERS
+per-file weblayer_content_browser_overlay_manifest.*=set noparent
+per-file weblayer_content_browser_overlay_manifest.*=file://ipc/SECURITY_OWNERS
+per-file weblayer_browser_interface_binders.*=set noparent
+per-file weblayer_browser_interface_binders.*=file://ipc/SECURITY_OWNERS
diff --git a/weblayer/browser/autofill_browsertest.cc b/weblayer/browser/autofill_browsertest.cc
index 870b935..15cb638 100644
--- a/weblayer/browser/autofill_browsertest.cc
+++ b/weblayer/browser/autofill_browsertest.cc
@@ -7,9 +7,11 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "weblayer/browser/tab_impl.h"
 #include "weblayer/shell/browser/shell.h"
 #include "weblayer/test/weblayer_browser_test_utils.h"
 
@@ -42,6 +44,14 @@
   AutofillBrowserTest() = default;
   ~AutofillBrowserTest() override = default;
 
+  void SetUp() override {
+#if defined(OS_ANDROID)
+    TabImpl::DisableAutofillSystemIntegrationForTesting();
+#endif
+
+    WebLayerBrowserTest::SetUp();
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(AutofillBrowserTest);
 };
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index 0b5f26d..8b265bfe 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -63,6 +63,7 @@
     ":weblayer_resources",
     "//base:base_java",
     "//base:jni_java",
+    "//components/autofill/android:provider_java",
     "//components/crash/android:handler_java",
     "//components/crash/android:java",
     "//components/embedder_support/android:application_java",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java
index abda363..d552bb42 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java
@@ -98,6 +98,15 @@
                     new WebContentsGestureStateTracker(mContentView, webContents, this);
         }
         mContentView.setWebContents(webContents);
+
+        if (mTab != null) {
+            // Now that |mContentView| is associated with this Tab's WebContents,
+            // associate |mContentView| with this Tab's AutofillProvider as well.
+            mContentView.setAutofillProvider(mTab.getAutofillProvider());
+        } else {
+            mContentView.setAutofillProvider(null);
+        }
+
         mContentViewRenderView.setWebContents(webContents);
         mTopControlsContainerView.setWebContents(webContents);
         if (mTab != null) {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ContentView.java b/weblayer/browser/java/org/chromium/weblayer_private/ContentView.java
index 65ff96fd0..45552f54 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ContentView.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ContentView.java
@@ -10,6 +10,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.util.SparseArray;
 import android.view.DragEvent;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -18,6 +19,7 @@
 import android.view.ViewGroup.OnHierarchyChangeListener;
 import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.autofill.AutofillValue;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.FrameLayout;
@@ -25,6 +27,7 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.compat.ApiHelperForO;
+import org.chromium.components.autofill.AutofillProvider;
 import org.chromium.content_public.browser.ImeAdapter;
 import org.chromium.content_public.browser.RenderCoordinates;
 import org.chromium.content_public.browser.SmartClipProvider;
@@ -48,6 +51,7 @@
             MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
 
     private WebContents mWebContents;
+    private AutofillProvider mAutofillProvider;
     private final ObserverList<OnHierarchyChangeListener> mHierarchyChangeListeners =
             new ObserverList<>();
     private final ObserverList<OnSystemUiVisibilityChangeListener> mSystemUiChangeListeners =
@@ -71,6 +75,9 @@
      */
     public static ContentView createContentView(
             Context context, EventOffsetHandler eventOffsetHandler) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            return new ContentViewApi26(context, eventOffsetHandler);
+        }
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             return new ContentViewApi23(context, eventOffsetHandler);
         }
@@ -102,6 +109,16 @@
 
         setOnHierarchyChangeListener(this);
         setOnSystemUiVisibilityChangeListener(this);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            // The Autofill system-level infrastructure has heuristics for which Views it considers
+            // important for autofill; only these Views will be queried for their autofill
+            // structure on notifications that a new (virtual) View was entered. By default,
+            // FrameLayout is not considered important for autofill. Thus, for ContentView to be
+            // queried for its autofill structure, we must explicitly inform the autofill system
+            // that this View is important for autofill.
+            setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
+        }
     }
 
     protected WebContentsAccessibility getWebContentsAccessibility() {
@@ -110,6 +127,10 @@
                 : null;
     }
 
+    protected AutofillProvider getAutofillProvider() {
+        return mAutofillProvider;
+    }
+
     public void setWebContents(WebContents webContents) {
         boolean wasFocused = isFocused();
         boolean wasWindowFocused = hasWindowFocus();
@@ -123,6 +144,10 @@
         if (wasAttached) onAttachedToWindow();
     }
 
+    public void setAutofillProvider(AutofillProvider autofillProvider) {
+        mAutofillProvider = autofillProvider;
+    }
+
     @Override
     public boolean performAccessibilityAction(int action, Bundle arguments) {
         WebContentsAccessibility wcax = getWebContentsAccessibility();
@@ -487,4 +512,32 @@
             if (wcax != null) wcax.onProvideVirtualStructure(structure, false);
         }
     }
+
+    private static class ContentViewApi26 extends ContentViewApi23 {
+        public ContentViewApi26(Context context, EventOffsetHandler eventOffsetHandler) {
+            super(context, eventOffsetHandler);
+        }
+
+        @Override
+        public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
+            // A new (virtual) View has been entered, and the autofill system-level
+            // infrastructure wants us to populate |structure| with the autofill structure of the
+            // (virtual) View. Forward this on to AutofillProvider to accomplish.
+            AutofillProvider autofillProvider = getAutofillProvider();
+            if (autofillProvider != null) {
+                autofillProvider.onProvideAutoFillVirtualStructure(structure, flags);
+            }
+        }
+
+        @Override
+        public void autofill(final SparseArray<AutofillValue> values) {
+            // The autofill system-level infrastructure has information that we can use to
+            // autofill the current (virtual) View. Forward this on to AutofillProvider to
+            // accomplish.
+            AutofillProvider autofillProvider = getAutofillProvider();
+            if (autofillProvider != null) {
+                autofillProvider.autofill(values);
+            }
+        }
+    }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
index 4af8dbc..e44b149 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
@@ -4,6 +4,7 @@
 
 package org.chromium.weblayer_private;
 
+import android.os.Build;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.webkit.ValueCallback;
@@ -12,6 +13,8 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
+import org.chromium.components.autofill.AutofillProvider;
+import org.chromium.components.autofill.AutofillProviderImpl;
 import org.chromium.content_public.browser.SelectionPopupController;
 import org.chromium.content_public.browser.ViewEventSink;
 import org.chromium.content_public.browser.WebContents;
@@ -45,6 +48,11 @@
     private ViewAndroidDelegate mViewAndroidDelegate;
     // BrowserImpl this TabImpl is in. This is only null during creation.
     private BrowserImpl mBrowser;
+    /**
+     * The AutofillProvider that integrates with system-level autofill. This is null until
+     * updateFromBrowser() is invoked.
+     */
+    private AutofillProvider mAutofillProvider;
     private NewTabCallbackProxy mNewTabCallbackProxy;
     private ITabClient mClient;
     private final int mId;
@@ -123,6 +131,21 @@
     public void updateFromBrowser() {
         mWebContents.setTopLevelNativeWindow(mBrowser.getWindowAndroid());
         mViewAndroidDelegate.setContainerView(mBrowser.getViewAndroidDelegateContainerView());
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            if (mBrowser.getContext() == null) {
+                // The Context and ViewContainer in which Autofill was previously operating have
+                // gone away, so tear down |mAutofillProvider|.
+                mAutofillProvider = null;
+            } else {
+                // Set up |mAutofillProvider| to operate in the new Context.
+                mAutofillProvider = new AutofillProviderImpl(
+                        mBrowser.getContext(), mBrowser.getViewAndroidDelegateContainerView());
+                mAutofillProvider.setWebContents(mWebContents);
+            }
+
+            TabImplJni.get().onAutofillProviderChanged(mNativeTab, mAutofillProvider);
+        }
     }
 
     public BrowserImpl getBrowser() {
@@ -168,6 +191,10 @@
         return mWebContents;
     }
 
+    public AutofillProvider getAutofillProvider() {
+        return mAutofillProvider;
+    }
+
     long getNativeTab() {
         return mNativeTab;
     }
@@ -293,6 +320,7 @@
     interface Natives {
         long createTab(long profile, TabImpl caller);
         void setJavaImpl(long nativeTabImpl, TabImpl impl);
+        void onAutofillProviderChanged(long nativeTabImpl, AutofillProvider autofillProvider);
         void setTopControlsContainerView(
                 long nativeTabImpl, TabImpl caller, long nativeTopControlsContainerView);
         void deleteTab(long tab);
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc
index cdad274..1c32168 100644
--- a/weblayer/browser/tab_impl.cc
+++ b/weblayer/browser/tab_impl.cc
@@ -39,6 +39,7 @@
 #include "base/android/jni_string.h"
 #include "base/json/json_writer.h"
 #include "base/trace_event/trace_event.h"
+#include "components/autofill/android/autofill_provider_android.h"
 #include "components/embedder_support/android/delegate/color_chooser_android.h"
 #include "weblayer/browser/java/jni/TabImpl_jni.h"
 #include "weblayer/browser/top_controls_container_view.h"
@@ -61,6 +62,9 @@
 
   return base::TimeDelta::FromSeconds(3);
 }
+
+bool g_system_autofill_disabled_for_testing = false;
+
 #endif
 
 NewTabType NewTabTypeFromWindowDisposition(WindowOpenDisposition disposition) {
@@ -232,6 +236,11 @@
 #endif
 
 #if defined(OS_ANDROID)
+// static
+void TabImpl::DisableAutofillSystemIntegrationForTesting() {
+  g_system_autofill_disabled_for_testing = true;
+}
+
 static jlong JNI_TabImpl_CreateTab(
     JNIEnv* env,
     jlong profile,
@@ -276,6 +285,30 @@
   java_impl_ = impl;
 }
 
+void TabImpl::OnAutofillProviderChanged(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& autofill_provider) {
+  if (g_system_autofill_disabled_for_testing)
+    return;
+
+  if (!autofill_provider_) {
+    // The first invocation should be when instantiating the autofill
+    // infrastructure, at which point the Java-side object should not be null.
+    DCHECK(autofill_provider);
+
+    // Initialize the native side of the autofill infrastructure.
+    autofill_provider_ = std::make_unique<autofill::AutofillProviderAndroid>(
+        autofill_provider, web_contents_.get());
+    InitializeAutofill();
+    return;
+  }
+
+  // The AutofillProvider Java object has been changed; inform
+  // |autofill_provider_|.
+  auto* provider =
+      static_cast<autofill::AutofillProviderAndroid*>(autofill_provider_.get());
+  provider->OnJavaAutofillProviderChanged(env, autofill_provider);
+}
 #endif
 
 content::WebContents* TabImpl::OpenURLFromTab(
@@ -470,6 +503,8 @@
 
 void TabImpl::InitializeAutofillForTests(
     std::unique_ptr<autofill::AutofillProvider> provider) {
+  DCHECK(!autofill_provider_);
+
   autofill_provider_ = std::move(provider);
   InitializeAutofill();
 }
diff --git a/weblayer/browser/tab_impl.h b/weblayer/browser/tab_impl.h
index a10af73..d624c765 100644
--- a/weblayer/browser/tab_impl.h
+++ b/weblayer/browser/tab_impl.h
@@ -63,6 +63,13 @@
   bool has_new_tab_delegate() const { return new_tab_delegate_ != nullptr; }
 
 #if defined(OS_ANDROID)
+  // Call this method to disable integration with the system-level Autofill
+  // infrastructure. Useful in conjunction with InitializeAutofillForTests().
+  // Should be called early in the lifetime of WebLayer, and in
+  // particular, must be called before the TabImpl is attached to the browser
+  // on the Java side to have the desired effect.
+  static void DisableAutofillSystemIntegrationForTesting();
+
   base::android::ScopedJavaLocalRef<jobject> GetWebContents(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
@@ -76,6 +83,15 @@
                      const base::android::JavaParamRef<jobject>& callback);
   void SetJavaImpl(JNIEnv* env,
                    const base::android::JavaParamRef<jobject>& impl);
+
+  // Invoked every time that the Java-side AutofillProvider instance is
+  // changed (set to null or to a new object). On first invocation with a non-
+  // null object initializes the native Autofill infrastructure. On
+  // subsequent invocations updates the association of that native
+  // infrastructure with its Java counterpart.
+  void OnAutofillProviderChanged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& autofill_provider);
 #endif
 
   DownloadDelegate* download_delegate() { return download_delegate_; }
diff --git a/weblayer/renderer/DEPS b/weblayer/renderer/DEPS
index 564d187..db14602d 100644
--- a/weblayer/renderer/DEPS
+++ b/weblayer/renderer/DEPS
@@ -1,12 +1,11 @@
 include_rules = [
+  "+components/android_system_error_page",
   "+components/autofill/content/renderer",
-  "+components/grit",
   "+components/safe_browsing/content/renderer",
   "+components/safe_browsing/core/common",
   "+components/security_interstitials/content/renderer",
   "+components/security_interstitials/core/common",
   "+components/spellcheck/renderer",
-  "+components/strings",
   "+content/public/renderer",
   # needed for safebrowsing
   "+mojo/public/cpp/bindings",
diff --git a/weblayer/renderer/content_renderer_client_impl.cc b/weblayer/renderer/content_renderer_client_impl.cc
index 96ab66c4d..e23fb98 100644
--- a/weblayer/renderer/content_renderer_client_impl.cc
+++ b/weblayer/renderer/content_renderer_client_impl.cc
@@ -5,25 +5,19 @@
 #include "weblayer/renderer/content_renderer_client_impl.h"
 
 #include "base/feature_list.h"
-#include "base/i18n/rtl.h"
-#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "components/autofill/content/renderer/autofill_agent.h"
 #include "components/autofill/content/renderer/password_autofill_agent.h"
 #include "content/public/renderer/render_thread.h"
-#include "net/base/escape.h"
 #include "third_party/blink/public/platform/platform.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "weblayer/common/features.h"
 #include "weblayer/renderer/ssl_error_helper.h"
 #include "weblayer/renderer/weblayer_render_frame_observer.h"
 
 #if defined(OS_ANDROID)
-#include "components/grit/components_resources.h"
+#include "components/android_system_error_page/error_page_populator.h"
 #include "components/spellcheck/renderer/spellcheck.h"           // nogncheck
 #include "components/spellcheck/renderer/spellcheck_provider.h"  // nogncheck
-#include "components/strings/grit/components_strings.h"
 #include "content/public/renderer/render_thread.h"
 #include "services/service_manager/public/cpp/local_interface_provider.h"
 #include "weblayer/renderer/url_loader_throttle_provider.h"
@@ -34,60 +28,6 @@
 namespace {
 
 #if defined(OS_ANDROID)
-constexpr char kThrottledErrorDescription[] =
-    "Request throttled. Visit http://dev.chromium.org/throttling for more "
-    "information.";
-
-// Populates |error_html| (if it is not null), based on |error|.
-// NOTE: This function is taken from
-// AWContentRendererClient::PrepareErrorPage().
-// TODO(1024326): If this implementation becomes the long-term
-// implementation, this code should be shared rather than copied.
-void PopulateErrorPageHTML(const blink::WebURLError& error,
-                           std::string* error_html) {
-  std::string err;
-  if (error.reason() == net::ERR_TEMPORARILY_THROTTLED)
-    err = kThrottledErrorDescription;
-  else
-    err = net::ErrorToString(error.reason());
-
-  if (!error_html)
-    return;
-
-  // Create the error page based on the error reason.
-  GURL gurl(error.url());
-  std::string url_string = gurl.possibly_invalid_spec();
-  int reason_id = IDS_ANDROID_ERROR_PAGE_WEBPAGE_CAN_NOT_BE_LOADED;
-
-  if (err.empty())
-    reason_id = IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN;
-
-  std::string escaped_url = net::EscapeForHTML(url_string);
-  std::vector<std::string> replacements;
-  replacements.push_back(
-      l10n_util::GetStringUTF8(IDS_ANDROID_ERROR_PAGE_WEBPAGE_NOT_AVAILABLE));
-  replacements.push_back(
-      l10n_util::GetStringFUTF8(reason_id, base::UTF8ToUTF16(escaped_url)));
-
-  // Having chosen the base reason, chose what extra information to add.
-  if (reason_id == IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN) {
-    replacements.push_back(l10n_util::GetStringUTF8(
-        IDS_ANDROID_ERROR_PAGE_WEBPAGE_TEMPORARILY_DOWN_SUGGESTIONS));
-  } else {
-    replacements.push_back(err);
-  }
-  if (base::i18n::IsRTL())
-    replacements.push_back("direction: rtl;");
-  else
-    replacements.push_back("");
-  *error_html = base::ReplaceStringPlaceholders(
-      ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
-          IDR_ANDROID_ERROR_PAGE_LOAD_ERROR_HTML),
-      replacements, nullptr);
-}
-#endif  // OS_ANDROID
-
-#if defined(OS_ANDROID)
 class SpellcheckInterfaceProvider
     : public service_manager::LocalInterfaceProvider {
  public:
@@ -160,7 +100,7 @@
     ssl_helper->PrepareErrorPage();
 
 #if defined(OS_ANDROID)
-  PopulateErrorPageHTML(error, error_html);
+  android_system_error_page::PopulateErrorPageHtml(error, error_html);
 #endif
 }